Java 冗余类型参数

Java 冗余类型参数,java,generics,Java,Generics,我已经用IntelliJ写了这门课 public class Main { public static void main(String[] args) { Main.<Number>foo(0); Main.<Integer>foo(0); } static <T> void foo(T t) {} } 公共类主{ 公共静态void main(字符串[]args){ Main.foo(0); M

我已经用IntelliJ写了这门课

public class Main  {

    public static void main(String[] args) {
        Main.<Number>foo(0);
        Main.<Integer>foo(0);
    }

    static <T> void foo(T t) {}
}
公共类主{
公共静态void main(字符串[]args){
Main.foo(0);
Main.foo(0);
}
静态void foo(T){}
}
Main.foo(0)不生成任何消息,但在下一行中我得到了消息

可以推断出显式类型参数。 此检查报告对参数化方法的所有调用,其中 显式参数类型可以省略,因为它们将 由编译器明确推断


这对我来说毫无意义。我的理解是所有类型参数都会被擦除,因此类型参数是否不明确并不重要。据我所知,调用返回类型为void的泛型方法时提供类型参数的唯一原因是说服编译器类型
T
存在于所需的范围内。除此之外,您实际提供的参数类型不会有任何区别。因此,如果类型参数在第二种情况下是冗余的,那么在第一种情况下它应该是冗余的。有谁能解释这些消息出现时的规则是如何工作的,以及为什么在这种情况下规则甚至应该依赖于提供的类型参数

我从未见过这条消息,但它看起来像是一个警告

第一个观察结果是,这来自Intellij编译器。当我使用Java8
javac
编译这个时,没有这样的警告消息

另一件需要注意的事情是,在这种情况下,编译器在这里为
T
推断的类型没有区别。我想这就是编译器告诉你的

如果该方法返回
T
,并且您将结果分配给一个变量(例如),那么这可能很重要。例如:

   Integer i = Main.<Integer>foo(0);  // OK
   i = Main.foo(0);                   // OK
   i = Main.<Long>foo(0L);            // Error
   i = Main.foo(0L);                  // Different error message.
Integer i=Main.foo(0);//好啊
i=Main.foo(0);//好啊
i=Main.foo(0L);//错误
i=Main.foo(0L);//不同的错误消息。
在第三种情况下,(
javac
)编译器表示不能将
Long
赋值给
Integer

在最后一种情况下,(
javac
)编译器推断
foo
将返回
Long
,并表示无法分配推断的类型


我不明白为什么要提供类型参数

考虑这样一种情况,
foo
调用的结果被用作重载方法的参数,您需要一个特定的结果类型来让Java调用正确的重载


还值得注意的是,Java8的类型推断比早期版本更复杂。在旧版本的Java中,可能存在推理需要显式类型参数形式的帮助的情况。

我从未见过这条消息,但它看起来像是一个警告

第一个观察结果是,这来自Intellij编译器。当我使用Java8
javac
编译这个时,没有这样的警告消息

另一件需要注意的事情是,在这种情况下,编译器在这里为
T
推断的类型没有区别。我想这就是编译器告诉你的

如果该方法返回
T
,并且您将结果分配给一个变量(例如),那么这可能很重要。例如:

   Integer i = Main.<Integer>foo(0);  // OK
   i = Main.foo(0);                   // OK
   i = Main.<Long>foo(0L);            // Error
   i = Main.foo(0L);                  // Different error message.
Integer i=Main.foo(0);//好啊
i=Main.foo(0);//好啊
i=Main.foo(0L);//错误
i=Main.foo(0L);//不同的错误消息。
在第三种情况下,(
javac
)编译器表示不能将
Long
赋值给
Integer

在最后一种情况下,(
javac
)编译器推断
foo
将返回
Long
,并表示无法分配推断的类型


我不明白为什么要提供类型参数

考虑这样一种情况,
foo
调用的结果被用作重载方法的参数,您需要一个特定的结果类型来让Java调用正确的重载


还值得注意的是,Java8的类型推断比早期版本更复杂。在旧版本的Java中,推理可能需要显式类型参数形式的帮助。

这只是一个警告,说明不需要指定类型

由于
T
是一个对象,不能是原语,因此
0
参数将被装箱为
整数。这意味着编译器将推断
T
表示
Integer
,因此指定它是多余的


无论指定何种类型的参数,参数都会被装箱为整数。例如,
Test.foo(0)
将不会编译,因为
Integer
Long

不兼容。这只是一个警告,说明不需要指定类型

由于
T
是一个对象,不能是原语,因此
0
参数将被装箱为
整数。这意味着编译器将推断
T
表示
Integer
,因此指定它是多余的


无论指定何种类型的参数,参数都会被装箱为整数。例如,
Test.foo(0)
不会编译,因为
Integer
与通用方法文档中的
Long
不兼容

请注意,我们不必将实际的类型参数传递给泛型方法。编译器根据实际参数的类型为我们推断类型参数。它通常会推断出使调用类型正确的最具体的类型参数

由于Integer是您案例中最具体的类型,因此指定它是多余的。因为数字是一种更通用的类型,所以它不是多余的

此外,您还正确地认识到,没有运行时差异