Reputation: 13190
My old code create a FrameBody subclass based on identifier
Class<AbstractID3v2FrameBody> c = (Class<AbstractID3v2FrameBody> Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier);
Class<?>[] constructorParameterTypes = {Class.forName("java.nio.ByteBuffer"), Integer.TYPE};
Object[] constructorParameterValues = {byteBuffer, frameSize};
Constructor<AbstractID3v2FrameBody> construct = c.getConstructor(constructorParameterTypes);
frameBody = (construct.newInstance(constructorParameterValues));
But profile analysis shows its a bit slow, the alternative to using reflecting is a big switch statement
switch(identifier)
{
case ID3v24Frames.FRAME_ID_AUDIO_ENCRYPTION:
frameBody = new FrameBodyAENC(byteBuffer, frameSize);
break;
case ID3v24Frames.FRAME_ID_ATTACHED_PICTURE:
frameBody = new FrameBodyAPIC(byteBuffer, frameSize);
break;
.......
}
but I have over 100 identifiers, so its seems a bit cumbersome
Is there a more elegant way to do this in Java 8 ?
Upvotes: 1
Views: 768
Reputation: 120848
EDIT:
This can be simplified indeed as Holger suggests:
Map<String, BiFunction<ByteBuffer, Integer, AbstractID3v2FrameBody>> LOOKUP = Map.of(
FRAME_ID_AUDIO_ENCRYPTION, FrameBodyAENC::new,
FRAME_ID_ATTACHED_PICTURE, FrameBodyAPIC::new
);
And then as simple as:
LOOKUP.get(ID3v24Frames.FRAME_ID_AUDIO_ENCRYPTION)
.apply(byteBuffer, frameSize);
PREVIOUS SUGGESTION
This is just a sample, you will need to adapt it to your classes:
private static final Lookup L = MethodHandles.lookup();
private static final MethodHandle CONS;
static {
try {
CONS = L.findConstructor(SomeClass.class, MethodType.methodType(void.class, int.class));
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
private static final Map<String, MethodHandle> LOOK_UP = Map.of(
"SOME_CLASS", CONS
);
public static void main(String[] args) {
try {
SomeClass sc = (SomeClass) LOOK_UP.get("SOME_CLASS").invokeExact(42);
System.out.println(sc.getX());
} catch (Throwable t) {
t.printStackTrace();
}
}
static class SomeClass {
private final int x;
public SomeClass(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
Upvotes: 2