Java泛型类型方法返回错误的类型

标签 java generics casting

时不时地,我觉得我根本不懂 Java.. 我最近发现了 Java 类型转换的这种奇怪行为:

public static void main(String[] args) {
    String res = get();
    System.out.println(res);
}

public static <T> T get() {
    Object longObj = Long.valueOf("0");
    T casted = (T) longObj;
    System.out.println("longObj=" + longObj.getClass());
    System.out.println("casted=" + casted.getClass()); // <-- Why the type of "casted" is Long instead of String???
    return casted;
}

输出是:

longObj=class java.lang.Long
casted=class java.lang.Long
Exception in thread "main" java.lang.ClassCastException: java.lang.Long 
cannot be cast to java.lang.String
    at com.apple.geo.coreloc.Test.main(Test.java:5)

我的困惑是:为什么变量 casted 的类型是 Long?不应该强制转换为类型T,即String吗?

以下是我认为它应该是 String 的原因:

  • 在运行时,String res = get() 提示 get() 方法返回一个 String
  • T casted = (T) longObj; 应该尝试将 Long 类型转换为 String(我希望这里有异常,但没有......)

最佳答案

泛型是编译时检查。它们不是编写糟糕类型转换的保障措施。

你试图做 (String) longIbj;其中 longObj很长。那会给你一个运行时 ClassCastException .

但是,因为它不是 T get() 上下文中的编译时错误T get()编译正确。由于“类型删除”,T 被提升为最高约束类型。您没有限制类型的上限,因此您的编译器处理的代码大致如下所示:

public static Object get() {
    Object longObj = Long.valueOf("0");
    Object casted = (Object) longObj;
    System.out.println("longObj=" + longObj.getClass());
    System.out.println("casted=" + casted.getClass()); // <-- Why the type of "casted" is Long instead of String???
    return casted;
}

<T>是一个 Object填充 longObj 的两行代码和 casted大致相同。在任何情况下,通过任一名称​​引用 对对象的多态调用仍将解析为对象的 .getClass()。方法,它仍然会返回 java.lang.Long .

Java 中的转换不会创建新对象。如果你想要一个不同的对象,你需要 new一个不同的对象并用相关信息填充它。在 java 中进行转换只会让您通过转换类型的方法名称访问该类。所以你可能会输 getLong()Long转换为 Object但它仍然存在(如果您通过 Long 类型的变量调用它。

关于Java泛型类型方法返回错误的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46895118/

相关文章:

java - 使用 simpleDateFormat 解析异常

java - 检查arraylist中是否存在具有特定坐标的圆?

java - Libgdx - 处理同一 Actor 的不同动画

scala - 概括一个 "next permutation"函数

c# - Reflection.Emit 实现接口(interface)的泛型方法约束

c - 为什么当你用字符串初始化一个没有 const 的数组时 gcc 不给出警告?

java - 如何使用 Selenium WebDriver 获取 HTTP 响应代码

java - 如何将有界泛型扩展为另一个有界泛型?

c - 为什么通过强制转换重新解释的 C 内存字段在常规强制转换和通过指针强制转换之间有所不同?

c# - 将列表<baseclass> 转换为列表<衍生类>