// reflection/NullRobot.java // (c)2021 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. // Using a dynamic proxy to create an Optional import onjava.*; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collections; import java.util.List; import java.util.stream.Stream; class NullRobotProxyHandler implements InvocationHandler { private String nullName; private Robot proxied = new NRobot(); NullRobotProxyHandler(Class type) { nullName = type.getSimpleName() + " NullRobot"; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(proxied, args); } private class NRobot implements Null, Robot { @Override public String name() { return nullName; } @Override public String model() { return nullName; } @Override public List operations() { return Collections.emptyList(); } } } public class NullRobot { public static Robot newNullRobot(Class type) { return (Robot) Proxy.newProxyInstance( NullRobot.class.getClassLoader(), new Class[]{Null.class, Robot.class}, new NullRobotProxyHandler(type)); } public static void main(String[] args) { Stream.of( new SnowRobot("SnowBee"), newNullRobot(SnowRobot.class) ).forEach(Robot::test); } } /* Output: Robot name: SnowBee Robot model: SnowBot Series 11 SnowBee can shovel snow SnowBee shoveling snow SnowBee can chip ice SnowBee chipping ice SnowBee can clear the roof SnowBee clearing roof [Null Robot] Robot name: SnowRobot NullRobot Robot model: SnowRobot NullRobot */