问题描述
在我看来,这样的switch语句会有很大的意义,但它给出一个编译错误:
It seems to me that such a switch statement would make a lot of sense, but it gives a compile error :
public void m(Class c) {
switch (c) {
case SubClassOfC1.class : //do stuff; break;
case SubClassOfC2.class : //do stuff; break;
}
}
但是,类不支持打开。是什么原因?
However, classes are not supported to switch on. What is the reason why?
我不想解决 instanceof
,它真的在类级别,有一些操作执行,没有实例。
I am not trying to workaround instanceof
, it's really at the class level that I got some operations to perform, no instances there.
编译错误是围绕SubClassOfC1& SubClassOfC2:需要常量表达式。
The compile error is around SubClassOfC1 & SubClassOfC2 : constant expression required.
推荐答案
有趣的是,基本上是说因为规范说了这么,这是正确的,但不是真正令人满意。在Java 7之前,不允许使用 String
,并且经常被视为在石头上雕刻。
Interestingly, all answers so far are basically saying "because the specification says so", which is correct but not really satisfying. Before Java 7, String
s were not allowed and that was often treated like being carved in stone.
障碍不应驱动语言设计。如果没有办法将它编译为高效的代码,它仍然可以编译为等效于 if ... else ...
子句,并且仍然有源代码简洁的胜利。在 String
值的情况下,有一种有效的方法。只需切换不变哈希码,并对匹配候选项执行 equals
检查。事实上,规范没有要求使用散列码,它可以是任何不变的 int
属性,例如。长度或第一个字符,但每个 String
的值应该不同。
But technical obstacles shouldn’t drive language design. If there is no way to compile it to efficient code, it might still get compiled to the equivalent of if … else …
clauses, and still have a win on source code brevity. In the case of String
values, there is an efficient way. Just switch over the invariant hashcode and perform an equals
check on the match candidate. In fact, the specification does not mandate to use the hash code, it could be any invariant int
property, e.g. the length or the first character, but it’s value should be different for each String
.
c $ c>开关超过类
对象是可能的。它的哈希码不是保证是相同的,但每个类都有一个常量名称和一个常量哈希码。例如。以下工作:
Similarly, a switch
over Class
objects is possible. It’s hash code is not guaranteed to be the same, but each class has a constant name with a constant hash code. E.g. the following works:
public class ClassSwitch {
static final class Foo {}
static final class Bar {}
static final class Baz {}
public static void main(String... arg) {
Class<?> cl=Bar.class;
switch(cl.getSimpleName().hashCode()) {
case 70822:
if(cl==Foo.class) {
System.out.println("case Foo:");
}
break;
case 66547:
if(cl==Bar.class) {
System.out.println("case Baz:");
}
break;
case 66555:
if(cl==Baz.class) {
System.out.println("case Baz:");
}
break;
}
}
}
的限定名,使这个示例代码是独立于包的。但我认为,图片是清楚的。对于具有常量 int
属性的任何类型的对象,可以实现高效的 switch
语句,编译时间。也就是说,也没有理由不支持 long
开关。有很多方法可以从 long
...
I used the simple name instead of the qualified name, so that this example code is package independent. But I think, the picture is clear. It is possible to implement efficient switch
statements for any kind of object which has a constant int
property that can be predicted at compile time. That said, there is also no reason not to support long
switches. There are plenty of ways to calculate a suitable int
from a long
…
因此还有其他重要的决定。
So there are another important decisions to make.
这个功能真的是一个好处吗?它看起来像代码气味 - 即使添加 String
支持是有争议的。它不会增加新的可能性,因为你可以对执行相同的操作,如果
- else
HashMap< Class,SomeHandlerType>
用于更大的数字。它并不真的看起来像需要那么频繁的东西,它是值得扩展的语言规范,即使它只是一个单一的句子,必须添加。
Is this feature really a benefit? It looks like code smell—even the addition of String
support was controversial. It does not add new possibilities as you may do the same with if
-else
for a small number of classes or a HashMap<Class,SomeHandlerType>
for bigger numbers. And it doesn’t really look like something that is needed so often, that it is worth expanding the language specification, even if it is just a single sentence that has to be added.
这些都是驱动语言设计的考虑因素,但不是心灵和平衡不能改变。所以我不是说这是不可能的,未来的版本获得这个功能。
These are the considerations that drive the language design, but it’s not that minds and balances cannot change. So I’m not saying that’s impossible that a future version gets this feature.
但是,看起来我想代码我的开关
手动...
But well, looking at the quality of generated String
switch
code I’d rather code my switches
manually…
这篇关于为什么我们不能在Java 7+中打开类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!