Подтвердить что ты не робот

Что делает компилятор Java с несколькими общими рамками?

Посмотрите на этот (возможно, глупый) код:

public <T extends Appendable & Closeable> void doStuff(T object)
throws IOException{

    object.append("hey there");
    object.close();

}

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

Это что-то вроде этого:

public void doStuff(Object object)
throws IOException{

    ((Appendable)object).append("hey there");
    ((Closeable)object).close();

}

Или, скорее, так:

public void doStuff(Object object)
throws IOException{
    Appendable appendable = (Appendable) object;
    Closeable closeable = (Closeable) object;

    appendable.append("hey there");
    closeable.close();

}

Или даже так:

public void doStuff(Appendable appendable)
throws IOException{
    Closeable closeable = (Closeable) appendable;

    appendable.append("hey there");
    closeable.close();

}

Или еще одна версия?

4b9b3361

Ответ 1

Подпись метода выглядит как public void doStuff(Appendable appendable), потому что

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

(JLS §4.4 Переменные типа)

Это поведение может быть важным, если вы используете отражение для доступа к этому методу.

Другое использование этого поведения заключается в сохранении двоичной совместимости с предварительными интерфейсами, как описано в Учебник по основам, раздел 10 (спасибо Mark Peters за указание на это). То есть

public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll)

является бинарным, совместимым с его исходной версией, возвращающей Object.


Тело метода эквивалентно следующему, но я думаю, что его детали реализации:

appendable.append("hey there"); 
((Closeable) appendable).close(); 

Ответ 2

Я не мог дождаться, мне нужно было ответить на свой вопрос. Ответ представляет собой комбинацию моей первой и третьей версий: первая граница используется как переменная типа, и объект присылается ко второй привязки всякий раз, когда это необходимо. Это результирующий байт-код (я добавил один разрыв строки для удобочитаемости):

  // Method descriptor #20 (Ljava/lang/Appendable;)V
  // Signature: <T::Ljava/lang/Appendable;:Ljava/io/Closeable;>(TT;)V
  // Stack: 2, Locals: 2
  public void doStuff(java.lang.Appendable object) throws java.io.IOException;
     0  aload_1 [object]
     1  ldc <String "hey there"> [26]
     3  invokeinterface java.lang.Appendable.append(java.lang.CharSequence) :
        java.lang.Appendable [28] [nargs: 2]
     8  pop
     9  aload_1 [object]
    10  checkcast java.io.Closeable [34]
    13  invokeinterface java.io.Closeable.close() : void [36] [nargs: 1]
    18  return
      Line numbers:
        [pc: 0, line: 14]
        [pc: 9, line: 15]
        [pc: 18, line: 17]
      Local variable table:
        [pc: 0, pc: 19] local: this index: 0 type: rumba.dumba.Bumba
        [pc: 0, pc: 19] local: object index: 1 type: java.lang.Appendable
      Local variable type table:
        [pc: 0, pc: 19] local: object index: 1 type: T