Я некоторое время изучал и экспериментировал с Java Generics, но столкнулся с чем-то, что не могу объяснить. Возьмем для примера следующий код:
public class Question {
public <T> Sub<T> getSub(Class<T> c) {
return new Sub<T>(c);
}
public class Sub<S> {
private Class<S> c;
public Sub(Class<S> c) {
this.c = c;
}
public void add(S s) {
}
}
}
И тестовый код:
import generics.Question.Sub;
public class Answer {
public static void main(String [] args) {
Question q = new Question();
Sub<String> s = q.getSub(String.class);
s.add("");
}
}
При запуске выдается удивительно загадочное сообщение об ошибке:
C:\Answer.java:8: incompatible types
found : generics.Question.Sub<java.lang.String>
required: generics.Question.Sub<java.lang.String>
Sub<String> s = q.getSub(String.class);
1 error
Теперь, проведя некоторые эксперименты, я выяснил, как предотвратить ошибку компилятора. Я могу либо сделать класс Sub статическим внутренним классом, либо мне нужно ссылаться на класс Sub как Question.Sub . Что я не могу сделать, так это объяснить, почему мне нужно это сделать.
Я немного прочел документацию по Java по Generics, но ни один из них не описывает этот конкретный случай.
Может кто-нибудь объяснить, почему код является несовместимым типом в его текущей форме?
-Edit-
Глядя на это поближе, я вижу, что за пределами Netbeans у меня такое же поведение. Если у меня есть код в следующей структуре:
generics\
generics\Question.java
generics\Answer.java
Когда я собираю файлы вместе, я не получаю сообщение об ошибке:
C:\>javac generics\Question.java generics\Answer.java
C:\>
Однако, когда я сначала компилирую Вопрос, а затем отвечаю, я получаю ошибку:
C:\>javac generics\Question.java
C:\>javac generics\Answer.java
generics\Answer.java:8: incompatible types
found : generics.Question.Sub<java.lang.String>
required: generics.Question.Sub<java.lang.String>
Sub<String> s = q.getSub(String.class);
^
1 error
Я слышал что-то упомянутое о Типе Erasure. Так ли это в этой ситуации?