Java Generics-метод моста?


что-то под названием "Метод моста" концепция, связанная с Java Generics заставил меня остановиться в точке и подумать над этим.

кстати, я знаю только, что это происходит в байт-код уровня и не доступен для нас, чтобы использовать.

но я очень хочу знать концепцию "метода моста", используемого компилятором Java.

Что именно происходит за кулисами и почему он используется?

помощь с примером будет очень признателен.

3   51   2011-02-15 20:48:40

3 ответа:

это метод, который позволяет классу, расширяющему универсальный класс или реализующий универсальный интерфейс (с конкретным параметром типа), по-прежнему использоваться в качестве необработанного типа.

представьте себе, это:

public class MyComparator implements Comparator<Integer> {
   public int compare(Integer a, Integer b) {
      //
   }
}

это не может быть использовано в сыром виде, передавая два ObjectS Для сравнения, потому что типы компилируются в методе сравнения (вопреки тому, что произошло бы, если бы это был параметр универсального типа T, где тип был бы стерт). Так что вместо этого, за кулисами, компилятор добавляет "метод моста", который выглядит примерно так (был ли это источник Java):

public class MyComparator implements Comparator<Integer> {
   public int compare(Integer a, Integer b) {
      //
   }

   //THIS is a "bridge method"
   public int compare(Object a, Object b) {
      return compare((Integer)a, (Integer)b);
   }
}

компилятор защищает доступ к методу bridge, обеспечивая, чтобы явные вызовы непосредственно к нему приводили к ошибке времени компиляции. Теперь класс можно использовать и в сыром виде:

Object a = 5;
Object b = 6;

Comparator rawComp = new MyComparator();
int comp = rawComp.compare(a, b);

зачем еще это нужно?

в дополнение к добавлению поддержки явного использования необработанных типов (в основном для обратной совместимости) также используются методы моста требуется для поддержки стирания типа. С типом стирания, метод, как это:

public <T> T max(List<T> list, Comparator<T> comp) {
   T biggestSoFar = list.get(0);
   for ( T t : list ) {
       if (comp.compare(t, biggestSoFar) > 0) {
          biggestSoFar = t;
       }
   }
   return biggestSoFar;
}

на самом деле компилируется в байт-код, совместимый с этим:

public Object max(List list, Comparator comp) {
   Object biggestSoFar = list.get(0);
   for ( Object  t : list ) {
       if (comp.compare(t, biggestSoFar) > 0) {  //IMPORTANT
          biggestSoFar = t;
       }
   }
   return biggestSoFar;
}

если метод моста не существует, и вы приняли List<Integer> и MyComparator для этой функции вызов на линии помеченIMPORTANT не так MyComparator не было бы метода с именем compare это займет два Object s...только один, который принимает два Integer s.

вопросы и ответы ниже хороший читать.

Читайте Также:

это insteresting, чтобы отметить, что компилятор выводит это MyComparator ' s метод:

public int compare(Integer a, Integer b) {/* code */}

пытается переопределить Comparator<T> ' s

public int compare(T a, T b);

от объявленного типа Comparator<Integer>. В противном случае, MyComparator ' s compare будет рассматриваться компилятором как дополнительный (перегрузки), а не переменная, метод. И как таковой, не было бы никакого метода моста, созданного для него.

если вы хотите понять, почему вам нужен метод моста, вы лучше понимаете, что происходит без него. Предположим, что нет никакого метода моста.

class A<T>{
  private T value;
  public void set(T newVal){
    value=newVal
  }
}

class B extends A<String>{
  public void set(String newVal){
    System.out.println(newVal);
    super.set(newVal);
  }
}

обратите внимание, что после удаления, способ set В стал public void set(Object newVal) поскольку нет привязки к параметру типа T. В классе B нет метода, сигнатура которого совпадает с set В A. Таким образом, нет переопределения. Следовательно, когда что-то подобное произошло:

A a=new B();
a.set("Hello World!");

полиморфизм здесь не работает. Помнить вам нужно переопределить метод родительского класса в дочернем классе, чтобы вы могли использовать родительский класс var для запуска полиморфизма.

что делает метод моста, это молча переопределяет метод в родительском классе со всей информацией из метода с тем же именем, но другой сигнатурой. С помощью мостового метода полиморфизм работал. Хотя на поверхности вы переопределяете метод родительского класса с помощью метода другой сигнатуры.