Menu

More stuff about Java

November 21, 2012 - .NET, Programming

Recently I started working on what turned out to be a lot bigger of a project than original intended. It is a Bukkit Plugin; Bukkit being a server “replacement” for Minecraft. Since it’s written in Java, that means the Plugins are as well. As a result, I’ve been working frequently with Java. In a previous blog post on the subject, I noted how C# Was, in almost every discernable way, better than Java. I still hold to that. That post did not of course (and I believe I mentioned this in the post itself) mean to say that Java was useless. Even though C# is cross-platform, it’s not marketed as such; additionally, many Windows-centric frameworks have appeared (WPF, WCF, etc) which aren’t available on other platforms, causing C# code to be coupled to the platform. Of course this can happen with Java code as well, but it’s probably more common with C# code.

Anyway, since I’ve been working with Java, both it’s strengths and weaknesses have popped out at me. This is more a list of opinions, really, but that’s stating the obvious.

Classes have to be in their own files

I’m not 100% sure about this one. It can really work both ways. With BASeBlock, some of my files have way too many classes, and it makes navigation difficult. On the other hand, a lot of those issues are alleviated by using the Solution Explorer to navigated as a class view, rather than file view. Additionally, I think the Java limitation of one public class per file is one of those design changes to Java that serve more to make it easy to write compilers as well as “force” what the designers of the language thought of as “good design”. I prefer having the ability to declare classes in the same files; a single C# file could add classes to various namespaces, add extension methods to existing classes, and so forth. Of course, it’s quite possible to go overboard with this, but I think that is something that should be dealt with by the programmer, not something entirely prevented in the interest of good design. It also makes file management easier.

Java also enforces a system where a class is either an inner class, or it MUST have the same name as the “compilation unit” (file). For example, a class named MonkeyGizzards must be in a file named MonkeyGizzards. I have to say I really do not like the way java uses the file system to manage packages, it just feels… weird, to me. It also has the odd side effect that package names need to conform to file system rules as well as the rules of java, which is arguably easy to avoid by simply not giving your packages stupid names, but is still a weird effect.

No Delegates

Personally, I actually find this, well, kind of infuriating. It’s one thing to lack lambda’s and closures, but completely lacking any functional data type is just weird to me, now that I’ve grown to use them. There are workarounds, but the problem with those is that they are just that- workarounds. They don’t fix the underlying omission. For example, Let’s go with a relatively simple function- it takes a List, and filters out elements based on the second parameter.

Of course, with C#, this is relatively simple- in fact, I believe the routine is provided as is within linq, but for the sake of the exercise let’s assume we need one:

A call to this function might look something like this…

One line of code within the function; one line to actually use it. This actually leverages several C# Features that Java doesn’t have; first, it uses a delegate as the argument type to the routine, and second is that it uses a lambda in the call to the function, which can be implicitly converted to the argument type, which utilizes operator overloading for implicit and explicit types. It’s also notable that it is possible to pass primitive types as type arguments, which in Java requires to use of one of the Boxing types, such as Integer.

The Java equivalent is more verbose. First, you need to define an interface:

Then you need to write the implementation- in this case, a Filter routine:

This is of course but one possible implementation. Other frameworks often provide much better functionality (apache commons has some excellent extensions of this sort). Anyway, using something like this would simply require the use of an anonymous class declaration. behold!

Quite a lot of code, for something so basic. It is worth noting that writing this sort of stuff is almost an initiation for Java programming. I can see it being useful to learn how to write these things if you are actually learning in a academic setting, but this is still the sort of stuff that should be supported out of the Box. The above could likely be condensed to use the Iterable (java.lang.Iterable) interface instead of List, since it certainly doesn’t need anything specific provided by the List interface. But that is a fringe concern.

the C# Version is supported by the linq namespace. Linq adds All, Select, SelectMany, and various other methods to some core collection interfaces; the result being that these methods appear to be on those interfaces, but are implemented elsewhere. This is good, because those methods really don’t fit anywhere else.

For some time, I wondered two things: One was why Eclipse was adding Imports one by one- importing each specific class; and why the import blah.blah.*; was so frowned upon. Fundamentally, it is because of a lack of flexibility in the imports statement, as compared to the C# equivalent, “using”. the C# using statement supports Aliassing; for example:

Using CollectionsList = System.Collections.List;

would ‘import’ the System.Collections.List Type, allowing you to use it as CollectionsList. java’s import statement lacks this feature, so you need to import more carefully to avoid collisions. The primary concern for those that push importing only those types you use is that adding a new asterisk import might cause issues. Looking this up online and it seems there was a “tribulation” some time ago, when Generics was newly introduced, and there was the new java.util.List class. Many java programs started with:

what ended up happening was that the compiler would prefer java.util. This had no bearing at the time, but with the introduction of generics- and, more specifically, the List class, there was now a List class within java.util as well as java.awt (java.awt.List being the ListBox implementation). proponents of the “import only classes you use” idea cite this rather often; what they don’t cite quite as frequently is that the problem is easily averted by simply adding a new import:

This is because precedence of imports goes to explicit class imports first, then to classes in the same package, and last to asterisk imports. Arguably, explicit imports would have prevented any issues, but then again, usually programmers move to a new SE platform to use new features, so they might actually want to use the new Generics features of the time; meaning they have the same problem either way… there are two classes with the same name declared in different packages and no way of aliasing, so they end up referring to one of them with the fully qualified name.

IDE’s such as Eclipse will allow you to import classes you reference in code explicitly, but I don’t see this as a good thing; imports you are no longer using don’t go away on their own, and good tooling to try to cover up deficiencies in a language is not something I feel should be encouraged. In this case it’s even arguably not a deficiency in the language, but rather a inability to recognize what is realistic; A person usually upgrades a Project to a new version of a platform to use new features, and the above issue is fixed with a single import anyway. Overall, the best compromise is if you are using an IDE with the ability, list all the imports you use. If you are writing with a text editor or another tool, just use asterisk imports. The sky will not implode in itself if you do.

Anyway, for C#, a lot of features really just make code shorter- they are, in many ways, syntactic sugar. But arguably any programming language is syntactic sugar, so trying to use it as a derogatory term doesn’t really work; I’ve had Java programmers tell me that Lambda’s and Delegates are just syntactic sugar for anonymous interface implementations. I agree. But I like quite a bit of sugar in my coffee- why should my tastes for programming language syntax be different? When you write 20 times as much code, you are going to have 20 times as many bugs, which is part of my issue with Java as a whole.

Now, don’t get me wrong; it really does provide enough base functionality to work with. And it’s important to realize that Java has been around for quite a long time, and back then, we didn’t have such prevalent access to features such as Generics. This has the advantage that there is quite a lot of Java code available, in various libraries. But also has the downside that those libraries might be out-dated, replaced by new features in the JVM, and so on.

Have something to say about this post? Comment!