Рассмотрим следующий пример, игнорируя причину, по которой можно было бы это сделать:
private static class Original {
public String getValue() {
return "Foo";
}
}
private static class Wrapper extends Original {
private Original orig;
public Wrapper(Original orig) {
this.orig = orig;
}
@Override
public String getValue() {
return orig.getValue();
}
}
public static void test(Original... o) {
if (o != null && o.length > 0) {
for (int i = 0; i < o.length; i++) {
if (o[i] instanceof Wrapper) {
o[i] = ((Wrapper) o[i]).orig; // Throws java.lang.ArrayStoreException at runtime
}
}
}
}
public static void main(String[] args){
test(new Wrapper[] { // Explicitly create an array of subclass type
new Wrapper(new Original())
});
}
Этот пример не выдает предупреждений или ошибок во время компиляции. Похоже, что компилятор решает, что Wrapper[]
содержит Wrapper
экземпляров, что фактически означает, что это определенно экземпляры класса Original
. Это прекрасно.
Однако во время выполнения экземпляр Wrapper[]
напрямую передается в метод. Я думал, что было бы достаточно разумно разорвать этот массив и воссоздать экземпляр Original[]
во время выполнения, но похоже, что это не так.
Это поведение где-нибудь задокументировано (например, JLS)? Обычный программист вроде меня всегда будет предполагать, что я могу манипулировать параметром vararg Original...
, как будто это Original[]
.
List<Dog>
не являетсяList<Animal>
). - person Andy Turner   schedule 03.07.2018o
равенWrapper[]
, а неOriginal[]
. Разве переданный параметр не должен быть помещен в массив varargs? Или есть специальное исключение для массивов, соответствующих типу параметра? - person markspace   schedule 03.07.2018Wrapper
не являетсяOriginal
, вы не можете поместить его в массивOriginal
. Из других ссылочных типов вы можете знать, что тип объекта во время выполнения может быть более точным, чем объявленный тип ссылочной переменной. Это возможно и для массивов: объявленный типo
— это массивOriginal
, но тип среды выполнения — массивWrapper
. - person Ole V.V.   schedule 03.07.2018Object...
принимает любой массив ссылок, так что это последовательно, но немного странно. МассивInteger
передается сам по себе, а не какObject[]
, содержащий одну ссылку наInteger[]
. - person markspace   schedule 03.07.2018