Java 8 和 Java 7 与类型参数绑定中的泛型方法有什么区别?
What's the difference between Java 8 and Java 7 related to generic methods in type parameter bound?
public class GenMethodDemo2 {
static <T, V extends T> boolean isIn(T x, V[] y){
for (int i = 0; i < y.length; i++) {
if (x.equals(y[i])) return true;
}
return false;
}
@Test
public void test(){
Integer[] nums = {1,2,3,4,5};
if(isIn("java",nums)) System.out.println("java is in nums");
if(!isIn("java",nums)) System.out.println("java is not in nums");
}
}
当我使用 jdk8 这段代码时 运行 很好,结果是 java is not in nums
但是当我换成jdk7时,同样的代码无法编译,提示信息是Inferred type 'java.lang.Integer' for type parameter 'V' is not within its bound; should extend 'java.lang.String'
我想知道:当函数显式定义类型参数绑定时,jdk8 如何编译这段代码V extends T
?
我相信与 Java 7 相比,Java 8 中泛型方法的类型推断有一些改进,但我不确定它能否解释您所看到的差异。在任何情况下,当推理失败时,您始终可以显式提供类型见证以向编译器证明存在满足边界的类型,例如:
if (GenMethodDemo2.<Object, Integer>isIn("java",nums))
System.out.println("java is in nums");
在这种情况下,类型变量 T
和 V
总是可以选择为 Object
,并且它不会接受任何更少的参数集(因为任何 T
将是 Object
的子类型,任何 V[]
将是 Object[]
的子类型)。所以你的方法实际上不需要任何泛型:
static boolean isIn(Object x, Object[] y){
for (int i = 0; i < y.length; i++) {
if (x.equals(y[i])) return true;
}
return false;
}
签名喜欢
static <T, V extends T> boolean isIn(T x, V[] y)
并不比
好多少
static boolean isIn(Object x, Object[] y)
因为调用者总是可以对 T
使用 Object
,这允许任意对象作为第一个参数,以及数组元素的任意引用类型。
因此,当您将方法更改为
@Test
public void test(){
Integer[] nums = {1,2,3,4,5};
if(GenMethodDemo2.<Object,Integer>isIn("java",nums))
System.out.println("java is in nums");
if(!GenMethodDemo2.<Object,Integer>isIn("java",nums))
System.out.println("java is not in nums");
}
它可以在所有 Java 支持泛型的版本中编译。
由于协变数组,也可以指定
if(GenMethodDemo2.<Object,Object>isIn("java",nums))
System.out.println("java is in nums");
if(!GenMethodDemo2.<Object,Object>isIn("java",nums))
System.out.println("java is not in nums");
Java8 的类型推断不会改变哪个方法调用是有效的,它只会使执行有效调用变得更容易,因为您需要显式指定类型参数的场景更少。
public class GenMethodDemo2 {
static <T, V extends T> boolean isIn(T x, V[] y){
for (int i = 0; i < y.length; i++) {
if (x.equals(y[i])) return true;
}
return false;
}
@Test
public void test(){
Integer[] nums = {1,2,3,4,5};
if(isIn("java",nums)) System.out.println("java is in nums");
if(!isIn("java",nums)) System.out.println("java is not in nums");
}
}
当我使用 jdk8 这段代码时 运行 很好,结果是 java is not in nums
但是当我换成jdk7时,同样的代码无法编译,提示信息是Inferred type 'java.lang.Integer' for type parameter 'V' is not within its bound; should extend 'java.lang.String'
我想知道:当函数显式定义类型参数绑定时,jdk8 如何编译这段代码V extends T
?
我相信与 Java 7 相比,Java 8 中泛型方法的类型推断有一些改进,但我不确定它能否解释您所看到的差异。在任何情况下,当推理失败时,您始终可以显式提供类型见证以向编译器证明存在满足边界的类型,例如:
if (GenMethodDemo2.<Object, Integer>isIn("java",nums))
System.out.println("java is in nums");
在这种情况下,类型变量 T
和 V
总是可以选择为 Object
,并且它不会接受任何更少的参数集(因为任何 T
将是 Object
的子类型,任何 V[]
将是 Object[]
的子类型)。所以你的方法实际上不需要任何泛型:
static boolean isIn(Object x, Object[] y){
for (int i = 0; i < y.length; i++) {
if (x.equals(y[i])) return true;
}
return false;
}
签名喜欢
static <T, V extends T> boolean isIn(T x, V[] y)
并不比
好多少static boolean isIn(Object x, Object[] y)
因为调用者总是可以对 T
使用 Object
,这允许任意对象作为第一个参数,以及数组元素的任意引用类型。
因此,当您将方法更改为
@Test
public void test(){
Integer[] nums = {1,2,3,4,5};
if(GenMethodDemo2.<Object,Integer>isIn("java",nums))
System.out.println("java is in nums");
if(!GenMethodDemo2.<Object,Integer>isIn("java",nums))
System.out.println("java is not in nums");
}
它可以在所有 Java 支持泛型的版本中编译。
由于协变数组,也可以指定
if(GenMethodDemo2.<Object,Object>isIn("java",nums))
System.out.println("java is in nums");
if(!GenMethodDemo2.<Object,Object>isIn("java",nums))
System.out.println("java is not in nums");
Java8 的类型推断不会改变哪个方法调用是有效的,它只会使执行有效调用变得更容易,因为您需要显式指定类型参数的场景更少。