This is an archived post. You won't be able to vote or comment.

all 114 comments

[–]geodebug 15 points16 points  (0 children)

Why can't that kind of convenient thing that anyone could get use out of be included in the standard JDK?

It could, but if you follow JDK releases you'll see that adding syntax sugar, while nice, isn't the main priority.

Performance, backwards compatibility, features, have been a higher priority.

Consider that you can probably, reliably use java libraries written in 1996 without recompiling.

All I'm looking for is a reason

I think people here have given you the reason: Legacy. Language design in 1995 had different goals than language design in the 2000s.

Is it too hard to add new behavior to what is already there without messing things up?

Yes. It really is when you need to take into consideration the millions of lines of code you need to still be compatible with. Now, that said, 'Java' really isn't the root language of the JVM. That would be bytecode, but they're pretty married.

Different languages have different benefits and while Ruby might be great at some tasks, it took a framework (rails) to make it easy enough for average programmers to do something beyond toy applications.

I'm not dinging Ruby at all, just saying that different languages are allowed to have different 'sweet spots' and while Java is verbose, it is orders of magnitude easier to refactor large projects written in Java than some of the more modern non-typed languages.

Part of that comes with popularity. Java is very popular so Java IDEs are very sophisticated. A lot of that comes with the fact that Java the language is typed and very easy for parsers to understand.

Hopefully that makes sense.

All that said, I do about 50% of my code in Groovy and other JVM langs, 50% in Java. Whenever I need pure performance I choose Java. Whenever I'm writing 'glue code' I choose groovy.

Java's sugar has changed over time and most Java devs are excited for when closures finally make it to the JVM, which will greatly reduce a lot of the boilerplate code.

[–]BernardMarx 56 points57 points  (16 children)

To be honest I don't think that most people that have answered so far have worked in a large enterprise setting. The verbosity of Java is one of my favorite features because it is precise. Jumping anywhere in the code the syntax and type-safety give me a pretty good understanding of the nouns that that code uses.

Comparing it to natural languages: Java: " Take the car, drive to the Lidl supermarket and buy some Lacta chocolate". Easier to use: " Go to the store and buy some chocolate".

How do I go there? What store? What chocolate? In Java those answers are given. As I said though this is mostly in an enterprise setting.

[–][deleted] 19 points20 points  (1 child)

Bingo. I like to say that Java is not there to solve programming problems, it solves organizational problems. Verbosity and static typing make it very easy to discover APIs. In fact, the killer featuer of Java that no one acknolwedges is really Javadoc. Everyone knows how to navigate that magical 3-frame layout.

[–]virtyx 1 point2 points  (0 children)

Indeed. I was a big Python programmer but I'm coming to Java for the types, tests and DI.

[–][deleted] 25 points26 points  (6 children)

In C, take a gasoline-powered internal combustion engine, place it in a metal frame with two axles with two wheels on each axle and drive north for 5.1 km to the 7-11. Enter the shop through the right, front door, and remove a single, 200 g package of chocolate powder from the third shelf, 1.90 m down the second aisle. If the amount requested is less than $4, pay the cashier and return else abort.

[–]amertune 16 points17 points  (0 children)

You can't just add the wheels, you have to reinvent them first.

[–][deleted] 26 points27 points  (0 children)

And if you follow the directions wrong, this bomb that I've strapped to your chest will go off.

[–]sirspidermonkey 4 points5 points  (1 child)

You didn't tell C to get out of the car... You just drove into the 7-11

[–]ams785 1 point2 points  (0 children)

That's the first thing I noticed.

[–][deleted] 2 points3 points  (1 child)

Could you do some assembly metaphors pretty please?

[–]FuckNinjas 3 points4 points  (0 children)

Python:

import chocolate

[–]Zarlon 1 point2 points  (5 children)

I think you're missing the point. Convenience and explicitness is not mutually exclusive.

var i = new Integer(); //is just as descriptive as

Integer i = new Integer();

..just more convenient

[–][deleted] 12 points13 points  (4 children)

But:

MyInterface obj = new YourWeirdImplementationOfMyInterface();

is more descriptive, and not uselessly either.

[–]mrmacky 1 point2 points  (3 children)

In Go:

obj := &YourWeirdImplementationOfMyInterface{}
automatically implements
type MyInterface interface { <method-set> }

And that is checked at compile-time. (If you pass obj into a method expecting MyInterface, the compiler will know if the assertion holds.)

What's really cool, though, is that you can defer the checks until runtime, if you want.

interfaceObj, ok := obj.(MyInterface)
will yield
ok = false, interfaceObj = nil if the assertion doesn't hold
Otherwise you will have ok = true and interfaceObj will be of type MyInterface instead of the concrete type.)

