java - 为什么java泛型在运行时只检查String类型的返回值

标签 java generics

我正在阅读《Thinking in java》、《Generics》。在一个例子中(在“边界处的行动”段落)

public class GenericHolder<T> {
    private T obj;
    public void set(T obj) { this.obj = obj; }
    public T get() { return obj; }
    public static void main(String[] args) {
        GenericHolder<String> holder =
        new GenericHolder<String>();
        holder.set("Item");
        String s = holder.get();
    }
} ///:~


public void set(java.lang.Object);
    0: aload_0
    1: aload_1
    2: putfield #2; //Field obj:Object;
    5: return
public java.lang.Object get();
    0: aload_0
    1: getfield #2; //Field obj:Object;
    4: areturn
public static void main(java.lang.String[]);
    470 Thinking in Java Bruce Eckel
    0: new #3; //class GenericHolder
    3: dup
    4: invokespecial #4; //Method "<init>":()V
    7: astore_1
    8: aload_1
    9: ldc #5; //String Item
    11: invokevirtual #6; //Method set:(Object;)V
    14: aload_1
    15: invokevirtual #7; //Method get:()Object;
    18: checkcast #8; //class java/lang/String
    21: astore_2
    22: return

根据反汇编代码第18行,编译器添加了checkcast代码。我想知道是否总是对通用进行这样的检查。我将String替换为Integer并再次尝试,但最终没有找到checkcast代码。对象类型也是如此。

有人能解释一下吗? Java中的String是一个特殊的对象吗?

最佳答案

I replace the String to Integer and tried again, but I didn't find the checkcast code at last.

对我来说,它也为 Integer 生成一个 checkcast:

  0: new    #3; //class GenericHolder
  3: dup
  4: invokespecial  #4; //Method GenericHolder."<init>":()V
  7: astore_1
  8: aload_1
  9: iconst_5
 10: invokestatic   #5; //Method java/lang/Integer.valueOf:(I)
 13: invokevirtual  #6; //Method GenericHolder.set:(Ljava/lang/Object;)V
 16: aload_1
 17: invokevirtual  #7; //Method GenericHolder.get:()Ljava/lang/Object;
 20: checkcast  #8; //class java/lang/Integer
 23: astore_2
 24: return

如您所见,get 方法具有签名 Ljava/lang/Object;checkcast 是为了确保返回的Object确实是一个Integer


编辑:在您作为评论发布的代码中:

0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3; //class b/TestG
6: dup
7: new #4; //class java/lang/Integer
10: dup
11: iconst_2
12: invokespecial #5; //Method java/lang/Integer."<init>":(I)V
15: invokespecial #6; //Method b/TestG."<init>":(Ljava/lang/Object;)V
18: invokevirtual #7; //Method b/TestG.getT:()Ljava/lang/Object;
21: invokevirtual #8; //Method java/io/PrintStream.print:(Ljava/lang/Objec t;)V 
24: return

您将返回值传递给接受对象PrintStream.print。因此,不需要转换返回值。 (checkcast java.lang.Object 总是会通过!)

关于java - 为什么java泛型在运行时只检查String类型的返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6524810/

相关文章:

java - 直接访问通用数组不起作用

java - Eclipse 突出显示事件,右列标记颜色

java - 在 JTable 中移动列后设置列索引

java - 禁用 Java ImageIO 色度子采样

c# - C# 中的通用阶乘函数

c# - 接口(interface) "IRepository<T>"的正确文件名是什么

java - 当RelativeLayout进入ScrollView时,通过触摸移动TextView无法正常工作

java - Jackson 如何创建 JsonObject

c# - 覆盖 ToString() 并添加到 ListBox C#

java - 如何在 Java 中获取 .class 的所有属性?