New Advice - a wishlist for Java

Categories: Java

For all its flaws, I would still recommend Java for any large-scale software development. Static typing, reasonably readable syntax, good libraries, no memory overflows, decent stack-traces when things go wrong. Portable as a bonus.

With Java 8, I’m looking forward to finally having some form of closures. But two things are particularly on my wishlist for improvements which are not on any plan I’ve seen: an interceptable new operator, and decent AOP advice support

The New Operator

I hate the “new” operator. Deeply. Just today I wanted to make a minor customisation to a large library. The class that needed to be modified, however, is directly instantiated (ie via ‘new’) by another - which is instantiated by another, which is instantiated by another. So this supposedly wonderful Object Oriented feature - oh, to customise a class, just subclass it - means actually creating custom subclasses of 5 classes. And the “new” operator is often being used in the middle of large methods - so the entire method needs to be copy-and-pasted into the subclass. And then I see that the top-level class is for some @#$% reason - final!

How about changing the “new” operator to simply be equivalent to System.getObjectFactory().newInstance(Constructor c, Object[] args)?

The default implementation is then to just call the constructor passing the args. But applications can optionally do this:

public class MyObjectFactory extends ObjectFactory {
  Object newInstance(Constructor c, Object[] args) {
    if (c.getDeclaringClass() == example.Problem.class) {
      return new ProblemSolved(args);
    } else {
      return super.newInstance(clazz, c, args);
    }
  }
}

System.setObjectFactory(new MyObjectFactory());

Yeah, the example above isn’t 100% right (maybe should be per-classloader rather than global, etc). However the principal seems possible, right?

Or maybe just have the ability to override per-class:

System.addObjectFactory(Problem.class, new ObjectFactory() {
  Problem newInstance(Constructor c, Object[] args) {
    return new ProblemSolved(args);
  }
});

Hmm .. that approach starts to look a bit like Guice. Or like powermock’s MockConstructor feature but for regular runtime use. Aspectj also appears to support pointcuts on the new operator so technically it seems possible.

Better Advice

Enhancing an existing class without subclassing it is often done via a Proxy. However proxy classes suck - seeing stacktraces of Spring-based applications can make the strongest stomach quiver. Bad debugger support, poor performance, ugly code, and worst of all is that the “this” pointer refers to an unproxied instance. Bytecode weaving produces a better result, but (a) isn’t always permitted, and (b) doesn’t work well with debuggers. Is it too much to ask for java classes to natively support before/after/around hooks allowing code (an advice) to be attached to methods (at class load or later) in an elegant way? CLOS has it, Perl/Ruby/Javascript all support it. Debuggers should be able to see exactly which methods have been hooked into each class, and properly step into them. Hmm .. and if it supported static methods too, then that might be another way to intercept the “new” operator..

Yes, Aspectj can add AOP advices around arbitrary methods, but it isn’t well integrated into the standard class model. No java.lang.reflection api to see them at runtime, static code analysis tools can’t see them before runtime. Sigh.

Can Father Christmas or his elves write code? A new version of Java with something like the above would be a very welcome present.

Or maybe the Kotlin project can deliver?