Is it possible to use the instanceof operator in a switch statement?
This is a typical scenario where subtype polymorphism helps. Do the following
interface I { void do();}class A implements I { void do() { doA() } ... }class B implements I { void do() { doB() } ... }class C implements I { void do() { doC() } ... }
Then you can simply call do()
on this
.
If you are not free to change A
, B
, and C
, you could apply the visitor pattern to achieve the same.
if you absolutely cannot code to an interface, then you could use an enum as an intermediary:
public A() { CLAZZ z = CLAZZ.valueOf(this.getClass().getSimpleName()); switch (z) { case A: doA(); break; case B: doB(); break; case C: doC(); break; }}enum CLAZZ { A,B,C;}
Create a Map
where the key is Class<?>
and the value is an expression (lambda or similar). Consider:
Map<Class,Runnable> doByClass = new HashMap<>();doByClass.put(Foo.class, () -> doAClosure(this));doByClass.put(Bar.class, this::doBMethod);doByClass.put(Baz.class, new MyCRunnable());// of course, refactor this to only initialize oncedoByClass.get(getClass()).run();
If you need checked exceptions than implement a FunctionalInterface
that throws the Exception
and use that instead of Runnable
.
Here's a real-word before-and-after showing how this approach can simplify code.
The code before refactoring to a map:
private Object unmarshall( final Property<?> property, final Object configValue ) { final Object result; final String value = configValue.toString(); if( property instanceof SimpleDoubleProperty ) { result = Double.parseDouble( value ); } else if( property instanceof SimpleFloatProperty ) { result = Float.parseFloat( value ); } else if( property instanceof SimpleBooleanProperty ) { result = Boolean.parseBoolean( value ); } else if( property instanceof SimpleFileProperty ) { result = new File( value ); } else { result = value; } return result;}
The code after refactoring to a map:
private final Map<Class<?>, Function<String, Object>> UNMARSHALL = Map.of( SimpleBooleanProperty.class, Boolean::parseBoolean, SimpleDoubleProperty.class, Double::parseDouble, SimpleFloatProperty.class, Float::parseFloat, SimpleFileProperty.class, File::new);private Object unmarshall( final Property<?> property, final Object configValue ) { return UNMARSHALL .getOrDefault( property.getClass(), ( v ) -> v ) .apply( configValue.toString() );}
This avoids repetition, eliminates nearly all branching statements, and simplifies maintenance.