Если во время компиляции параметры типа Java заменяются соответствующими границами, почему следующий код не работает? - PullRequest
0 голосов
/ 01 ноября 2018
class World{

  <T extends Class1> World(TreeSet<? extends ClassA> set){
    *some code*
  }

  <T extends Class2> World(TreeSet<? extends ClassB> set){
    *some code*
  }

}

Выше кода показывает ошибку "столкновение имен: Мир и Мир имеют одно и то же стирание". Почему код не компилируется? Что более важно, почему компилятор говорит, что они имеют одинаковое стирание? Все вопросы на этом сайте, которые я нашел, связанные с этой темой, не углубляются в объяснение моей проблемы.

1 Ответ

0 голосов
/ 01 ноября 2018

Я исследовал проблему с помощью плагина просмотра байт-кода Intellij Idea для класса, содержащего следующий метод:

public <A extends Calendar> void fn(ArrayList<? extends File> abc){  //line number:11
  A a=(A)new Object();  //line 12
}  //line number:13

Ниже приведен байт-код, соответствующий этому методу, из средства просмотра байт-кода:

  // access flags 0x1
  // signature <A:Ljava/util/Calendar;>(Ljava/util/ArrayList<+Ljava/io/File;>;)V
  // declaration: void fn<A extends java.util.Calendar>(java.util.ArrayList<?extends java.io.File>)
public fn(Ljava/util/ArrayList;)V
  L0
    LINENUMBER 12 L0
    NEW java/lang/Object
    DUP
    INVOKESPECIAL java/lang/Object.<init> ()V
    CHECKCAST java/util/Calendar
    ASTORE 2
 L1
    LINENUMBER 13 L1
    RETURN
 L2
    LOCALVARIABLE this LMain; L0 L2 0
    LOCALVARIABLE abc Ljava/util/ArrayList; L0 L2 1
    // signature Ljava/util/ArrayList<+Ljava/io/File;>;
    // declaration: java.util.ArrayList<? extends java.io.File>
    LOCALVARIABLE a Ljava/util/Calendar; L1 L2 2
    // signature TA;
    // declaration: A
    MAXSTACK = 2
    MAXLOCALS = 3

Посмотрите на строку 2 выше. Параметры типа с правильными границами сохраняются, хотя и закомментированы. Но сигнатура метода не содержит никаких параметров типа после компиляции (строка 4). Мы снова видим в строке 10 информацию о параметрах сохраненного типа, используемую для преобразования, которая соответствует строке 12 исходного кода. Таким образом, вывод заключается в том, что параметры типа не заменяются своими границами. Ваш скомпилированный файл сохранит информацию как о параметрах типа, так и об их границах. Эта сохраненная информация будет использоваться только при необходимости, как определено компилятором. И по какой-то причине компилятор не считает, что метод (или конструктор) должен располагать этой информацией в своем объявлении в скомпилированном файле (это объясняет часть ошибки «тот же стирание»). Причина в том, что это связано с обратной совместимостью с версиями Java, когда у него не было общей функции. Таким образом, простое изменение / добавление / удаление параметров типа и / или их границ не перегружает метод или конструктор.


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

...