Создайте экземпляр данного типа класса - PullRequest
0 голосов
/ 16 мая 2018

У меня есть несколько дочерних классов, где все они расширены одним общим родительским классом.

Мне нужен конкретный метод в родительском классе, и этот метод должен возвращать новый объект данного типа класса.

Это то, что я пытался.

class Vehicle {

    public <T> T get(Class<T> type){
        //return new T();
    }
}

class Car extends Vehicle {
}

class Van extends Vehicle {
}

выше get(...) метода

return new T();

оператор дает ошибку компиляции, говоря:

Неожиданный тип
& emsp; требуется: класс
& emsp; найдено: параметр типа T

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

new Car();

по какой-то причине. Дочерних классов может быть любое количество, поэтому переопределение метода get() в каждом из них также невозможно. Есть идеи?

Ответы [ 5 ]

0 голосов
/ 16 мая 2018

Если у вас есть конструктор по умолчанию в классах Car и Van, вы можете использовать этот подход:

public static <T extends Vehicle> T get(Class<T> cls) throws Exception {
    return cls.getConstructor().newInstance();
}

Или, в качестве альтернативы, этот (мне он кажется более предпочтительным; но у меня нет никаких противоречий с предыдущим):

public static <T extends Vehicle> T get(Class<T> cls) {
    if (cls.isAssignableFrom(Car.class))
        return (T)new Car();
    if (cls.isAssignableFrom(Van.class))
        return (T)new Van();
    throw new RuntimeException("Unknown class '" + cls.getSimpleName() + '\'');
}
0 голосов
/ 16 мая 2018

Вы можете сделать базовый класс универсальным, чтобы у вас был правильный тип возвращаемого значения для метода get().

abstract class Vehicle<T extends Vehicle> {
    public abstract T get();
}

class Car extends Vehicle {
    @Override
    public Car get() {
        return new Car();
    }
}

Однако это не заставляет Car фактически возвращать Car; можно вернуть Van.

0 голосов
/ 16 мая 2018

Измените ваш метод get, как показано в следующем коде:

public <T> T get(Class<T> type) throws InstantiationException, IllegalAccessException {
    return type.newInstance();
}
0 голосов
/ 16 мая 2018

T является заполнителем для типа, а не типа; поэтому вы не можете вызвать new T(), потому что у вас нет значения в T.

Значение в type, и вы должны использовать эту переменную.

Важно помнить, что в обобщенной системе заполнители не являются типами в смысле типов Java. Они следуют различным правилам о том, как они ограничены (супер и т. Д.). У них разные привязки, когда они применяются (время компиляции). Эти характеристики означают, что они не могут быть согласованы с системой типов Java, даже если они (в некоторой степени) контролируют ее.

Теперь у вас есть Class объект в качестве значения, связанный с переменной type. Вы можете использовать средства Java для создания новых экземпляров из объекта Class в type.

0 голосов
/ 16 мая 2018

Вы можете создать экземпляр объекта Class, используя Class.newInstance().

public <T> T get(Class<T> type) throws InstantiationException, IllegalAccessException {
    return type.newInstance();
}

Но для класса должен существовать конструктор без аргументов;и это может вызвать исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...