是否有理由在方法之前没有静态/实例引用时无法调用Java Generic方法?喜欢"案例2"和"案例5"关于示例代码。
换句话说,为什么我们可以在没有静态/实例引用的情况下调用普通方法(例如在"案例3和#34;中),在通用方法中我们可以调用
public class MyClass {
public static void main(String[] args) {
MyClass.<String>doWhatEver("Test Me!"); // case 1
<String>doWhatEver("Test Me2!"); // case 2 COMPILE ERROR HERE
doSomething("Test Me 3!"); // case 3 (just for compare)
new MyClass().<String>doMoreStuff("Test me 4"); // case 4
}
public void doX(){
<String>doMoreStuff("test me 5"); // case 5 COMPILE ERROR HERE
}
public static <T> void doWhatEver(T x){
System.out.println(x);
}
public static void doSomething(String x){
System.out.println(x);
}
public <T> void doMoreStuff(T x){
System.out.println(x);
}
}
答案 0 :(得分:4)
<String>
,编译器将为您处理此问题。线程“main”中的异常java.lang.RuntimeException:Uncompilable 源代码 - 非法开始表达
这很简单,你的问题的答案是因为语法无效,并不意味着在javac
规范中以这种方式使用。
但是,这与static
无关。在构造函数中尝试将static关键字删除到doWhatEver
方法:
public MyClass()
{
<String>doWhatEver("Test Me2!"); //does not compile
doWhatEver("Test Me2!"); //compile
}
public <T> void doWhatEver(T x){
System.out.println(x);
}
现在,如果你想知道为什么MyClass.<String>doWhat..
编译而<String>doWhat..
没有编译,即使我们修改了static关键字,让我们看一下生成的字节码。
您的专栏将编译为:
6: invokestatic #5 // Method doWhatEver:(Ljava/lang/Object;)V
哪个更正了你的语法错误,但为什么?。
尝试编译例如这两行
MyClass.<String>doWhatEver("Test Me2!");
MyClass.doWhatEver("Test Me3!");
然后在.class文件上运行javap -v
,您会注意到两个调用都被编译为相同的字节码。
4: ldc #4 // String Test Me2!
6: invokestatic #5 // Method doWhatEver:(Ljava/lang/Object;)V
9: ldc #6 // String Test Me3!
11: invokestatic #5 // Method doWhatEver:(Ljava/lang/Object;)V
如果你调用非静态方法,生成的字节码将改为invokevirtual
:
17: invokevirtual #8 // Method doWhatEver2:(Ljava/lang/Object;)V
我的猜测是invokestatic
将直接在常量池(存储静态方法)中搜索与指定调用相对应的方法,并将省略类型声明,而invokevirtual
将搜索实际的班级。