Java 为什么编译器在静态调用时会接受无效的语法调用(方法)?

Java 为什么编译器在静态调用时会接受无效的语法调用(方法)?,java,generics,methods,Java,Generics,Methods,是否有一个原因使得Java泛型方法在没有静态/实例引用的情况下不能被调用?类似于示例代码中的案例2和案例5 换句话说,为什么我们可以在没有静态/实例引用的情况下调用普通方法,就像在案例3中那样,而在泛型方法中我们不能这样做 public class MyClass { public static void main(String[] args) { MyClass.<String>doWhatEver("Test Me!"); // case 1 <Str

是否有一个原因使得Java泛型方法在没有静态/实例引用的情况下不能被调用?类似于示例代码中的案例2和案例5

换句话说,为什么我们可以在没有静态/实例引用的情况下调用普通方法,就像在案例3中那样,而在泛型方法中我们不能这样做

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);
}

}
您不需要为案例1和4指定,编译器将为您处理此问题。 现在让我们试着运行您的示例,看看会发生什么。 线程主java.lang.RuntimeException中的异常:不可编译 源代码-表达式的开头非法

就这么简单,你的问题的答案是因为语法是无效的,在javac规范中不是这样使用的

然而,这与是否是静态无关。在构造函数中尝试将静态关键字删除到doWhatEver方法:

这纠正了你的语法错误,但为什么

试着编译这两行代码

MyClass.<String>doWhatEver("Test Me2!");
MyClass.doWhatEver("Test Me3!");
在调用非静态方法的情况下,生成的字节码将改为invokevirtual:

17: invokevirtual #8                  // Method doWhatEver2:(Ljava/lang/Object;)V
我猜invokestatic将直接在常量池中搜索,其中存储了与指定调用相对应的方法的静态方法,并将ommit类型声明,而invokevirtual将在实际类中搜索

您不需要为案例1和4指定,编译器将为您处理此问题。 现在让我们试着运行您的示例,看看会发生什么。 线程主java.lang.RuntimeException中的异常:不可编译 源代码-表达式的开头非法

就这么简单,你的问题的答案是因为语法是无效的,在javac规范中不是这样使用的

然而,这与是否是静态无关。在构造函数中尝试将静态关键字删除到doWhatEver方法:

这纠正了你的语法错误,但为什么

试着编译这两行代码

MyClass.<String>doWhatEver("Test Me2!");
MyClass.doWhatEver("Test Me3!");
在调用非静态方法的情况下,生成的字节码将改为invokevirtual:

17: invokevirtual #8                  // Method doWhatEver2:(Ljava/lang/Object;)V

我猜invokestatic将直接在常量池中搜索,其中存储了与指定调用对应的方法的静态方法,并将ommit类型声明,而invokevirtual将在实际类中搜索。

AFAIK someMethod不是有效语法。.这是语法错误。您不需要,编译器通常会推断出正确的类型。@AdrianLeonhard是的,我知道,但不是语法错误,如果您对案例2和案例5进行注释,它将编译并运行。有些情况下,某些API必须使用这些语法。@RC。你在哪里看到这个?这是一种方法。这是合法的code@NESPowerGlove是的,因为您可以使用普通方法在没有实例/静态引用的情况下调用,而不能使用泛型方法…AFAIK someMethod不是有效语法..这是语法错误。您不需要,编译器通常会推断出正确的类型。@AdrianLeonhard是的,我知道,但不是语法错误,如果您对案例2和案例5进行注释,它将编译并运行。有些情况下,某些API必须使用这些语法。@RC。你在哪里看到这个?这是一种方法。这是合法的code@NESPowerGlove是的,因为你可以用一个普通的方法调用而不用实例/静态引用,而一个通用的方法你不能…非常好的答案,tnx太多了。我刚刚找到了语法规范。规则是,如果是泛型方法,则必须使用super/this/reference变量/或Class(如果是静态的)调用。回答得很好,tnx太多了。我刚刚找到了语法规范。规则是,如果是泛型方法,则必须使用super/this/reference变量或类(如果是静态的)调用。
17: invokevirtual #8                  // Method doWhatEver2:(Ljava/lang/Object;)V