More Stupid Java Tricks

Posted in Java by Dan on August 26th, 2008

My previous post was reasonably popular so I decided to follow-up with some more stupid Java tricks. It should go without saying that you shouldn’t use these techniques in any serious code, unless of course your objective is to write unmaintainable code.

It was pointed out to me by a couple of people that the puzzle I posed previously is also in Josh Bloch and Neal Gafter’s excellent Java Puzzlers book. If you are interested in all of the ugly corners of the Java platform, this book is well worth buying.

Unchecked Checked Exceptions

Throw checked exceptions without the hassle of dealing with them

There’s a lot of debate about the relative merits of checked and unchecked exceptions in Java. You can have the best of both worlds by throwing checked exceptions without either catching them or declaring them in a throws clause. The deprecated Thread.stop(Throwable) method is one way:

private void throwSomething() // Look, no throws clause!
{
    Thread.currentThread().stop(new IOException("This won't be caught."));
}

The slightly more socially-acceptable Class.newInstance() method is another way. It’s not deprecated but it does have one well-documented flaw:

Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler.

Invasion of Privacy

Strings aren’t really immutable, even literals can’t be trusted

This is a bit of a golden oldie but it still has great potential for messing with your co-workers’ sanity.

All high-level programming languages have rules. These rules are there to protect you, to stop you from really messing things up. Fortunately, Java allows you bypass some of these rules, via the dark art of reflection, and have some fun by changing things that you really shouldn’t be allowed to change.  Your confused colleagues might never trust a machine again. It’s all about the String constants cached by the JVM.

All it takes is a few lines (suitably hidden in some seemingly unrelated class)

java.lang.reflect.Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set("Hello World!", "Goodbye     ".toCharArray());

then this

System.out.println("Hello World!");

prints this

Goodbye

Escape to Victory

A language feature that appears to exist primarily to break syntax-highlighers

Of course, if your co-workers are made of sterner stuff you may need to be a little more devious to send them insane. They won’t be able to track down the offending code above by searching for “Hello World!”, “Goodbye” or even “setAccessible” if these Strings don’t appear anywhere in the source.

Unicode escape sequences (such as 'u0020') can be used not only to construct character and String literals but can actually be used anywhere in the source that their equivalent characters can be used. So entire statements, even entire classes can be written solely with these escape sequences.

Questionable Parentage

Instantiating inner class objects outside of the parent class

Inner classes (that is non-static nested classes) have an implicit reference to an instance of their containing class, but they don’t necessarily have to be instantiated within the scope of the parent class. Daniel Pitts shows another way. File this one under “ugly syntax” and “surely that’s not supposed to work?”.

Boxing Clever

From stupid Java tricks to stupid Java pitfalls

This one is not a trick as such but it is a good example of Java code that behaves completely unintuitively. The introduction of auto-boxing and auto-unboxing in Java 5 has created a whole new set of opportunities for bugs.

This is my personal favourite:

Integer n = 128;
Integer m = 128;
assert n <= m; // This works.
assert n >= m; // This works.
assert n == m; // This fails.

It gets better. Try changing n and m to both be 127 and it works, which, to be fair, is exactly how it’s supposed to work according to the JLS:

If the value p being boxed is true, false, a byte, a char in the range u0000 to u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

But it’s not exactly what you would expect if you hadn’t read the spec.

Any more?

That’s all the Java stupidity I can think of right now. Feel free to add your own stupid Java tricks in the comments.