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条)

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条