`

java Bridge method

阅读更多

 

 bridge method may be created by the compiler when extending a parameterized type whose methods have parameterized arguments.

You can find in this class BridgeMethodResolver a way to get the actual Method referred by a 'bridge method'.

See Create Frame, Synchronize, Transfer Control :

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(String) differs in its signature from that of the compile-time method declaration, C.id(Object) . 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.

See also Bridge:

as mentioned in the comment, bridge methods are also needed for covariant overriding:

  •      In Java 1.4, and earlier, one method can override another if the signatures match exactly.
  •      In Java 5, a method can override another if the arguments match exactly but the return type of the overriding method, if it is a subtype of the return type of the other method.


Typically, a method Object clone() can be overridden by a MyObject clone() , but a bridge method will be generated by the compiler:

 

public bridge Object MyObject.clone();

 

=========================================================

The example shown there (quoted from the JLS) makes it sound like bridge methods are only used in situations where raw types are used. Since this is not the case, I thought I'd pipe in with an example where bridge methods are used for totally type-correct generic code.

Consider the following interface and function:

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);
}

 
If you use this code in the following way, a bridge method is used:

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

applyFunc(lower, "Hello");

 

After erasure, the Function interface contains the method apply(Object)Object (which you can confirm by decompiling the bytecode). Naturally, if you look at the decompiled code for applyFunc you'll see that it contains a call to apply(Object)Object . Object is the upper bound of its type variables, so no other signature would make sense.

So when an anonymous class is created with the method apply(String)String , it doesn't actually implement the Function interface unless a bridge method is created. The bridge method allows all generically typed code to make use of that Function implementation.

Interestingly, only if the class implemented some other interface with the signature apply(String) String and only if the method was called via a reference of that interface type would the compiler ever emit a call with that signature.

Even if I have the following code:

Function<String, String> lower = ...;

lower.apply("Hello");

 

The compiler still emits a call to apply(Object)Object .

There is actually one other way to get the compiler to call apply(String)String , but it takes advantage of the magical type assigned to an anonymous class creation expression which cannot otherwise be written down:

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

=================================================

多角度看 Java 中的泛型

 

======

通过下面的例子可以很清楚看到编译器给我们插入了一些方法的实现

 

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.springframework.util.ReflectionUtils;

/**
 *  用于测试桥接方法
 * @author wenzhihong
 *
 */
interface Enable<T> {
    void say(T t);
    T getInfo();
}

//产生桥接方法
class MyEnable implements Enable<String> {

    @Override
    public String getInfo() {
        return null;
    }

    @Override
    public void say(String t) {
    }
}

//不产生桥接方法
class Other<T> implements Enable<T>{

    @Override
    public T getInfo() {
        return null;
    }

    @Override
    public void say(T t) {
        
    }
}

class MethodInfo{
    Class classInfo;
    String name;
    Class[] paraTypes;
    Class returnType;
    boolean bridge;
    
    @Override
    public String toString() {
        StringBuilder info = new StringBuilder(); 
        info.append(returnType.getSimpleName() + " " + classInfo.getName() + "." + name + "("); 
        for(Class para : paraTypes){
            info.append(para.getSimpleName() + ",");
        }
        if(paraTypes.length > 0){
            info.setCharAt(info.length()-1, ')');
        }else{
            info.append(')');
        }
        
        info.append("  bridge[" + bridge + "]");
        
        return info.toString();
    }
}

public class Test {
    
    public static void main(String[] args) {
        System.out.println("==============产生桥接方法============");
        print(MyEnable.class);
        
        System.out.println("==============不产生桥接方法================");
        print(new Other<String>().getClass());
    }

    private static void print(Class cls) {
        final List<MethodInfo> result = new ArrayList<MethodInfo>();
        
        ReflectionUtils.doWithMethods(cls, new ReflectionUtils.MethodCallback() {
            @Override
            public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                MethodInfo info = new MethodInfo();
                info.classInfo = method.getDeclaringClass();
                info.name = method.getName();
                info.paraTypes = method.getParameterTypes();
                info.returnType = method.getReturnType();
                info.bridge = method.isBridge();
                
                result.add(info);
                
            }
        });
        
        for(MethodInfo info : result){
            System.out.println(info);
        }
    }

}
 

 

执行输出

==============产生桥接方法============
void MyEnable.say(String)  bridge[false]

void MyEnable.say(Object)  bridge[true]

String MyEnable.getInfo()  bridge[false]

Object MyEnable.getInfo()  bridge[true]

void java.lang.Object.finalize()  bridge[false]

void java.lang.Object.wait()  bridge[false]

void java.lang.Object.wait(long,int)  bridge[false]

void java.lang.Object.wait(long)  bridge[false]

int java.lang.Object.hashCode()  bridge[false]

Class java.lang.Object.getClass()  bridge[false]

Object java.lang.Object.clone()  bridge[false]

boolean java.lang.Object.equals(Object)  bridge[false]

void java.lang.Object.registerNatives()  bridge[false]

String java.lang.Object.toString()  bridge[false]

void java.lang.Object.notify()  bridge[false]

void java.lang.Object.notifyAll()  bridge[false]

==============不产生桥接方法================
void Other.say(Object)  bridge[false]

Object Other.getInfo()  bridge[false]

void java.lang.Object.finalize()  bridge[false]

void java.lang.Object.wait()  bridge[false]

void java.lang.Object.wait(long,int)  bridge[false]

void java.lang.Object.wait(long)  bridge[false]

int java.lang.Object.hashCode()  bridge[false]

Class java.lang.Object.getClass()  bridge[false]

Object java.lang.Object.clone()  bridge[false]

boolean java.lang.Object.equals(Object)  bridge[false]

void java.lang.Object.registerNatives()  bridge[false]

String java.lang.Object.toString()  bridge[false]

void java.lang.Object.notify()  bridge[false]

void java.lang.Object.notifyAll()  bridge[false]

 

 

 认真比较输出信息, 相信大家可以很容易理解什么是桥接方法.

 

 

桥接方法也就是编译器给我们加入了, 为了使java的范型字节码和1.5版本前的字节码相兼容.

 

分享到:
评论

相关推荐

    javabridge-1.0.19-cp38-cp38-win_amd64.zip

    from javabridge import start_jvm, get_class, get_method, call_static_method start_jvm() # 启动 JVM StringClass = get_class("java/lang/String") # 获取 Java String 类 printlnMethod = get_method(String...

    javabridge-1.0.18-cp35-cp35m-win_amd64.zip

    from javabridge import get_env, start_vm, call_method start_vm(class_path=["path/to/your/classes"]) # 加载 Java 类 jb_object = get_env().find_class("com/example/YourJavaClass") # 创建 Java 对象 ...

    PHP-Java-Bridge

    2. **部署JavaBridge.jar**:将JavaBridge.jar放在服务器的适当位置,并确保Java守护进程可以访问。 3. **配置PHP**:将Java.inc添加到PHP的include_path中,以便PHP脚本可以轻松地引入和使用。 4. **启动Java守护...

    php调用java,不是http桥接

    如果需要后台运行,可使用`nohup java -jar JavaBridge.jar SERVLET_LOCAL:8080 &gt; JavaBridge.log &`,这样即使关闭终端窗口也能继续运行。 2. **配置PHP项目** - 将`Java.inc`文件放到PHP项目的指定目录(如`...

    JAVA调用C++的dell应用例子

    Jni(Java Native Interface)是sun提供的java与系统中的原生方法交互的技术(在windows\linux系统中,实现java与native method互调)。目前只能由c/c++实现。后两个都是sourceforge上的开源项目,同时也都是基于jni...

    tomcat+php调用jar包文件 JavaBridgeTemplate721.war php版本是7.2

    $url = 'http://your_server:port/JavaBridge/?java=com.example.MyClass&method=myMethod'; // 添加参数,如果有的话 $params = http_build_query(['param1' =&gt; 'value1', 'param2' =&gt; 'value2']); // 使用cURL发送...

    java调用vtk

    Java调用VTK不仅可以实现基本的3D渲染,还可以结合其他Java库,如ParaView Glance或 itk-jvtk-bridge,用于更复杂的可视化任务,如并行计算、大数据可视化和网络应用。 总的来说,Java调用VTK提供了一种在Java环境...

    java操作word文件工具类级dell文件

    在Java中,由于Java本身并不直接支持与Windows API交互,因此需要借助第三方库来实现,其中Jacob(Java COM Bridge)是一个常用的解决方案。 Jacob是一个开源Java库,它提供了Java到COM(Component Object Model)...

    Qt Android 调用JAVA

    bridge.callMethod("callFromQt", "(Ljava/lang/String;)V", QAndroidJniObject::fromString("Hello from Qt").object()); ``` 6. **运行和调试**:确保你的Qt应用和Android项目配置正确,然后在Android设备或...

    bridge-method-annotation-1.13.jar

    javaweb/javaee 常用jar包,亲测可用,若需其他版本其他jar包请留言我看到后会上传分享

    java操作word-jacob

    Jacob全称为Java COM Bridge,它是一个开源的Java库,允许Java应用程序利用COM(Component Object Model)接口来调用Windows上的COM组件,比如Microsoft Office套件中的Word。 在Java中,由于其原生不支持对Office...

    java设计模式(疯狂java联盟版)

    结构型模式如适配器(Adapter)、桥接(Bridge)、组合(Composite)、装饰(Decorator)、外观(Facade)、享元(Flyweight)和代理(Proxy),主要关注如何组合不同的类和对象以实现新的功能。行为型模式如策略...

    java给word文档插入水印并设置保护密码

    JACOB(JavaCOM Bridge)是一个Java到COM桥接库,它允许Java程序调用COM组件,如Microsoft Word。在Java项目中引入JACOB库,你可以通过以下步骤实现: 1. 下载JACOB的jar文件(通常为`jacob.jar`)及其对应的本地...

    java 设计模式 demo

    7. 桥接模式(Bridge):将抽象部分与实现部分分离,使它们可以独立变化。Java中,桥接模式常用于将接口和其实现分离,提高扩展性。 8. 组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构...

    java与模式光盘源码

    桥接模式(Bridge)将抽象部分与其实现部分分离,使它们可以独立变化,提供更大的灵活性。这些模式的组合使用可以帮助开发者构建更复杂、更健壮的系统。 在实际项目中,设计模式的应用可以提高代码的可读性、可维护...

    Java设计模式(疯狂Java联盟版) 

    2. **结构型模式**:结构型模式关注如何将类或对象组合成更大的结构,如适配器模式(Adapter)、装饰器模式(Decorator)、代理模式(Proxy)、桥接模式(Bridge)、组合模式(Composite)、外观模式(Facade)和享...

    scrcpy投屏 AssertionError: java.lang.reflect.InvocationTargetExcep

    2. **更新ADB(Android Debug Bridge)**:ADB是Android开发工具的一部分,用于连接设备和电脑进行调试。如果ADB版本过旧,可能会导致Scrcpy无法正常工作。更新至最新版本的ADB有时可以解决这类问题。 3. **USB调试...

    java设计模式和30种java架构图.zip

    2. 结构型模式:包括适配器(Adapter)、桥接(Bridge)、组合(Composite)、装饰(Decorator)、外观(Facade)、享元(Flyweight)、代理(Proxy),这些模式处理对象的组合和关系。 3. 行为型模式:如责任链...

    java父子资料(答案)

    - **JDBC-ODBC 桥驱动** (`JDBC-ODBC Bridge`): 通过 ODBC 接口与数据库通信。 - **本地库 Java 实现驱动** (`Native Library Implementation Driver`): 通过本地库与数据库通信。 - **网络协议驱动** (`Network ...

    java-design-patterns-master_JAVAdesignpattens_java_design_

    16. **模板方法模式(Template Method Pattern)**:在抽象类中定义了一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 17. **状态模式(State...

Global site tag (gtag.js) - Google Analytics