Инициализация полей типа generi c в самом классе - PullRequest
0 голосов
/ 22 апреля 2020

Вот код ...

public class Dog {

}


public class Bird {

}


public class Animal< T > {
    T field1 = (T) new Bird();  // unchecked cast : Bird to T

    public void display() {
        System.out.println(field1);
    }
}

Я ожидал ошибку времени выполнения, но она работает нормально ....

Это дает мне вывод:

com.company.Bird@48140564

в основном классе

public static void main(){
    Animal<Dog> animal = new Animal();
    animal.display();   // I was expecting run time error here

}

1 Ответ

1 голос
/ 22 апреля 2020

Ошибка не появляется, потому что код все еще "действителен". Java Обобщения - это модный способ обработки объектов и улучшения проверки типов. Каждый раз, когда вы используете обобщенный c, при компиляции кода Java преобразует их в явное приведение. Основная причина связана с унаследованными версиями Java до того, как дженерики были представлены, поэтому Java обрабатывает их как класс "Object" и затем приводит их за вас при необходимости.

Например, в вашем. * В файле 1018 * вы пишете следующий код:

String hello = new String();
ArrayList<String> list = new ArrayList<>();
list.add(hello);

Object noCastRequired = list.get(0);
String castRequired = list.get(0);

В своем относительном .class-файле Java напишет:

String hello = new String();
ArrayList<String> list = new ArrayList();
list.add(hello);
Object noCastRequired = list.get(0);
String castRequired = (String)list.get(0);

Если вы собираетесь проверить свой скомпилированный код, вы можете видеть, что выражение все еще является допустимым оператором кода, но у вас будут ошибки и проблемы, если вы попытаетесь «использовать» это поле в методе, где требуется «тип»; Оператор print принимает объектный класс в качестве параметра, поэтому Java не собирается его приводить.

Пример:

class Scratch {
    public static void main(String[] args) {
        Root<FirstLevel> correct = new Root<>();

        Root<FirstLevelChild> iAmNotValid = new Root<>(); // No error
        Root<SecondLevel> iAmNotValidToo = new Root<>(); // No error

        System.out.println(correct.field.first); // Ok
        System.out.println(iAmNotValid.field.first); // Ko, because java.lang.ClassCastException: FirstLevel cannot be cast to FirstLevelChild
        System.out.println(iAmNotValidToo.field.second);
    }


}

class Root<T> {
    public T field = (T) new FirstLevel();
}

class FirstLevel {
    public String first = "First";
}

class SecondLevel {
    public String second = "Second";
}

class FirstLevelChild extends FirstLevel {
}
...