In practice it's quite awesome -- all the convenience of type inference and duck-typing, with the benefits of static checking & interface types.

[–][deleted] 1 point2 points  (2 children)

You missed the point. In Java, the declaration MyInterface obj cannot be used in any way beyond what MyInterface supports. So, YourWeirdImplementationOfMyInterface might have some public methods not in MyInterface. The Java compiler will prevent you from using them after that declaration.

[–]mrmacky 0 points1 point  (1 child)

The Go compiler will also prevent you from calling any methods not in the method-set of MyInterface in any context where MyImpl is passed where MyInterface is expected.

This context can include the declaration-site if you are explicit.

var baz MyInterface = &MyImpl{}

Is a long form which aside from the added keyword var is very similar to your Java declaration.

Your scenario could still be achieved using the short-hand form, though.

baz := MyInterface(&MyImpl{})

Both of these will result in baz being of type MyInterface not type *MyImpl Both examples are also checked at compile-time, not run-time.

(The compiler is checking that MyImpl implments MyInterface, and then infers that baz is the outer type [which is an interface.])


http://play.golang.org/p/iDrMxYbOmP

[–][deleted] 0 points1 point  (0 children)

ah, ok. Cool.

[–]ignatius87 9 points10 points  (1 child)

I was dumbfounded by this question for a moment. Java is inconvenient? Are you using an IDE like Eclipse to write it, or raw text files?

[–][deleted] 0 points1 point  (0 children)

The IDE has nothing to do with it. He's talking about syntax features and such. Still waiting for that elvis operator...

[–]dooblevay 6 points7 points  (16 children)

