yujie8409 2012-10-13 08:41
浏览 420
已采纳

关于泛型类方法重写的问题

现在有一个泛型类如下:
public abstract class Parent {

public int toInfo(T t){
    return 0;
}

}
有个子类继承该泛型类:
public class Child extends Parent {

@Override
public int toInfo(String t) {
    return super.toInfo(t);
}

}
现在我获取该子类的所有方法
public class Test {

public static void main(String[] args) {
    Child c = new Child();
    Method[] ms = c.getClass().getMethods();
}

}
发现有两个toInfo方法
1. public int Child.toInfo(java.lang.String)
2. public int Child.toInfo(java.lang.Object)

请问我该如何处理只会得到一个方法public int Child.toInfo(java.lang.String)?

  • 写回答

2条回答 默认 最新

  • jinnianshilongnian 2012-10-13 16:08
    关注

    首先,这个问题在《Java语言规范》中已经提到了,请参考 15.12.4.5 Create Frame, Synchronize, Transfer Control :
    [quote]Discussion
    As an example of such a situation, consider the declarations:

    class C<T> { abstract T id(T x); }
    
    class D extends C<String> { String id(String x) { return x; } }
    

    Now, given an invocation

    C c = new D();
    
    c.id(new Object()); // fails with a ClassCastException
    

    The erasure of the actual method being invoked, D.id(), differs in its signature from that of the compile-time method declaration, C.id(). The former takes an argument of type String while the latter takes an argument of type Object. The invocation fails with a ClassCastException before the body of the method is executed.

    Such situations can only arise if the program gives rise to an unchecked warning (§5.1.9).

    Implementations can enforce these semantics by creating bridge methods. In the above example, the following bridge method would be created in class D:

    Object id(Object x) { return id((String) x); }
    

    This is the method that would actually be invoked by the Java virtual machine in response to the call c.id(new Object()) shown above, and it will execute the cast and fail, as required.[/quote]

    1、对于泛型形参 在实际运行时会进行泛型擦去:
    如:
    [code="java"]class Parent {
    public T toInfo(T t){
    return t;
    }
    }
    class Child extends Parent {
    @Override
    public String toInfo(String t) {
    return t;
    }
    } [/code]

    实际方法的字节码如下:
    [code="java"]public java.lang.String toInfo(java.lang.String);
    Code:
    Stack=1, Locals=2, Args_size=2
    0: aload_1
    1: areturn
    LineNumberTable:
    line 27: 0

    public java.lang.Object toInfo(java.lang.Object);
    Code:
    Stack=2, Locals=2, Args_size=2
    0: aload_0
    1: aload_1
    2: checkcast #2; //class java/lang/String //保证类型是String的
    5: invokevirtual #3; //Method toInfo:(Ljava/lang/String;)Ljava/lang/Strin
    g;
    8: areturn
    LineNumberTable:
    line 23: 0[/code]
    此处我们可以看到多了一个 public java.lang.Object toInfo(java.lang.Object); 此方法叫做bridge方法;

    Java虚拟机规范: 即bridge方法是由编译器产生的 不再源代码中存在的。
    The ACC_BRIDGE flag is used to indicate a bridge method
    generated by the compiler.

    可以参考
    [url]http://stackoverflow.com/questions/289731/what-java-lang-reflect-method-isbridge-used-for[/url]

    Child实际对应的方法为(大体):
    class Child extends Parent {
    @Override
    public String toInfo(String t) {
    return t;
    }
    @Override
    public Object toInfo(Object t) { //这是一个 bridge方法
    return (String)t;
    }
    }

    即public int Child.toInfo(java.lang.Object) 因为泛型信息在编译时要进行泛型擦出,因为为了保证那些如(class Child extends Parent )正常工作,由编译器产生的一个bridge方法。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?