java - Java Generics:特定参数类型的静态方法与功能接口不匹配

下面的第一个赋值没有编译,但我不知道为什么,静态方法的方法签名与功能方法签名匹配,尽管它没有使用类型参数。第二行编译得很好,即使除了类型参数化之外它是相同的签名。

这背后的原因是什么?

public class GenericSample<T> {
    public static void staticLambdaMtd(Integer a) {
            
    }   

    public static<X> void staticLambdaMtd2(X a) {
            
    }  

    // Funca<T> fa1 = GenericSample::staticLambdaMtd;//does not compile !

    Funca<T> fa = GenericSample::staticLambdaMtd2;//does compile !      
}
    
interface Funca<A> {
    public void funct(A a);
}

回答1

您正在混合泛型参数 T 和类型 Integer。这是行不通的,因为 TInteger 是不同的类型。

Generics 是不变的。这意味着您只能为 List<Person> 分配具有相同通用参数的另一个列表,即 Person(不是 IntegerCatT)。同样,我们不能将 Funca<Integer> 分配给 Funca<T> 类型的变量。

有关详细信息,请查看 Oracle 提供的此https://docs.oracle.com/javase/tutorial/java/generics/index.html

使用静态方法 staticLambdaMtd(Integer a) 创建的函数只能分配给 Funca<Integer> 类型的变量,而不是 Funca<T> - 即某种任意类型的函数,因为只有 Integer 类型会匹配方法签名,而不是任何类型将在类 GenericSample 实例化时定义的类型(如 StringCatBigDecimal)。

第二条语句编译得很好,因为它不需要任何特定类型。 XT 一样只是一个占位符。并且表达式 GenericSample::staticLambdaMtd2 应该被归类为所谓的 https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.2,即因为您没有提供类型编译器需要从赋值上下文中推断它。

因此,表达式 GenericSample::staticLambdaMtd2 将被推断为类型为 Funca<T> 并且第二条语句将编译得很好。

下面显示的所有分配都是有效的:

// expression on the right could represent only `Funca<Integer>`

Funca<Integer> fa1 = GenericSample::staticLambdaMtd;


// expression on the right can be succefully inferred to 
// a function of any type based on the assingment context on the left

Funca<T> fa = GenericSample::staticLambdaMtd2;      
Funca<String> fa = GenericSample::staticLambdaMtd2;
Funca<BigDecimal> fa = GenericSample::staticLambdaMtd2;

请注意,表达式 GenericSample::staticLambdaMtd2 可以通过提供泛型参数从 poly 表达式转换为“独立形式”(实际上,规范中提供的定义方法引用始终是 poly 表达式,因此我在引号仅表示将忽略分配上下文)。

而我们如何才能打破它:

// that will not compile for the same reason as the the firt statement doesn't compile

Funca<T> fa3 = GenericSample::<Integer>staticLambdaMtd2;

相似文章

随机推荐

最新文章