ewo*_*wok 27 java enums types instanceof switch-statement
在开始之前,我知道这个问题有很多答案可以提出替代方法.我正在寻求这种特殊方法的帮助,以确定是否可行,如果不可能,可能会有类似的方法.
我有一个方法,它接受一个超类并根据传递的对象的类型调用一个方法.例如:
public void handle(Object o){
if (o instanceof A)
handleA((A)o);
else if (o instanceof B)
handleB((B)o);
else if (o instanceof C)
handleC((C)o);
else
handleUnknown(o);
Run Code Online (Sandbox Code Playgroud)
我不能修改子类型来覆盖一个handle()方法,正如这个答案所暗示的那样,因为我不拥有这些类.所以这个instanceof方法就是我所拥有的.
我想用一个switch声明代替if/else,只是因为它更整洁.我知道你只能打开基元和字符串,所以我要切换类名:
switch(o.getClass().getCanonicalName()){
case "my.package.A":
handleA((A)o);
break;
case "my.package.B":
handleB((B)o);
break;
case "my.package.C":
handleC((C)o);
break;
default:
handleUnknown(o);
break;
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是规范名称非常长(如12个子包),我不能调用ClassName.class.getCanonicalName()case语句,因为Java不允许这样做.所以我的下一个解决方案是Enum.这是我遇到问题的地方.
我希望我的代码看起来像这样:
public enum Classes {
A (A.getCanonicalName()),
B (B.getCanonicalName()),
C (C.getCanonicalName());
}
switch (o.getClass().getCanonicalName()){
case Classes.A:
handleA((A)o);
break;
case Classes.B:
handleB((B)o);
break;
case Classes.C:
handleC((C)o);
break;
default:
handleUnknown(o);
break;
}
Run Code Online (Sandbox Code Playgroud)
但这不编译.我不知道为什么.我想要一些允许我切换类型而不必输入整个规范名称的方法.如果我这样做,我不妨只使用if/else和instanceof.
注意有几种类型具有相同的名称(内部类),因此getSimpleName()也是如此.
das*_*ght 30
这是一种根本不处理类名的方法,并且调度与switch语句一样快:创建哈希映射以将Class<T>对象映射到特定于类的处理程序,并使用映射而不是switch:
// Declare an interface for your polymorphic handlers to implement.
// There will be only anonymous implementations of this interface.
private interface Handler {
void handle(Object o);
}
// Make a map that translates a Class object to a Handler
private static final Map<Class,Handler> dispatch = new HashMap<Class,Handler>();
// Populate the map in a static initializer
static {
dispatch.put(A.class, new Handler() {
public void handle(Object o) {
handleA((A)o);
}
});
dispatch.put(B.class, new Handler() {
public void handle(Object o) {
handleB((B)o);
}
});
dispatch.put(C.class, new Handler() {
public void handle(Object o) {
handleC((C)o);
}
});
}
// This object performs the dispatch by looking up a handler,
// and calling it if it's available
private static void handle(Object o) {
Handler h = dispatch.get(o.getClass());
if (h == null) {
// Throw an exception: unknown type
}
h.handle(o); // <<== Here is the magic
}
Run Code Online (Sandbox Code Playgroud)
eit*_*tan 24
使用java 8 lambdas你可以得到这样的东西:
Collection col = Arrays.asList(1,2,3);
switchType(col,
caze(Collection.class, c->System.out.println(c.size())),
caze(ArrayBlockingQueue.class, bq->System.out.println(bq.remainingCapacity())),
caze(Queue.class, q->System.out.println(q.poll())),
caze(String.class, s->System.out.println(s.substring(0))),
caze(ArrayList.class, al->System.out.println(al.get(0)))
);
Run Code Online (Sandbox Code Playgroud)
为此,您应该定义以下静态方法:
public static <T> void switchType(Object o, Consumer... a) {
for (Consumer consumer : a)
consumer.accept(o);
}
public static <T> Consumer caze(Class<T> cls, Consumer<T> c) {
return obj -> Optional.of(obj).filter(cls::isInstance).map(cls::cast).ifPresent(c);
}
Run Code Online (Sandbox Code Playgroud)
A_A*_*old 19
Java 目前有一个草案来支持这一点。见这里。语法看起来像这样
switch (obj) {
case Integer i: handleI(i); break;
case Byte b: handleB(b); break;
case Long l: handleL(l); break;
case Double d: handleD(d); break;
case String s: handleS(s); break
default: handle(obj);
}
Run Code Online (Sandbox Code Playgroud)