универсальный метод для создания экземпляра из объекта

#java

#java

Вопрос:

Является ли это безопасным способом создания экземпляра (при условии, что T имеет доступный конструктор по умолчанию)?

 <T>
public T defaultObj(T obj) throws Exception {
    return (T) obj.getClass().newInstance();
}
  

Из-за стирания типа приведенные выше коды будут генерировать непроверенное предупреждение. Можно ли избавиться от этого предупреждения, кроме @SuppressWarnings?

Заранее большое спасибо!

Редактировать: Да, я знаю, мог бы я передать class<T> type , что было бы намного лучше. Но давайте просто предположим, что пока об этом не может быть и речи.

Ответ №1:

Вы можете немного изменить подпись <T> T defaultObj(Class<T> obj) , а затем newInstance() вернет соответствующий объект.

Комментарии:

1. Спасибо за совет. Но давайте предположим, что сигнатура метода не может быть изменена. Безопасно ли использовать приведенные выше коды?

2. Да, я полностью согласен с axtavt.

3. Сигнатура метода должна быть записана. Не имеет никакого смысла делать подобные вещи (как и большинство реальных применений отражения).

Ответ №2:

Это именно то, что @SuppressWarnings предполагается сделать: этот код безопасен (потому что вызов getClass() объекта типа T на самом деле дает Class<? extends T> результат), но компилятор не может его понять (возвращаемое значение getClass() объявляется как Class<?> из-за ограничений дженериков) и генерирует предупреждение.

@SuppressWarnings В этом случае его использование абсолютно законно, и вы не должны пытаться избегать его использования.

Комментарии:

1. Спасибо!! Это заверение, которое я надеялся услышать. 🙂

Ответ №3:

Можно ли избавиться от этого предупреждения, кроме @SuppressWarnings?

Вы могли бы ограничить T расширение некоторого интерфейса, который предоставляет фабричный метод.

 interface Newable<T>
{
    T getNewInstance();
}

<T extends Newable<T>> T defaultObj(T obj)
{
    return obj.getNewInstance();
}
  

пример реализации:

 class Foo implements Newable<Foo>
{
    @Override
    public Foo getNewInstance() {
        return new Foo();
    }
}