What are "bridge" methods in Java?

Asked

Viewed 118 times

11

I recently had a problem with methods bridge, what occasional in an excellent answer by Victor Stafusa.

But now I realize I don’t know why that method bridge have been created, nor what it means to be a method or not bridge.

So my doubts on the subject:

  • What is a method bridge?
  • How to create methods bridge?
  • Why methods have emerged bridge in the history of Java?
  • What problems they solve?
  • These problems were from the Java language or related to some limitation of the JVM?
  • Does this feature have any parallel in any other language? Which language? What problem in that other language is solved with this?
  • Other languages that target JVM by default need to be alert to the existence of these methods?
  • 3

    To help while Victor doesn’t come to answer :) https://stackoverflow.com/q/5007357/221800. It’s not even good there, I think you’ll have a much better answer here. Just re-read the first paragraph :)

1 answer

11


  • What is a bridge method?

  • How to create bridge methods?

  • Why bridge methods have emerged in the history of Java?

  • What problems they solve?

  • These problems were from the Java language or related to some limitation of the JVM?

The bridge methods are synthetic, that is, who introduces them is the compiler. They were introduced in Java 5 and their purpose is to make the covariance of generic types work at the JVM level.

For example:

class A<T> {
    public int foo(T x) {
        return 42;
    }
}

class B extends A<String> {
    @Override
    public int foo(String x) {
        return 53;
    }
}

Note that the method foo class B override the foo class A. However, the parameters are different.

In Java, a subclass/subinterface method overrides another when: (a) has the same name and (b) parameters of the same type. With the advent of generic types, knowing when superscript occurs is more difficult than before, and to make matters worse, the JVM does not have generic types at runtime due to the type-Rasure (erasing).

Because of type-Rasure, what the JVM sees in the class A at runtime that’s it:

    public int foo(Object x) {
        return 42;
    }

The reason is that generic type T is erased to its base type, ie, Object. In the case of a generic type <X extends Y>, due to type Erasure, all references of the generic type X are seen by the JVM as occurrences of the type Y.

To resolve this incompatibility between method types at the JVM level at runtime, the solution is for the compiler to create a synthetic method in the class B thus:

    public int foo(Object x) {
        return foo((String) x);
    }

There are still other complications due to the type of return. Because in the JVM, for there to be superscripted methods, not only the type of parameters has to be equal, but the type of return as well. Again, this is solved with bridge methods introduced by the compiler that do Casts also with the return value. For example:

import java.lang.reflect.Method;

public class Exemplo {

    class C<X, Y> {
        public X foo1(Y x) {
            return null;
        }

        public int foo2(Y x) {
            return 42;
        }

        public X foo3(int x) {
            return null;
        }
    }

    class D extends C<String, Integer> {
        @Override
        public String foo1(Integer x) {
            return "abc";
        }

        @Override
        public int foo2(Integer x) {
            return 53;
        }

        @Override
        public String foo3(int x) {
            return "xyz";
        }
    }

    public static void main(String[] args) {
        System.out.println("Métodos de C:");
        for (Method m : C.class.getMethods()) {
            if (m.getDeclaringClass() != Object.class) System.out.println(m);
        }
        System.out.println();

        System.out.println("Métodos de D:");
        for (Method m : D.class.getMethods()) {
            if (m.getDeclaringClass() != Object.class) System.out.println(m);
        }
    }
}

Watch the exit:

Métodos de C:
public java.lang.Object Exemplo$C.foo1(java.lang.Object)
public int Exemplo$C.foo2(java.lang.Object)
public java.lang.Object Exemplo$C.foo3(int)

Métodos de D:
public java.lang.Object Exemplo$D.foo1(java.lang.Object)
public java.lang.String Exemplo$D.foo1(java.lang.Integer)
public int Exemplo$D.foo2(java.lang.Object)
public int Exemplo$D.foo2(java.lang.Integer)
public java.lang.String Exemplo$D.foo3(int)
public java.lang.Object Exemplo$D.foo3(int)

Notice that in class D, all three methods foo1, foo2 and foo3 are duplicated. Duplicates using generic base types (Object in this case) are bridge methods. Also note that generic types appear for the class C have been erased to their base types.

Official reference:

  • Does this feature have any parallel in any other language? Which language? What problem in that other language is solved with this?

I don’t know, but I can’t say it doesn’t exist. In the case of languages with dynamic typing such as Python, Javascript and largely (but not at all) PHP, bridge methods would have no sense of existence, but in languages with static typing, they might. At bottom, bridge methods are a gambit to solve a JVM limitation, and therefore, it makes little sense that such a thing exists in most other programming languages.

  • Other languages that target JVM by default need to be alert to the existence of these methods?

Yes, but in very rare cases. Even in Java, bridge methods rarely cause any problems. This only becomes a problem when you are doing some operation with Reflection and the presence of bridge methods gets in your way, just like you did in your previous question. But that kind of circumstance is something quite unusual.

  • 4

    Bitch Ambi, but I already imagined it :D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.