The Reason For Java's Staying Power: It's Easy To Read
jfruh writes: Java made its public debut twenty years ago today, and despite a sometimes bumpy history that features its parent company being absorbed by Oracle, it's still widely used. Mark Reinhold, chief architect for the Oracle's Java platform group, offers one explanation for its continuing popularity: it's easy for humans to understand it at a glance. "It is pretty easy to read Java code and figure out what it means. There aren't a lot of obscure gotchas in the language ... Most of the cost of maintaining any body of code over time is in maintenance, not in initial creation."
Easy to read? The author must have never seen code in the wild, especially from asia.
Java is a general purpose language that can do anything.... badly.
Not only do you have to re-learn basic elements every decade, you might have to rewrite very old code to work on current systems.
The people who make these incompatible changes vastly underestimate the cost of such incompatibilities.
The sheer amount of working Java code is not only why the language will stay around for a long time, but economically represents a very large amount of wealth.
I'll see your senator, and I'll raise you two judges.
That would make sense, but the system I am referring to doesn't. There is a "Q" class, but it is not a queue. I don't think the people who wrote this know what a queue is. Took us a while to figure out that "rlogic" was the actions initiated from the right side of the screen. Doesn't tell us what they do, but it made some sense. The amazing thing is the system works, even if we don't know what the parts do. The naming standards look more like algebra than Java. We think the whole system must be trying to solve for "x".
BTW, in case you haven't noticed, Python syntax is similar to Fortran syntax which is among the oldest, if not the oldest programming language still alive.
This. I think Fortran (and now Julia) strikes the best balance, because it doesn't have the tab/space issue that may produce problems, especially when sharing code. Like Python, it lacks the ugly {} ; punctuations, but it needs something to denote the end of a block, so it uses the English word "end" to keep things simple and clean.
Escher was the first MC and Giger invented the HR department.
Readability goes along with 'toolability'. The fact that tools can 'understand' Java code and therefore can correctly make so many kinds of automated changes to the source code is a major sign of readability. If it is not possible to make tools that can do precise and sophisticated manipulations of the source code, then chances are that humans cannot understand it easily.
As an example of what I mean by 'toolable'. When I rename a variable in Java, every instance of that variable throughout the entire project are changed. This is not a dumb 'search and replace'. It is a precise change made by tools that use most of the Java compiler front end in order to make these changes. Similarly if I rename a method, the change is precisely made throughout the source code. It doesn't matter if there is a variable, or a class or even another method elsewhere with the same name, there can be no possible confusion. Just as the compiler has no confusion about what identifier 'foo' in some line of code refers to, the renaming and refactoring processes are equally precise. That is what is meant by toolable.
I'll see your senator, and I'll raise you two judges.
I agree with this guy. Java forces you to acknowledge and address subtle differences between different types of objects. Yes, sometimes code is overly verbose, but overly compact code that does a lot of "magic" for you, is far worse. I unfortunately work in PHP a lot, and you can pretty much treat any value as any type and usually get away with it, until you suddenly don't. Strong typing and an IDE that whacks you with a stick every time you forget it, is far preferable, even if your code is a few lines longer.
Like most people I thought pythons enforced white space and avoidance of braces and elimination of semicolons was constricting. Then I realized how easy it was to read other people programs. Python used to be even simpler to read when it only provided one idioms for one job (avoiding a dozen way to do the same thing resulting in dialects). Now it's adding new idioms and genres so it's a little more opaque. But it's still easier to read than any language with comparable expressiveness. (Lua is refreshing for similar reasons).
Some drink at the fountain of knowledge. Others just gargle.
I'd agree with the ecosystem being a huge factor in Java's success.
More than that, it is a relatively closed ecosystem. Tools like JNI are available, but in practice few projects seem to use them. Mostly, either you're working in JVM world or you're working somewhere else. That's a lot of momentum to overcome for any long-standing project or development team to move to another language, tool chain, standard library, and so on.
I also think the summary's claim that Java is easy for humans to understand at a glance because of its simplicity is a mischaracterisation. Java is a relatively verbose, inexpressive language, so actually it can take quite a long time to figure out how any given piece of code works. What Java does offer is that an average developer can reliably figure out how any given piece of code works, even if it takes a while. For long-running, large-scale projects that is a valuable attribute for a programming language.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
It is pretty easy to read Java code and figure out what it means.
Many who deal with the "enterprise" software would simply laugh at the statement.
But hey, the same argument was often made about the BASIC. And I always said that Java and BASIC users are very similar.
All hope abandon ye who enter here.
What amuses me is that many people rave on about how great C# is, while denouncing Java. Yet other than a few minor syntax tweaks (like the way you write getters/setters and the "?" indicator for nullable attributes), they are virtually identical right down to the API.
They're both very easy to read and code with, and if you know the packages/libraries of one you'll find the equivalent in the other in short order, with very, very few differences in the details of the APIs.
Yet C# is "great" and Java "sucks".
Go figure.
I do not fail; I succeed at finding out what does not work.
I disagree that it is because java is easy to read. Java is easy to write. A good programer can write an app in Java and have it work really well. A bad programer can write an app in java it will work.
With C++ a good programer can write an app and it will work but you really have to watch for a lot of gotchas. A bad programer can not write a program that works in C++ because it will leak memory, stomp on memory, and have issues with pointers.
Java is better at stopping the little brain farts from blowing up in your face.
C++ is a lot more fun to write in IMHO.
See my blog http://ilovecookes.blogspot.com/ for light hearted technical information.
C# is like a cleaned-up, easy-mode Java. It's really difficult to not know what you're doing if you actually paid attention in your 101-level programming courses in college.
C# delegates are just, in C terms, typedef'ed function pointer prototypes. Now, C doesn't really have those. But you know what a prototype is, you know what a function pointer is, and you know what typedef-ing does. Now combine these ideas. "This is a name for a specific format of a function pointer that I'm going to use over and over later." Due to the C++ influence, it also has an object protection level specified.
The format is: {protection level} delegate {return type} {typedef name} ({parameter list});
Example: public delegate int Foo(int a, int b);
Now, when you want to use one (for a callback, probably), you simply accept a parameter of your delegate type. (Example: void DoSomethingAndCallAFoo(int blah, int blah2, Foo callback))
And to provide that delegate, you would write a function in a class somewhere that has the same signature as the delegate, then pass it as the argument to DoSomethingAndCallAFoo. So, if you had a function named Bar that matches the Foo delegate's signature, you could call DoSomethingAndCallAFoo(blah, blah2, Bar); or optionally, you could make it slightly more obvious what's going on by calling DoSomethingAndCallAFoo(blah, blah2, new Foo(Bar));.
As for events, they're just function pointer lists that only(*) accept pointers to delegates with an expected signature: public delegate void Whatever(object sender, EventArgs e). (EventArgs is covariant, so derived EventArgs can be passed in as well.) Those pointers-to-delegates-with-an-expected-signature are called event handlers. The EventHandler generic handles all of this for you. Declaring a member event as public event EventHandler ShitHappened; will accept the Whatever delegate above (and you don't even have to declare the delegate, since the signature-matching happens anyway at compile-time). All that's needed now is a dispatcher function, typically named On{event name} (in this case, OnShitHappened), and accepting only the appropriate EventArgs as a parameter. It should check for a non-null event pointer list, and call the event handler with a this-pointer and the event args parameter it was supplied with.
You shouldn't really have tricky memory leaks to watch out for unless you're doing threaded stuff (due to the way thread memory allocation works, you can abandon a thread in a messy way and leave a bunch of un-GC-able stuff lying around that won't get cleaned up until the process goes away). Just using delegates and events shouldn't cause any trouble.
(*) "only", if you're sane. You can force events to use non-standard delegate signatures, but you're an idiot if you do. Nobody will be able to maintain your code. Not even your 6-months-future self. Especially if I'm your boss and catch you using that unmaintainable crap, because your 6-months-future self won't be working near me or that code anymore.
Yeap, of course repeat the type of the object twice, the ugly diamond operators, use else if instead of elif, etc, produces verbosity, but this is not related to be easy or not to understand.
The thing is, I think it is related to how easy something is to understand.
If I can express an algorithm as a single function of 10 lines then, other things being equal, that will be easier to understand than distributing the same algorithm across 5 functions each of 20 lines. You can see the whole thing at once, instead of jumping around within or between files. You don't have overheads of passing around and returning values.
Similarly, if I can express a simple bit of logic as a clean one-liner, while a verbose style requires 6 lines of manual loop/conditional logic and maybe a function wrapped around it, then I'm thinking about what that logic is doing and it how it fits in with the other logic around it while you're still worrying about loop counters.
Here's a version of finding all the items less than 10 in a list, written in Haskell, a relatively powerful language:
Here's a slightly more verbose version, written in Python, also a language known for being clean and expressive:
And in contrast, here is the best Stack Overflow has to offer about implementing this sort of requirement in Java.
Spoiler: There are basically three kinds of replies. Some write out entire functions to implement the filter using a manual loop. Some use a third party library to do a more clumsy variation of the Python and Haskell examples above. And a few recent ones use Java 8 to do a slightly less clumsy variation of the Python and Haskell examples above. The clear trend is to try to get away from classical, verbose Java to something more powerful and expressive. Like Scala, according to the first comment on the original question...
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
Totally disagree. If I see
I know exactly what it does. Anyone who has done any programming in any language can guess what it does. Its simple, easy to read, and if you want can be pulled into a function. Your haskell and Python implementations are unreadable and requires the user to think about each line. They're inferior to straight forward programming by orders of magnitude and should never be used.
I still have more fans than freaks. WTF is wrong with you people?
I've never used any of the three languages in discussion here, and would barely count myself as a programmer at all, and upon initial reading of each of these routines this was my interpretation:
Java (I assume yours is): For every integer (call it "i") in the set "items", if "i" is less than ten, do whatever the 'add' function of the 'results' object does to it. (No idea what that function is, but my first guess would be to do the math of "results" + "i". Upon reflection after seeing the other languages' versions of this routine, I get now that it means "put 'i' as a member into the set 'results', or more loosely, "add 'i' to the set 'results'".)
Haskell: The set "items" contains members 1, 15, 27, 3, and 54. The set "results" contains every member of that set ("items") that passes the filter of being less than 10. (This is the clearest to me, and the one that shed light on the purpose of the other two).
Python: The set "items" contains members 1, 15, 27, 3, and 54. The set "results"... uhh.... assuming this does the same thing as the Haskell function, I'd guess it means that "results" contains every "item", where "item" is any item in the set of items, but only if "item" is less than ten; a roundabout way of saying, in a more Java-like fashion, "for every item (call it 'item') in the set 'items', if 'item' is less than ten [then that is part of what the set 'results' equals]".
-Forrest Cameranesi, Geek of all Trades
"I am Sam. Sam I am. I do not like trolls, flames, or spam."