代码之家  ›  专栏  ›  技术社区  ›  Nrj

IsBridge用于什么方法?

  •  27
  • Nrj  · 技术社区  · 16 年前

    在导航期间 java.lang.reflect.Method 我遇到了方法 isBridge . 它的Javadoc说,只有当Java规范声明方法为true时,它才返回真。

    请帮助我理解这是用来做什么的!如果需要,自定义类能否将其方法声明为桥?

    3 回复  |  直到 6 年前
        1
  •  27
  •   VonC    12 年前

    在扩展方法具有参数化参数的参数化类型时,编译器可以创建桥接方法。

    你可以在这节课上找到 BridgeMethodResolver 一种获取“桥方法”引用的实际方法的方法。

    Create Frame, Synchronize, Transfer Control :

    作为这种情况的一个例子,考虑声明:

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

    现在,给出一个调用

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

    正在调用的实际方法的擦除, D.id(String) 它的签名与编译时方法声明的签名不同, C.id(Object) . 前者接受字符串类型的参数,而后者接受对象类型的参数。在执行方法体之前,调用失败,并带有ClassCastException。

    只有程序发出未经检查的警告时,才会出现这种情况。( §5.1.9 )

    实现可以通过创建桥接方法来加强这些语义。在上面的示例中,将在类D中创建以下Bridge方法:

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

    这是由Java虚拟机响应调用而实际调用的方法。 c.id(new Object()) 如上所示,它将根据需要执行强制转换和失败。

    也见 Bridge :

    如评论中所述,桥梁方法也需要 协变覆盖 :

    • 在Java 1.4和更早的版本中,如果签名匹配,则一种方法可以重写另一种方法。 确切地。
    • 在Java 5中,如果参数完全匹配,则方法可以重写另一个方法。 但是返回类型 如果重写方法是 亚型 其他方法的返回类型。

    通常,一种方法 Object clone() 可以被重写 MyObject clone() ,但编译器将生成一个网桥方法:

    public bridge Object MyObject.clone();
    
        2
  •  3
  •   samskivert    15 年前

    这里所示的例子(引用自JLS)听起来就像桥梁方法只在使用原始类型的情况下使用。由于情况并非如此,我想我将介绍一个示例,其中使用桥接方法来完全正确地输入泛型代码。

    考虑以下接口和功能:

    public static interface Function<A,R> {
        public R apply (A arg);
    }
    public static <A, R> R applyFunc (Function<A,R> func, A arg) {
        return func.apply(arg);
    }
    

    如果按以下方式使用此代码,将使用Bridge方法:

    Function<String, String> lower = new Function<String, String>() {
        public String apply (String arg) {
            return arg.toLowerCase();
        }
    };
    applyFunc(lower, "Hello");
    

    擦除后, Function 接口包含方法 apply(Object)Object (您可以通过对字节码进行反编译来确认)。当然,如果您查看 applyFunc 您将看到它包含一个呼叫 应用(对象)对象 . Object 是其类型变量的上限,因此没有其他签名有意义。

    因此,当使用方法创建匿名类时 apply(String)String ,它实际上没有实现 功能 接口,除非创建了Bridge方法。bridge方法允许所有一般类型的代码使用它 功能 实施。

    有趣的是,只有当类实现了 其他 与签名的接口 应用(字符串)字符串 而且,只有通过该接口类型的引用调用该方法,编译器才会发出具有该签名的调用。

    即使我有以下代码:

    Function<String, String> lower = ...;
    lower.apply("Hello");
    

    编译器仍然发出对 应用(对象)对象 .

    实际上还有另一种方法可以让编译器调用 应用(字符串)字符串 但它利用了分配给匿名类创建表达式的神奇类型,而匿名类创建表达式不能被写下来:

    new Function<String, String>() {
        public String apply (String arg) {
            return arg.toLowerCase();
        }
    }.apply("Hello");
    
        3
  •  0
  •   Jesse Glick    11 年前

    我偶然发现的另一个案例与仿制药无关:

    protected abstract class Super {
        public void m() {}
    }
    public class Sub extends Super {}
    assert Sub.class.getMethod("m").isBridge();