java - 泛型方法和泛型类中的类型推断

标签 java generics

无法理解 Java 中的泛型编程。

我阅读了一些有关它的教程,但仍然很困惑,尤其是当事情变得复杂的时候。

谁能解释一下这个例子中发生了什么?

import java.util.Date;

public class Test1 {

    public static void main(String[] args) {
        P<Cls> p = new P<>();   //<1>   //I expect a ClassCastException here, but no. Why? //How does the type inference for class P<E> work? 
        System.out.println(p.name); //it prints
//      System.out.println(p.name.getClass());//but this line throws ClassCastException //why here? why not line <1>?

        test1(p);//it runs
//      test2(p);//throws ClassCastException//What is going on in method test1&test2? 
                //How does the type inference for generic methods work in this case?
        }


    public static<T> void test1(P<? extends T> k){
        System.out.println(k.name.getClass());
    }

    public static<T extends Cls> void test2(P<? extends T> k){
        System.out.println(k.name.getClass());
    }
}

class P<E>{
    E name = (E)new Date();//<2>
}

class Cls{}

最佳答案

P<Cls> p = new P<>();

请记住,Java 通过删除 实现泛型,这意味着P 的构造函数真的不知道什么E在运行时。 Java 中的泛型纯粹是为了在编译时帮助开发人员。

这意味着当您创建一个 new P<>() , 一个 new Date()已创建,但它实际上并未转换为任何特定类型,因为运行时对 E 一无所知EP<E>而言,在运行时不存在类(Class)有关。 name只是一个 Object具有 Date 的引用里面。但是,任何时候您编写的代码都会消耗 name在某种程度上,运行时环境需要知道它是特定类型(在本例中为 Cls),编译器会在不告诉您的情况下插入对该类型的强制转换。

  • p.name.getClass()被编译为 ((Cls)p.name).getClass() ,这将创建一个类转换异常。
  • test2()指定非泛型的类型约束 ( extends Cls )。所以它调用p.name.getClass()同样被翻译成((Cls)p.name).getClass() .

另一方面:

  • System.out.println(p.name)实际上与System.out.println((Object)p.name)相同因为println是一种非泛型方法,采用 object .
  • test1(p.name)很相似。因为运行时实际上不知道是什么类型 T是,它基本上转换 p.name作为Object打电话前getClass()在上面。

换句话说,这是您实际编译的代码:

class P{
    Object name = new Date();
}

public static void main(String[] args) {
    P p = new P();   
    System.out.println(p.name);
    System.out.println(((Cls)p.name).getClass());

    test1(p);
    test2(p);
}


public static void test1(P k){
    System.out.println(k.name.getClass());
}

public static void test2(P k){
    System.out.println(((Cls)k.name).getClass());
}

关于java - 泛型方法和泛型类中的类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26314668/

相关文章:

java - 有没有办法从后端服务器使用 google play 应用内产品?

java - 仅限消费者的 kotlin 泛型

java - 无法使用有界通配符传递通用子类的内部类

java - 通配符(?) 有效,而类型 "T"在泛型中无效 - 为什么?

java - SwingWorker Java Swing 内的计时器应用程序不起作用

java - 你能在一个 SQL 语句中返回多个 COUNTs 吗?

java - 捕获从构造函数的 cflow 内进行的调用

java - Bufferedreader 和通过 ASCII 编码的文件

java - 为什么 .getClass 强制我使用扩展?

.net - 如何将 Cookie 集合转换为通用列表?容易地