Posted by & filed under Java, Uncategorized.

One annoyance in Java is having to do instanceof checks on multiple lines. e.g.

if (object instanceof Foo) {
    Foo foo = (Foo)object;
    foo.foo();
}

While this is often a sign of a design failure, there are times when instanceof checks are required often due to framework constraints etc. The above is quite ugly and involves using 3 lines instead of 1 for a single method call. If foo() is a void method we can’t even use the ternary ? : operator to make it more concise.

In c# with Lambdas and Extension methods one can create something like :

    object.When<Foo>(foo => foo.Foo());

Where “When” is an extension method added to all objects which takes a type parameter and a lambda to execute if the type parameter matches. (Implementation available if anyone cares).

Since Java doesn’t have Extension methods or Lambdas yet (Oracle minus minus) we can’t do this. We can however always use reflection and get something like:

package scratchpad;
 
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import static scratchpad.When.when;
 
public class Let {
	public static void main(String... args) {
		Object a = new Foo();
		Object b = "hello world";
 
		when(Foo.class).isTypeOf(a).foo(); // Prints "foo"
		when(Foo.class).isTypeOf(b).foo(); // Does nothing at all
	}
}
 
class Foo {
	public void foo() {
		System.out.println("foo");
	}
}
 
class When {
	public static <T> Is<T> when(final Class<T> cls) {
		return new Is<T>() {
			@SuppressWarnings("unchecked")
			public T isTypeOf(Object o) {
				return o != null && cls.isAssignableFrom(o.getClass()) 
					? (T)o
					: NullObject.create(cls);
			}
 
		};
	}
 
	public interface Is<T> {
		public T isTypeOf(Object o);
	}
}
 
class NullObject implements MethodInterceptor  {
 
	@SuppressWarnings("unchecked")
	public static <T> T create(Class<T> cls){
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(cls);
		enhancer.setCallback(new NullObject());
		return (T)enhancer.create();
	}
 
	public Object intercept(Object o, Method method, Object[] os, MethodProxy mp) throws Throwable {
		return null;
	}
}

Tags:

Leave a Reply

  • (will not be published)