Java 冗余类型参数
我已经用IntelliJ写了这门课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
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编译器。当我使用Java8javac
编译这个时,没有这样的警告消息
另一件需要注意的事情是,在这种情况下,编译器在这里为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编译器。当我使用Java8javac
编译这个时,没有这样的警告消息
另一件需要注意的事情是,在这种情况下,编译器在这里为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是您案例中最具体的类型,因此指定它是多余的。因为数字是一种更通用的类型,所以它不是多余的
此外,您还正确地认识到,没有运行时差异