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

pro*_*avi 2 java generics covariance java-8 method-reference

下面的第一个作业无法编译,但我不确定为什么,静态方法的方法签名与函数方法签名匹配,尽管它不使用类型参数。尽管第二行除了类型参数化之外具有相同的签名,但编译良好。

这背后的原因是什么?

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);
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*nko 6

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

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

有关详细信息,请查看Oracle 提供的本教程。

使用静态方法创建的函数staticLambdaMtd(Integer a)只能分配给类型为 的变量Funca<Integer>,但不能Funca<T>分配给任意类型的函数,因为只有Integer类型会与方法签名匹配,但不能与class 时定义的任何类型(如StringCat、 )相匹配BigDecimalGenericSample )相匹配将被实例化。

第二条语句编译得很好,因为它不需要任何特定类型。X只是一个占位符,以及T. 表达式GenericSample::staticLambdaMtd2应该被归类为所谓的多表达式,即因为您没有提供类型编译器需要从赋值上下文中推断它。

因此,表达式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;
Run Code Online (Sandbox Code Playgroud)

请注意,通过提供通用参数,可以将表达式从聚合GenericSample::staticLambdaMtd2表达式转换为“独立形式” (事实上,规范中提供的定义方法引用始终是聚合表达式,因此我在引号中使用了“独立”含义)仅该赋值上下文将被忽略)。

我们如何打破它:

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

Funca<T> fa3 = GenericSample::<Integer>staticLambdaMtd2;
Run Code Online (Sandbox Code Playgroud)