public class Test{
    public static void main(String[] args){
        testPairEmployee(new Pair<>(new Manager(),new Manager()));
    }
    public static void testPairEmployee(Pair<Employee> p) throws NoSuchMethodException {
        p.testFunc();
    }
}
class Employee{}
class Manager extends Employee{}
class Pair<T>{
    private T first;
    private T second;
    public Pair(T first, T second){
        this.first = first;
        this.second = second;
    }
    public void testFunc() {
        System.out.println(first.getClass().getName() + '\t' + second.getClass().getName());
    }
}

new Pair<>(new Manager(),new Manager())的类型是Pair<Manager>,为什么这段代码能成功运行?

如果您认为它的类型是Pair<Employee>,但当我编写这段代码时:

testPairEmployee((Pair<Employee>)new Pair<>(new Manager(),new Manager()));

我遇到编译错误:

不可转换的类型;不能强制转换 ‘TestGeneration.Pair&lt;TestGeneration.Manager&gt;’至 ‘TestGeneration.Pair&lt;TestGeneration.Employee&gt;

换句话说,编译器清楚地知道它的类型是Pair<Manager>.

为什么?

This part below is due to my unclear presentation. This is actually another question, and I understand why the following code snippet is wrong: because generics are not covariable. Thanks to the two friends who originally posted the answer, I'm sorry for causing you misunderstanding. Friends who see this problem later can ignore this part below.

同样令我惊讶的是,以下代码运行得很好:

Pair<Employee> p2 = new Pair<>(new Manager(), new Manager());

但下面的代码是ERROR:

Pair<Employee> p3 = new Pair<>(new Employee(), new Employee());
Pair<Manager> p4 = new Pair<>(new Manager(), new Manager());
p3 = p4; // ERROR

推荐答案

新的Pair<>(new Manager(),new Manager())型是Pair<Manager>

不,不是的.对于javac 20,我们可以使用--debug=verboseResolution=all查看参数的类型:

Test.java:3: Note: resolving method testPairEmployee in type Test to candidate 0
        testPairEmployee(new Pair<>(new Manager(),new Manager()));
        ^
  phase: BASIC
  with actuals: Pair<Employee>
  with type-args: no arguments
  candidates:
      #0 applicable method found: testPairEmployee(Pair<Employee>)

如您所见,参数的类型是Pair<Employee>.


您还可以看到参数类型不能是Pair<Manager>,因为如果您显式提供Manager作为类型参数:

testPairEmployee(new Pair<Manager>(new Manager(),new Manager()));

代码编译失败:

Test.java:3: error: incompatible types: Pair<Manager> cannot be converted to Pair<Employee>
        testPairEmployee(new Pair<Manager>(new Manager(),new Manager()));
                         ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

Java相关问答推荐

Java JAR环境(JRE)是否支持模块?

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

scanner 如何在执行hasNextLine一次后重新读取整个文件?

Java Swing:初始化身份验证类后未检测到ATM_Interface键事件

基于调车场算法的科学计算器

在执行流和相关操作时,使用Java泛型为2个方法执行相同的操作,但对象不同

有谁能帮我修一下这个吗?使输出变得更加整洁

STREAMS减少部分结果的问题

try 使用预准备语句占位符获取信息时出现Try-With-Resources错误

项目react 堆中doOnComplete()和Subscribe()的第三个参数之间的差异

向Java进程发送`kill-11`会引发NullPointerException吗?

记录是类的语法糖吗?

接受类及其接口的Java类型(矛盾)

如何在Java中的重写方法参数中强制(Enum)接口实现?

使用同步方法中的新线程调用同步方法

Cucumber java-maven-示例表-未定义一步

OpenJDK20:JEP434:Foreign Function&;内存API(第二次预览)

Spring Mapstruct如何获取Lazy初始化实体字段的信息?

Spring Boot Security-每个端点都被403禁止,Spring记录一个BasicErrorController#错误(HttpServlet请求)

JavaFX中ListView中的问题