Search This Blog

Tuesday, 21 December 2010

Order matters

Every so often I come across these simple things that after thinking about them I kick myself for not thinking about and knowing sooner. Earlier today was one of those moments!

It might seem natural, assumed, even obvious that for many method calls it doesn't actually matter what way around things go. So take "asd".equals("dsa"); - does it ever make a difference?

In this case, no - but what about if we introduce variables?

String str = "asd";
System.out.println(str.equals("dsa"));
System.out.println("dsa".equals(str));


Again, no difference. Now let's be a bit sneaky however and swap str to null (you may see where this is going!)

String str = null;
System.out.println("dsa".equals(str));
System.out.println(str.equals("dsa"));

Ahah! This time we (somewhat obviously) get a NPE on the third line. But the second line executes without any problems at all (also rather obviously - we're not dereferencing null here!)

Conclusion? When comparing strings, it makes much more sense to adopt a design pattern of putting the literal first rather than a variable name. If this is the case and if the variable happens to be null, then equals will just return false rather than causing an NPE. 99% of time this is the desired behaviour, unless you know your strings should never be null and want to be screamed at if they are. Even so, it'd probably make more sense in this case to put a separate check in rather than relying on the order of the values to give you an NPE - that could easily disappear when someone else comes along and reverses the order without realising it was intentionally the other way around :-)

Saturday, 4 December 2010

The solution

You might expect it to print out 104, "10" being the sum of the fields and then "4" being the number of fields. You would of course be wrong :-)

If you run the following code you won't get a number out at all, you'll get an exception:


Exception in thread "main" java.lang.IllegalArgumentException: Attempt to get test.Outer field "test.Outer$Inner.this$0" with illegal data type conversion to int
at sun.reflect.UnsafeFieldAccessorImpl.newGetIllegalArgumentException(UnsafeFieldAccessorImpl.java:46)
at sun.reflect.UnsafeFieldAccessorImpl.newGetIntIllegalArgumentException(UnsafeFieldAccessorImpl.java:111)
at sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.getInt(UnsafeQualifiedObjectFieldAccessorImpl.java:41)
at java.lang.reflect.Field.getInt(Field.java:499)
at test.Outer.(Outer.java:21)
at test.Outer.main(Outer.java:29)


The key here is actually down to an implementation detail of Java - specifically how inner classes have a reference to their outer classes. If we make the inner class static (static inner classes don't have a reference to their enclosing class) then the problem goes away and we get the expected output, 104. So what's happening here?

It might help to think how a non-static inner class can always access its outer class. And it also might help if I tell you it's more along the realms of hackery than black magic! The key here is a field, this$0, that the compiler puts in every inner class. This is set by a constructor the compiler also puts in the inner class which is called when an object of this type is instantiated. It's an implementation detail, but quite a geeky and fun one to play around with. If you decompile the class files, you can actually see this extra field and constructor in plain daylight.

I got the idea for this puzzle from http://www.javaspecialists.eu/archive/Issue062.html - this explains this implementation detail far more accurately if you want to take a look.

So, we've got an extra field in the class that's of type Outer, not int. So when we try to call getInt() on this field, we understandably get an error.

As a follow on puzzle which you should now be able to answer, if we change this line:

catch(IllegalAccessException ex) {}

to:
catch(Exception ex) {}


what's printed out now?


The answer? 105. The values that are ints are still summed, so we get 10, but there's still 5 fields in the Inner class!

This is quite frankly a shoddy way to do things anyway, and the chances of doing something like this in real life are rather remote. But how could we fix it? One option is to check for synthetic fields and ignore them - synthetic fields are ones generated by the compiler and not by the user. So if we put if(field.isSynthetic()) continue; as the first line in the for loop and check for similar synthetic fields in counting them at the end, the problem goes away. There's a catch though - there's no requirement for the compiler to actually mark anything as synthetic. It's a bit like using a well established class in the sun package - while it might help in situations like this and is likely to be fine, it shouldn't really be relied upon.

This may seem like a silly example, but it does serve a few lessons. First, as shown by the follow on puzzle, if you just catch all exception types and expect everything to work, you may well get caught out by bugs you weren't expecting, but can really bite you later. Secondly, don't use reflection to loop through fields. It's just plain wrong. If you really have to, at least check for synthetic fields and make sure the fields are of the type you expect. And lastly, decompiling compiled code and looking at the results can be rather interesting in uncovering some Java implementation details!

Wednesday, 17 November 2010

No, I'm still not keeping these to myself ;-)

The usual drill here - what does it print and why?

...yes, it does compile :-)


