Это неподготовлено, но не является этим, для чего был Кузнечик ?
Я думаю, что первый метод должен выглядеть примерно так:
public static <T> T create(final String className, Class<T> ifaceClass)
throws ClassNotFoundException {
final Class<T> clazz = Class.forName(className).asSubclass(ifaceClass);
return create(clazz);
}
Вы не можете выполнить приведение типов с использованием параметра типа ... без этих надоедливых предупреждений о безопасности типов.
] Между прочим, если вы проигнорируете эти предупреждения, метод create может создать экземпляр некоторого класса, несовместимого с фактическим типом, используемым вызывающей стороной. Это может позже привести к неожиданному исключению ClassCastException; например, когда экземпляр назначен.
РЕДАКТИРОВАТЬ: @Pascal указывает, что нам нужно добавить приведение типов, чтобы сделать эту компиляцию; т.е.
Class<T> clazz = (Class<T>) Class.forName(className).asSubclass(ifaceClass);
К сожалению, нам также необходимо добавить аннотацию @SuppressWarnings.
Я думаю, это потому, что Class.forName (..)
не параметризован для T. Когда вы запускаете автозаполнение eclipse, оно предполагает возврат clazz.newInstance () Объект. Итак, сохраните состав и добавьте @SuppressWarnings. Если вы не используете метод должным образом (например, String str = Utils.create ("java.util.ArrayList");
), то возникнет исключение ClassCastException
, но это нормально .
Второй метод хорош.
Но для первого в качестве параметра можно передать любое имя класса.
Суть метода заключается в создании экземпляра класса, о котором вызывающий код не знает во время компиляции, он знает о нем только во время выполнения.
В этих условиях вызывающий код не может установить параметр типа , поэтому метод не может быть параметризован, поэтому приведение не имеет смысла ...
Поэтому я бы сказал , что весь метод не имеет смысла .
Некоторый балл можно было бы дать методу , если бы вызывающий код знал супертип класса . Это можно было бы передать в качестве параметра, и приведение было бы возможным и значимым.
public static <T> T create(final Class<T> superType, final String className) {
try {
final Class<?> clazz = Class.forName(className);
final Object object = clazz.newInstance();
if (superType.isInstance(object)) {
return (T)object; // safe cast
}
return null; // or other error
} // catch and other error code
}
Даже если вы можете заставить приведенный выше код работать, метод конструктора newInstance () предполагает конструктор с нулевым аргументом.
Если у класса его нет, то есть конструктор с нулевым аргументом класса, который вы пытаетесь создать, был явно объявлен закрытым или пакетным, в зависимости от того, откуда вызывается метод, вы получите исключение IllegalAccessException. Что-то, что можно добавить к предварительному условию, если оно сработает.
Конструктор с нулевым аргументом класса, который вы пытаетесь создать, был явно объявлен частным или пакетным, в зависимости от того, откуда вызывается метод, вы получите исключение IllegalAccessException. Что-то, что можно добавить к предварительному условию, если оно сработает. Конструктор с нулевым аргументом класса, который вы пытаетесь создать, был явно объявлен частным или пакетным, в зависимости от того, откуда вызывается метод, вы получите исключение IllegalAccessException. Что-то, что можно добавить к предварительному условию, если оно сработает.Вы не можете ограничить параметр типа, чтобы он содержал тип с именем className. Следовательно, вызывающий может предоставить любой тип вашей функции create (String), что, конечно, небезопасно по типу.
Поскольку вы не можете статически принудительно обеспечить, чтобы возвращаемый экземпляр реализует какой-либо интерфейс (без того, чтобы вызывающий сообщал вам, передав соответствующий Class object), я бы обошелся без дженериков и приводил вызывающего абонента к любому типу, который он ожидал.
public static Object create(final String className) {
try {
final Class<?> clazz = Class.forName(className);
return create(clazz);
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Затем вызывающий может написать:
Foo foo = (Foo) create("my.cool.FooBar");
вместо
Foo foo = create("my.cool.FooBar", Foo.class);