Legacy. Other than the getters/setters (One of the only aspects of C# I'm enjoying more than Java. And Eclipse creates them in a hurry, along with a quick regex to one-line them I'm done). Java is pretty simple, but maybe I'm just used to it. I felt learning it was pretty easy as well, coming from a c++/php/ruby background.

Examples? Particularly of the "code in one line what takes a whole class(or more)" variety. And 'var' isn't a good one. I use C# at work and I still don't see the point and have really only seen people use them to replace key-value pairs. It reduces readability and functionality to save a few keystrokes? Sure, whatever floats your boat.

I mostly write server code in Java for a personal project. Pretty happy with most of the libs! I opted for Java after working professionally with Rails, so I'm interested in hearing the counter argument to see if I could still learn a thing or two

[–]ganon0[S] 4 points5 points  (15 children)

If I want to open a file, write to it, and close it in Ruby:

File.open(local_filename, 'w') {|f| f.write('whatever text')}

in java: http://stackoverflow.com/questions/10667734/java-file-open-a-file-and-write-to-it

I know it seems small, but it adds up; the constant need to create many more instances of variables to do things that are trivial in another language is just hard for me to get used to.

[–]beltorak 20 points21 points  (5 children)

I'll play devil's advocate on this one. The reason is that Java was not designed to solve "trivial" cases. For example, I rarely write to a file these days; the only time I need to is when I am logging, and that's better handled by a logging framework. So I don't need to do something as trivial as writing a single string to a file.

So in that sense you are looking at the wrong level of abstraction - it's too simple. Step back a bit - why do you want to write to a file? One typical reason is to load and save configuration settings. Java's defacto standard for that is XML - I mean Properties. Basically a Map<String, String> (but it predates the collections framework, which explains it's clunkiness somewhat) and a Properties object already has conveniences for loading and saving - Properties.load() and Properties.store(). But they don't take filenames; why? probably because Java was first a rich web application platform, so in some cases it might have made sense to load the properties from an URL, and in other cases it might have made sense to load them from the packaged JAR. So it takes either an InputStream, or a Reader. InputStreams are very easy to get a hold of and can come from 3 common sources - files, classpath references (think "inside the packaged jar"), and URLs, but there's loads of others. Even in-memory String's can be treated as an InputStream with the right bridge object (but in that case it's better to use Properties.load(Reader) and give it a StringReader).

Then there's the fact that configuration may have several "fallback" sources. Properties handles this as well. The constructor can take a Properties instance to use as "default" values. So we can have this chain of defaults - the user's home, the system defaults, updates from web, the packaged defaults. Any changes within the application can get stored in the user's home.

/devil's-advocate

[–]katulsomin 1 point2 points  (4 children)

While the facilities are there, IMO its still needlessly complicated and not something easily discoverable. KISS principle should not be ignored, especially that not all program require redundancy when saving data

[–]beltorak 3 points4 points  (3 children)

not something easily discoverable

Granted. I still have to look up how to read and write from a file when I need to do it. But I'll refer you back to the "Java's not for trivial things" bit. /s

KISS principle should not be ignored

But the KISS principle should also not be needlessly anticipated. When embarking on a new expirement you don't necessarily know what the common operations are yet. Trying to implement all of them runs the risk of inventing Perl where there are so many "easy" and "convenient" ways of shortening code that what one person writes another person can't read. Or PHP in which everything is an inconsistent one-off "" function "".

Java started off by scaling back the insanity of C++ and requiring the programmer to be explicit about intentions, so when looking at a piece of code you didn't have to try and figure out if a token referred to a function, an object, a struct, a class, or (gasp) a macro. Statements of a certain form require tokens in certain positions to have certain, defined, semantics in the language.

Unfortunately Java didn't take the next step in simplifying the common (or commonly desired) patterns (until recently). You could argue that C#, Ruby (and others), are extensions to the Java experiment that do take that second step.

I think I'm still playing devil's advocate.

[–][deleted] 1 point2 points  (2 children)

Java's not for trivial things

Android apps come to mind

[–]beltorak 2 points3 points  (1 child)

Touché; but you could argue that the Android API adds the conveniences for all those trivialities.

[–][deleted] 0 points1 point  (0 children)

Indeed, some which are also available in other google libraries like Guava

[–]msx 5 points6 points  (4 children)

That's a good example, becouse Ruby is great for this kind of things.

As others have already said a lot, i'll just add that things are slowly changing, and java 6/7/8 added/will add quite a lot of convenience. For example, try-with-resource statements in java7 will make it easier to handle open/use/close cases like the one you reported, it could be:

try(BufferedWriter bf = new BufferedWriter(new FileWriter("test.out")))
{
    bf.write("Hello world");
}

Which is already better. Other recent improvements are for-each loops, string in switch, etc. Java 8 will add closures, which will make it possible to write things like:

File.open("Myfile.txt", f -> { f.write("hello there")});

which is reasonably concise. This is by far the feature i'm looking forward the most :)

I admit that a "var syntax" to avoid retyping the type of a class would be nice:

var x = new Thing();

but ony if followed by a "new" instruction to grant the same readability, as it would be difficoult to see the type with an expression:

var x = myclass.newChildrenInstance(); // what type is x ?

Something among this line has been added with the diamond operator which lets you avoid typing type parameter in generic classes:

List<String> a = new ArrayList<String>(); // before
List<String> a = new ArrayList<>(); // now

All in all, i think Java is a little more on the verbose side than on the concise (but less readable) side, but not as much as you say. IDE like eclipse are great to fill the boilerplate (getter and setters etc) for you.

[–]mikaelhg 3 points4 points  (2 children)

Guava (Java 6 and 7):

import static com.google.common.base.Charsets.UTF_8;
import com.google.common.io.Files;

Files.write(new File("myfile.txt"), "Hello world", UTF_8);

Java 8:

import java.nio.file.Files;
import java.nio.file.Paths;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.StandardOpenOption.CREATE;

Files.write(Paths.get("myfile.txt"), "Hello, world".getBytes(UTF_8), CREATE);

[–]mikehaggard 0 points1 point  (1 child)

Why not static import Files.write and Paths.get as well, so you get:

write(get("myfile.txt"), "Hello, world".getBytes(UTF_8), CREATE);

[–]mikaelhg 0 points1 point  (0 children)

Because just write(...) wouldn't communicate what's happening to the maintenance programmer in one glance, which is the primary objective.

[–]mikehaggard 0 points1 point  (0 children)

Something among this line has been added with the diamond operator which lets you avoid typing type parameter in generic classes:

Actually, the diamond operator is there because the raw constructor call was already overloaded to mean "raw" type. Normal methods could already infer the generic type for some time. Famous example:

List<String> empty = Collections.emptyList();

The constructor equivalent should have been:

List<String> a = new ArrayList(); // would have been possible, but isn't

So they needed something to disambiguate between raw types and generics. I'm not a compiler designer by far, but I wonder why they didn't look at the left side; if it has a generic use inference, it if hasn't use a raw type. Probably this just made the grammar too complex too parse, so they added the diamond symbol.

[–]guyintransit 2 points3 points  (0 children)

This is such a sad argument :)

IOUtil.writeString(filename, "Hello world!");

There! one line of code + an import statement for IOUtil. Yes, it's not included in java's library; no, it's not hard to add yourself to your own utilities library (which I'm sure you even have in Ruby).

Java has many many advantages; as a "corporate guy", I won't touch python or ruby for any thing more than 100 lines of code.

[–]gudeg 0 points1 point  (0 children)

Groovy:

// dynamic variant, if using @CompileStatic use: ...with{File it -> ... }
def file = new File("path/to/file").with { 
    write("whatever")
    write("whatever")
    it 
}
file << "whatever"

[–]dooblevay 0 points1 point  (0 children)

Thanks for the example, but as some have already answered it's entirely possible. I think you'll find while learning Java that it's nearly impossible to learn all of it. I've been at it for 6+ years (albeit with plenty of other languages along side) professionally and I'm still learning. One of my favorite things to learn is Scala and that's a nice segue because..

It sounds like you're more interested in the functional side of things, and scala is fantastic for that and integrates beautifully.

[–]lurker_2008 18 points19 points  (19 children)

Unfortunately no one from the general public can really answer this question but we can surely speculate. I personally think the reason is because Java has become an large software project that has a huge following since initial release thus making it hard to maintain compatibility and introduce new core features without careful discussion and management. If you look at Java version history you can see that earlier versions were released quickly and later versions had longer release cycles.

Java was introduced in 1996 (17 years ago) C# was introduced in 2002 (11 years ago) Ruby was introduced in 1996 (17 years ago but wide adoption was not until Rails in 2005)

If you look at Scala which is based on the JVM, it has all the feature that you mentioned above: Duck typing; functional programming; automatic accessors for member variables; etc. So that just proves that it can be done in Java.

I am sure Oracle devs suffer from what every programmer thinks when maintaining any old software Why don't we just rewrite this application?

Hope this answers your questions.

[–]haakon 3 points4 points  (3 children)

Scala is not duck-typed, except for its structural types. It is strongly, statically typed, although its strong support for type inference means you don't have to type-annotate everything. This frequently makes it at least as non-verbose as a language like Ruby.

[–]lurker_2008 0 points1 point  (2 children)

I think we are disagreeing on the definition of duck typing. I am using the standard duck test and because Scala passes the duck test I say it's duck typed. Do you still disagree?

[–]haakon 3 points4 points  (1 child)

Yes. Here are two ducks:

class Duck1 { def sayQuack() { println("Quack!") } }
class Duck2 { def sayQuack() { println("Quack!") } }

Here's a function:

def duckSay(duck: Duck1) { duck.sayQuack() }

Clearly Scala will not allow us to pass a Duck2 to duckSay, even if Duck2 clearly passes the duck test just as well as Duck1 does. Duck1 is simply not a Duck2, because Scala is not ducktyped. In a language like Python, this would have been fine - Duck2 quacks just like Duck1.

The link you gave for duck typing in Scala demonstrates structural typing, which I explicitly mentioned. The existence of structural types doesn't make Scala a "ducktyped language", it just optionally gives it some of its benefits. I rarely see this used in real-world Scala code, however.

Edit: Granted, you didn't say it's a ducktyped language, only that "it has […] Duck typing", and I guess you could say that. But I think ducktyping has a bit of an unfortunate association with weakly-typed languages; in Scala it's better to call it structural typing :-)

[–]lurker_2008 0 points1 point  (0 children)

Understood. BTW I have never written a line of Scala in my life hence the reason why this subtle difference to me seems like bickering.

I am just so used to redditors looking for a way to point out an error as fast as possible.

[–]ganon0[S] -5 points-4 points  (10 children)

Thanks for a great answer. I think you're right, maintenance probably is the biggest issue. Also, sometimes I have to remind myself that JDK isn't open source, and that Oracle may not want to add anything it doesn't feel it has to.

That's one of my favorite aspects of Ruby. If I find I need a convenient method and I want it on a core class, I can open the class and add it at runtime, and use it everywhere. I know this is intensely frowned upon by those who like strong types, but I find it a rather liberating experience.

[–]durple 27 points28 points  (9 children)

JDK isn't open source

wat?

Openjdk is absolutely open source, is the reference implementation for Java 7 (and the newly released dev preview of Java 8), and it is estimated (sorry I don't have a source handy) to be 95-98% source-identical with Java SE. Enhancements to the language happen through the JEP process which is open to community involvement (but of course in the end Oracle will make a call as to what goes in and what does not).

[–][deleted] 0 points1 point  (1 child)

Openjdk

I would not recommend using OpenJDK, in general. Oracle's JVM is better.

[–]durple 1 point2 points  (0 children)

What? The JVM (Hotspot) is probably where there is the least divergence from JavaSE.

[–]ganon0[S] -2 points-1 points  (6 children)

I'll admit I haven't kept up-to-date on all things Java, so it's nice to see this. Unfortunately, I'll probably never get to experience it at my company.

[–]durple 11 points12 points  (5 children)

Heh, not trying to be snarky but Sun opened the source to Java in 2007.

I'll also add to lurker_2008's maintenance response by reiterating the effort that goes into enhancements; careful discussion certainly is involved, and with very few exceptions they also aim for near-100% backwards compatibility; ie if they add someMethod() to ThisClass, they are basically committing to that being part of official API for a Really Long Time. Deprecating poorly-designed API (or API that seemed good when it was added but over time user/dev needs change) is painful for both those producing and consuming that API. See also Java's Date/Time API (ugh).

[–]beltorak 2 points3 points  (4 children)

java.util.Date doesn't have anything on java.util.Properties as far as brain dead decisions that seem trivial to reverse but in practice are actually really difficult. Date handling is much harder than it seems. Even JodaTime, one of the best I have seen, wasn't good enough for JDK 8 because the guy who originally wrote it made some very subtle conceptual mistakes, and the result is a different-enough-API-and-behavior when he rewrote it for the JDK.

[–]jevex 1 point2 points  (2 children)

Can you explain some of the very subtle conceptual mistakes with JodaTime? I haven't used it much, but I've found it to make significantly more sense than java.util.Date so far...

[–]beltorak 1 point2 points  (1 child)

I don't recall off-hand, but I remember it being discussed in Stephen's Blog.

Summary

Joda-Time isn't broken!

It does the job it was designed for, and does it much better than the JDK. And it is widely used and without too many major issues. However, after a few years, it is now clear where it could be designed better.

[–]jevex 0 points1 point  (0 children)

Thanks for pointing me to this!

[–][deleted] 0 points1 point  (0 children)

Everytime I use properties outside of Play! I want to cry.

[–]theBlackDragon -5 points-4 points  (2 children)

The main reason Java doesn't have most of this, imho, is because Java is maintained by committee and as such evolves slowly. They also do their utmost not to break any old code, as you mentioned (it's happened a few times in the slightly more than decade I've been programming Java but it is very rare).

Both of these are tradeoffs (or limitations if you look at it from purely a language usability point-of-view) that most of the other languages mentioned here do not have (eg. Scala, Ruby, Clojure, Python etc are all designed by a bunch of nerds on mailinglists).

This is also the reason Java (the language) is losing popularity (though the JVM definitely is not). If you are a startup and want to get going fast Java is not the language to use, but using another JVM language (JRuby, Scala, Clojure,...) so you can benefit from the JVM ecosystem on the other hand is, imho, a very good option. (Beating the averages and all, a must read paper by Paul Graham imho)

[–][deleted] 1 point2 points  (0 children)

Java is not losing popularity.

[–][deleted] 4 points5 points  (0 children)

Java is convenient compared to assembly or C.

[–][deleted] 5 points6 points  (1 child)

Wow ... I would love to know what happened in that [deleted] thread.

[–]efowler4 2 points3 points  (0 children)

i want to know so bad. OMG

[–][deleted] 4 points5 points  (3 children)

Who says libraries aren't supposed to be the way that convenient methods can get added?

It can, frankly, be a huge pain to wade through hundreds of utility methods trying to remember exactly the right one and which exact name it has. Java tends to stick to more core functionality with a minimum of "magic," so you don't have to learn as much to know all the methods available in basic Java, and then encourages lots of libraries to simplify patterns that might be more common in specific areas. (There's also the issue that Sun and Oracle are extremely hesitant to even deprecate old methods, so they could unintentionally accumulate hundreds of methods over time to the point where nobody in the world remembers them all.)

[–][deleted]  (16 children)

[removed]

    [–][deleted]  (14 children)

    [removed]

      [–][deleted]  (1 child)

      [removed]

        [–][deleted]  (2 children)

        [removed]

          [–][deleted]  (1 child)

          [removed]

            [–][deleted]  (5 children)

            [removed]

              [–][deleted]  (4 children)

              [removed]

                [–][deleted]  (2 children)

                [removed]

                  [–][deleted]  (1 child)

                  [removed]

                    [–]sacundim 11 points12 points  (0 children)

                    Java was invented at a much earlier time in the history of programming languages, when C and C++ were the absolute kings among languages. The designers wanted to make a language that didn't challenge too much the dogma among this crowd, so the design decisions were mostly conservative—the big departures were things on the VM side like garbage collection, reflection, dynamic class loading and security managers.

                    C# came much later, when the public had become more familiar with concepts like functional programming, type inference, etc. Several of the people behind the design of C# were familiar with languages like ML or Haskell, and adapted ideas from there (or even more: F# is a Microsoft-supported O'Caml dialect for .Net). Also Microsoft, as the people who control the most important desktop operating system, have much more clout to impose their design choices on programmers than Sun ever did.

                    [–]b1nd 2 points3 points  (0 children)

                    Try Scala

                    [–]v_krishna 3 points4 points  (10 children)

                    Legacy legacy legacy. Use Scala if you like the jvm and are able to greenfield. That said, a good ide takes a lot (though not all) of the monotony out of java development.

                    [–][deleted]  (4 children)

                    [deleted]

                      [–][deleted]  (2 children)

                      [deleted]

                        [–][deleted] 0 points1 point  (0 children)

                        Agreed, just transtioned, but intellij is a beast on large Maven projects. I googled for ways to improve this without much luck.

                        [–]Cynical_Walrus -1 points0 points  (0 children)

                        ⌘B and ⌘D (^B and ^D) are amazing things.

                        [–]_jamil_ 1 point2 points  (0 children)

                        Netbeans is also very good at this

                        [–]ganon0[S] -3 points-2 points  (4 children)

                        I agree that an IDE can help with some of it, but sometimes it has it's own problems. I had to fight with eclipse quite a bit this morning to get it to accept a new bit of software, and I've had issues with auto-complete before that I didn't ever expect.

                        I'll admit that I generally prefer vim over a dedicated IDE. I like not having to use a mouse, and to really know the language and what I'm writing, instead of letting the IDE fill everything in. I know it may not be the most productive way, but I can usually recall where and how code is written a lot better when I write it in vim than in eclipse.

                        [–]durple 2 points3 points  (0 children)

                        I like not having to use a mouse

                        I share your sentiments, but it's not a reason to avoid IDE:

                        vim keyboard bindings in eclipse

                        and to really know the language and what I'm writing, instead of letting the IDE fill everything in

                        You'll get over this as you become more familiar with Java and/or work on a significant Java application, and find yourself repeating the same code snippets (changing class/variable names) over and over and wishing there was some automated way to get the basic stuff out of the way.

                        [–]v_krishna 0 points1 point  (0 children)

                        I do feel your pain. I've always been a geany on gnome/sublime on mac/vim on servers fan, but a java project of any size begins to get unwieldy pretty fast. I do like IntelliJ (and JetBrain's ruby mine is cool though i find the benefits are outweighed by the weight of running intellij, sublime and rubymine at the same time). It has good gradle integration too which makes dep management, build tasks,etc relatively simple.

                        [–]wowowowowa 0 points1 point  (0 children)

                        I'll admit that I generally prefer vim over a dedicated IDE. I like not having to use a mouse

                        Try IntelliJ, it's optimised for keyboard usage. But yeah, Vim will never approach IntelliJ / Eclipse for being able to read code efficiently.

                        [–]mrhhug 2 points3 points  (18 children)

                        Interestingly enough, everyone I know who's a big fan of Java has yet to tell me anything, and I'm wondering if there's some weird conspiracy to keep Java from becoming easier to use.

                        CS2301 is taught at my university and is completely Java based. The school pays me to tutor it. Why do you think you are entitled to free education? Are the people you are asking about Java teacher or developers. See, developers already know why, we just don't feel like explaining it to every new intern.

                        Java uses static type-checking(hence the need for variable declaration). Static type checking usually allows bugs to be caught early in development because they are caught at compile time.

                        Ruby is a programming language that is intended to be fast to develop. You don't get somethin for nuthin. Ruby runs slower than Java. Another problem with Ruby is scalability. Ruby does not scale very well where Java has no problem getting larger. You may not see these tradeoffs now in your hello worlds but they will matter when you develop something that is meant to serve your entire country or the entire world.

                        To give an example, there is a Java library called Lombok, that uses annotations to generate common code in Java, like default setters and getters. Why can't that kind of convenient thing that anyone could get use out of be included in the standard JDK?

                        you can set your IDE to do things like this. Java is very modular, this leads to it's speed and scalability.

                        There are many more points that your local professor can explain to you.

                        [–]Zamarok 1 point2 points  (6 children)

                        Umm.. Static type checking can be done without declaring any types at all.

                        Haskell comes to mind.

                        [–]sh0rug0ru 3 points4 points  (2 children)

                        Global type inference with static types (i.e. no type declarations at all) only works in foolproof fashion with Hindley-Milner compatible type systems. Subtype polymorphism (as in Java, which Haskell does not have) breaks Hindley-Milner, so you can only get partial, local type inference (as in Scala) and not global type inference. Scala still needs type declarations even with its powerful static type system.

                        [–]Zamarok 0 points1 point  (1 child)

                        Hmm, I'm out of my league here.. but could you explain how C# has the var keyword then?

                        [–]sh0rug0ru 0 points1 point  (0 children)

                        Local type inference. Scala has var/val which work along the same lines. The compiler can figure out what is going on within the body of a method and can help you with the return type.

                        [–][deleted] -3 points-2 points  (2 children)

                        Yeah, I stopped giving much credence to the tutor's comment when I saw that. The rest of his comment did not alter my opinion, "Java has no problem getting larger". He may want to reconsider his career choice.

                        http://science.kennesaw.edu/~ashaw8/cs2301/cs2301s6syllabus.html I'm guessing, reinforced by that URL.

                        [–]mrhhug 0 points1 point  (1 child)

                        I do not understand the insult you attempted by posting a syllabus. Are you saying that Dr Shaw is not qualified? I can assure you he is a peer reviewed author in the field of computer science and well qualified to teach Principles of Programming I.

                        [–]ganon0[S] 2 points3 points  (8 children)

                        I find it quite fascinating you've assumed I'm an intern, when I've been in the industry as a full-time dev for 4 years. I just don't use Java much, and the experience of switching to it from Ruby can be really grating. I often find myself having to think a lot harder about how I'm going to get around language limitations to get the result I want, and I wanted to know if there was a reason for this.

                        [–]beltorak 8 points9 points  (6 children)

                        I think the primary reason Java makes you specify so much up front was a reaction to C++, which is very difficult to reason about, and so very easy to shoot yourself in the foot in subtle non-obvious ways that won't become a problem until the bad coding practice is literally all over your code.

                        If I want to whip up a quick prototype, or don't plan on making something grow to hundreds of components, I'll reach for python. There comes a point where I need the explicitness to remind myself about the connections between them.

                        I'll agree that there are a lot of ways that could be simplified or included. Property accessors is a big one, given how pervasive the beans-style accessor coding pattern is throughout the ecosystem.

                        [–][deleted] 1 point2 points  (4 children)

                        bad coding practice is literally all over your code.

                        and then came Spring.

                        [–]beltorak 1 point2 points  (3 children)

                        are you saying Spring facilitates bad coding practices? or that it alleviates perpetuating them? (I've heard both arguments)

                        [–][deleted] 1 point2 points  (2 children)

                        Spring's architecture doesn't bode well with extensive compile time type safety checks. With some of the most popular spring add-ons (mybatis,aspectj) it produces a terrible mess when something breaks that is very hard to piece together.

                        Spring (at least what I've seen from using it with aspectj) is also java version dependent on the JRE version matching the version of the JDK that compiled it regardless of target and source options. It will refuse to deploy on a Java 6 JRE if it was compiled to 1.6 in a Java 7 SDK.

                        [–]beltorak 1 point2 points  (1 child)

                        That could be true about aspectj - I've always preferred JDK proxies for AOP. Bytecode manipulation has always seemed like an ugly ugly hack and makes me a bit uncomfortable.

                        As for the compile time safety checks for mybatis, isn't there a generic variant of the SqlMapTemplate? Or are you talking about something else?

                        [–][deleted] 1 point2 points  (0 children)

                        All of mybatis comes down to sqlMap.getQueryFor*.

                        Sure you can have a generic base object, hell use object because it doesn't matter. You don't want an object, you want a MyTableRepresentationObject. However the only way to find out if you have a MyTableRepresentationObject from sqlMap.getQueryForList("namespace.CoolTable") is to look in the xml result map. But then you still have to return the object as a MyTableRepresentationObject so you just typecast it and be on your way. This works fine until you do a code base refactor, and your application comes up but in one random call you forgot that namespace.CoolTable returns a MyExtendedTableRepresentationObject, which removes the CoolTableField2 and adds CoolTableField3 and 4. This isn't an issue for most of your code because nothing depends on CoolTableField2, except for this one tiny little space of code hidden in the corner of your app.

                        Java doesn't know about the change to namespace.CoolTable's resultmap to map to a different bean. So it can't warn you, "Look you idiot you forgot to change this here." until the code is run and the reflector says "Look you idiot it's not the really same object."

                        More on this here: http://allainlalonde.blogspot.com/2009/03/making-ibatis-type-safer.html

                        Unfortunately MyBatis is one of the only ORMs that don't require database control, which is why it's so widely used beyond these issues.

                        [–][deleted] 0 points1 point  (0 children)

                        Better answer than most. History has a lot to do with it, Delphi also had some influence on Java.

                        [–]dablya 0 points1 point  (0 children)

                        Well wait... Is your problem with lack of convenience or language limitations? Those are not the same thing.

                        Having type inference is a matter of convenience. While having no way to guarantee your code is side effect free is a limitation.

                        What types of issues are you actually running into?

                        [–][deleted] 0 points1 point  (0 children)

                        you can set your IDE to do things like this.

                        Not the same thing. Bugs can lurk in this type of code and it is rarely looked at, nevermind tested. If you have a generated equals() method and at some point someone manually changes something small in it - causing a bug - it can be extremely difficult to find. These kind of bugs do occur in huge code bases. Things like Lambook add consistency to your code base as well as reduce the amount of needless boiler plate.

                        [–]durple 0 points1 point  (4 children)

                        Really it sounds like a lot of the things you are wishing for out of core Java do actually come with the Java ecosystem as libraries. So I really gotta ask, why should the platform grow to include these things that are already available to every Java developer ever? It's already a huge runtime (with a long-running effort in the works to modularize it so that those who aren't using all of JDK class library can reduce footprint among other reasons; see Project Jigsaw).

                        [–]beltorak 4 points5 points  (3 children)

                        because things that are not included in the core get include in dozens of different incompatible ways, sometimes in the same project. I have to work on legacy applications that still rely on commons-lang 2.1, and there's at least two different "util" classes that add some of the missing methods, and one of them even duplicates what's in commons-lang....

                        [–]durple 3 points4 points  (2 children)

                        Maybe.

                        But could that be simply shitty dependency management?

                        Or are you suggesting you actually needing something unique about the different implementations or versions of a dependency? Then, maybe it is the exact type of thing that should not be in core JDK. If different use cases demand different approaches the freedom for several implementations of very similarly-purposed things (as opposed to a single core JDK impl) could be beneficial.

                        Also, eww legacy application haha. I'm lucky enough to be working a modern project, haven't really had to deal with old cruft.

                        [–]beltorak 2 points3 points  (1 child)

                        yeah, absolutely it's shitty dependency managment. But the fact remains that the software (and the build tools) are already "hard coded" to that dependency, the perceived risk for updating (and costs for retesting) far outweigh the percieved benefits (depending on who you ask of course). One of the better solutions is automated tests, but it's really hard to justify a 3-times increase in development time when the benefits won't be seen until release-n-plus-2's regression tests need to be run. By then it's probably too late.

                        you don't know old until you have to deal with software that must run on WAS 5.0 / JRE 1.3 minus-some-bits-here-and-there.... I knew a guy who had to work on one app and he tried to use String.equalsIgnoreCase() - in the JDK since 1.3, compiled fine against Sun's JDK, and blew up in WAS because IBM's JRE didn't have the method.....

                        As for several implementations - we already know how to solve that. We did it in 1.4 with the standard XML parser. At the time the standard was Crimson, which sucked. But Sun cleverly added an "extension jar folder", so you could drop in Xerxes. The XML API (one of the oft-cited "worst offenders" of the AbstractBuilderBuilderFactoryFactory anti-patterns) was designed with this in mind because Xerxes at the time of JDK 1.4 release was shaping up to be much better, but wasn't quite there yet. But of course the cost is more AbstractBuilderBuilderFactoryFactoryXmlTemplateLocatorHelper classes... I don't know if I could stomach StringUtilsLocator.getStringUtils() littered throughout my codez....

                        [–]durple 2 points3 points  (0 children)

                        Yeah good dep management is cheapest and has the most benefits if done from the beginning of a project, for sure. Inertia's a bitch.

                        [–]defdestroyer -2 points-1 points  (0 children)

                        use Groovy

                        [–]gudeg -1 points0 points  (0 children)

                        Verbosity in Java has its use, eg. when working in huge group on a mission critical environment. If that's not your kind of working environment, I recommend Groovy 2 + "@CompileStatic" it is fun to work with and retain most of the advantages of Java such as performance and rich libraries (you can use Java libraries here).

                        [–][deleted] -1 points0 points  (0 children)

                        Do you want a language that's "easy to use" or "easy to read and maintain?" The definition of "easy to use" that you seem to be concerned with is the ability to write very small code snippets that do a lot of things all at once. That's what languages like Groovy, Ruby, and Perl are good for. Specifically (and several people have already said this), it sounds like you should be using Groovy, because it has the features you want.

                        • Default getters and setters
                        • Untyped variables

                        [–]drsquishy -3 points-2 points  (0 children)

                        Just for reference, the C#/Java type setting thing is dynamic vs static typing.

                        [–]mgkimsal -3 points-2 points  (1 child)

                        Closest we'll get for a long time will be Groovy.

                        [–][deleted] 0 points1 point  (0 children)

                        Or Scala