import java.lang.reflect.Field;

public class Outer {

private class Inner {
private int field1 = 1;
private int field2 = 2;
private int field3 = 3;
private int field4 = 4;
}

public Outer() {
int count=0;
Inner inner = new Inner();
for(Field field : Inner.class.getDeclaredFields()) {
field.setAccessible(true);
try {
count += field.getInt(inner);
}
catch(IllegalAccessException ex) {}
}
System.out.print(count);
}

public static void main(String[] arguments) {
new Outer();
System.out.println(Inner.class.getDeclaredFields().length);
}
}

Tuesday, 19 October 2010

Quelea

So, I've started a new project on the side. It's something I've had on my mind for a while but something that I've never really had the incentive to start. Until now that is!

The project is essentially a lyrics projection system designed for use in churches, much like OpenLP, Opensong and Easyworship. All of the preceding are decent packages and I've used them all, but there's various things in each of them I like and don't like. The aim? To bring all the features I do like together into one neat, easy to use package that's comprehensive, reliable and open source. When I say "I" I actually mean a few people I've spoken to as well as myself - I'm definitely getting other input before ploughing ahead! :-)

The site's www.quelea.org - there's not much there at the moment but things are definitely on the way. (You may notice a few interesting things on there, I don't like to take everything quite 100% seriously!) I'm hoping by Christmas this year I'll have a bare bones working release to ship as an early alpha, and perhaps a few partially complete demos before then.

Technical details? It's written in Java, uses hsqldb for its song database and uses substance for its look and feel (might as well have something that looks nice when you get it for free! Definitely better than the default look and feel...) Swing can look pretty. Honest :-) Beyond that there's not an awful lot decided yet, though the schedule file format will probably be a zip file stuffed with XML files and resources required (vaguely like the new MS Office formats.)

Watch this space!

ListModel turns generic - at last

The features of project coin have been shouted about and argued over for a while now, and other various API changes have also made it into the spotlight - a fork-join framework in java.util.concurrent and the ability to have shaped windows for instance.

However, one thing that seems to have slipped under the spotlight is the fact that ListModel is now generic, a change that's well overdue in my opinion.

http://download-llnw.oracle.com/javase/7/docs/api/javax/swing/ListModel.html

Dealing with constant casting on list models thus far hasn't been nice, and I'm not sure why it's taken this long for the class to become generic - it's an obvious candidate and I struggle to see how it slipped under the carpet for both Java 5 and 6.

It's a relatively minor change in the grand scheme of things, but sometimes it's the minor changes that actually turn out to be the ones that work best and save most time. I'll certainly look forward to the day when I no longer need to cast everything coming out of listmodels!

Tuesday, 5 October 2010

Apricots

No, I haven't become addicted to the orange fruit growing on trees. But I have become a tad addicted to the game called apricots (again, nothing to do with the fruit and aside from "various reasons" I can't find any explanation as to why it's called this!)

It's a game where you have to fly a little plane around and shoot enemy bases whilst avoiding civilian houses, trees and skyscrapers. Grab it, it's free and has Linux and Windows versions: http://www.fishies.org.uk/apricots.html

It's rather simplistic, but highly addictive and I like the idea. Despite the fact the site claims it's still being developed, the last update was the best part of a decade ago, and after attempting to contact the author a while back and receiving no reply I'm pretty certain it's been abandoned. I'm considering taking the idea and rewriting it in Java with more modern looking graphics and gameplay - it'd be an interesting project on the side. That is if I can stop playing the thing...

Java puzzle - the solution

Though no-one's actually commented on the Java puzzle, I know at least two who attempted it... and one who, after a hint, got it bang on.

The key is that anonymous inner class that actually gets compiled into a separate class file - Main$1.class. It's this class that contains the code which prints out hello, so the following compiled and dropped in place would cause the program to print goodbye, without modifying Main.class:


package bosscode;

public class Main$1 implements Runnable {
public void run() {
System.out.println("goodbye");
}
}


The java.lang.Runnable in the original code was deliberately there to prevent the creation of an additional Runnable class in the bosscode package, which would have worked had Runnable not been declared with its package!

This actually highlights an interesting problem - it's entirely legal as far as the compiler's concerned to create a Main class and a Main$1 class in the same package, creating naming conflicts. Whilst this may seem unlikely, if the inner class isn't anonymous the name will take the form of Outer$Inner - so the potential is there to cause issues. In fact, whilst experimenting around with this puzzle in Netbeans it didn't show me any warnings that I'd created such a conflict, the last class to be compiled was just the one that dictated the output.

Of course, we can solve this problem altogether by never using a dollar sign in class names explicitly, reserving it as a special symbol for the compiler to use. I do wonder why this isn't strictly enforced though - it'd eliminate this problem (and this puzzle!) altogether.

Wednesday, 29 September 2010

Scala

I'm a Java guy - I've dabbled around in other languages but generally speaking my default language of choice for a project comes back to Java. It's been that way for a while, and quite honestly it's because out of the languages that I've looked at it seems the best "general" one out there. It's extremely versatile, can do an awful lot in the right hands and despite the various myths, well written Java code is really rather speedy these days. More recently though, there's been a lot of talk about Scala - it's been around for a decade or so but it seems it's only recently it's gained a lot of attention.

Every so often something comes along that looks great from an academic perspective, but for various reasons (usually because the industry has made its mind up already) it's not adopted - left to rot and subsequently forgotten about. Then again, every so often something comes along that looks awful from an academic perspective but somehow (usually due to a large corporation investing stupid amounts of money into it) it gains a foothold and we all have to put up with it because that's just the way things are done.

If Scala does end up squarely falling into one of these categories, it'll be the first. From an academic perspective it really does look very good indeed, with much better language level support for the functional side of things that Java looks to bolt on in the 7th (or 8th!) revision of its language. It's harder to pick up in places, yes, but because of its nature it will be. You have to get into the functional mindset to appreciate or use a functional language, just as you have to get in the OO mindset to appreciate and use an OO language such as Java.

The problem? Well, it's entirely on the practical side. A new language means people learning it from scratch, getting into a new mindset, an inevitable short term decrease in productivity whilst people get accustomed to working with it - none of which are good things for a business. And for the majority of people Java is still doing absolutely fine, especially with it's java.util.concurrent libraries. There's no desperate need to switch.

It's hard to say whether it will take off, but over the next few weeks I hope to look at it on a more practical level, playing around with a few demos and seeing if there's anywhere I can sensibly use it to integrate into existing Java code. We'll see what happens!

Wednesday, 22 September 2010

A java puzzle

I like coming up with these things once in a while. They exercise the mind, make people think and occasionally someone comes up with another method or two of solving the thing I hadn't considered.

So, here we go.

You've been presented with the following class written by your boss, which is meant to print "goodbye" out to the console. However, as you can clearly see the following code actually prints "hello". Your boss has asked you to rectify this problem somehow, but his code is perfect and it must be a bug in the JDK (of course).

In fact, he's already compiled the thing and it's ready to go, so he's said the only thing you're allowed to do is to add / modify / change class files in the bosscode package before it's released. Change whatever classes you want, as long as it's not Main.class (that's the perfect one!)


package bosscode;

public class Main {
public static void main(String[] args) {
new java.lang.Runnable() {
public void run() {
System.out.println("hello");
}
}.run();
}
}


Good luck - I'll post my solution / explanation in a few days time if anyone attempts it!

Tuesday, 21 September 2010

Java 7 - and now 8?!

It'd all gone pretty quiet on the Java 7 front recently - the last that'd been heard for a while was an estimate of a late 2010 release. I was hoping no news was good news on this front and that sometime around Christmas we might hear something positive regarding a release - alas this isn't the case.

This link sheds some light on things: http://blogs.sun.com/mr/entry/rethinking_jdk7

To summarise, it seems now that JDK7 is going to have an estimated ship date of mid 2011, *but* with a lot of the new features everyone was raving about (including Lambda, Jigsaw and parts of Coin) pushed back to JDK8 which should hit home in around 2 years time. The other approach detailed is shipping JDK7 with all its original bits in mid 2012 with no updates in the meantime.

Everyone was hoping for something a bit quicker, yes, but I guess with the Sun / Oracle acquisition slowing things down Java was bound to take a bit of a back seat. It's not such bad news, and if anything I'm mildly encouraged by the fact Oracle are leaning towards the approach to release early and postpone features rather than the "release everything in one go and hope for the best" approach.

...Yes, I know, I did just say something vaguely positive about Oracle!

It'll be interesting to see how this situation unfolds, whether plan B does actually happen and if so whether it'll happen to schedule.

Thursday, 16 September 2010

The move

After a bit of thought I decided I could no longer justify shelling out for a domain and hosting package on mikkle.co.uk for what had essentially become low traffic blog. So here it is - the site in its new format on blogger.

Unfortunately I can't upload files here, but I'll set up a Google site for that and link out to them on there.

Apart from those changes things should pretty much stay as usual - same guy, same thoughts!