|
Spec-Zone .ru
спецификации, руководства, описания, API
|
Есть два отражающих метода для того, чтобы создать экземпляры классов: java.lang.reflect.Constructor.newInstance() и . Прежний предпочитается и таким образом используется в этих примерах потому что:
private конструкторы при определенных обстоятельствах.Иногда это может быть требуемым, чтобы получить внутреннее состояние от объекта, который только устанавливается после конструкции. Рассмотрите сценарий, где необходимо получить внутренний набор символов, используемый . ( Console набор символов сохранен в частном поле и является не обязательно тем же самым как набором символов значения по умолчанию виртуальной машины Java, возвращенным ).
import java.io.Console;
import java.nio.charset.Charset;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;
public class ConsoleCharset {
public static void main(String... args) {
Constructor[] ctors = Console.class.getDeclaredConstructors();
Constructor ctor = null;
for (int i = 0; i < ctors.length; i++) {
ctor = ctors[i];
if (ctor.getGenericParameterTypes().length == 0)
break;
}
try {
ctor.setAccessible(true);
Console c = (Console)ctor.newInstance();
Field f = c.getClass().getDeclaredField("cs");
f.setAccessible(true);
out.format("Console charset : %s%n", f.get(c));
out.format("Charset.defaultCharset(): %s%n",
Charset.defaultCharset());
// production code should handle these exceptions more gracefully
} catch (InstantiationException x) {
x.printStackTrace();
} catch (InvocationTargetException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
} catch (NoSuchFieldException x) {
x.printStackTrace();
}
}
}
Class.newInstance() только успешно выполнится, если конструктор будет, имеет нулевые параметры и уже доступен. Иначе, необходимо использовать как в вышеупомянутом примере.
Пример выводил для системы Unix:
$ java ConsoleCharset Console charset : ISO-8859-1 Charset.defaultCharset() : ISO-8859-1
Пример выводил для системы Windows:
C:\> java ConsoleCharset Console charset : IBM437 Charset.defaultCharset() : windows-1252
Другое общее применение должен вызвать конструкторов, которые берут параметры.
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static java.lang.System.out;
class EmailAliases {
private Set<String> aliases;
private EmailAliases(HashMap<String, String> h) {
aliases = h.keySet();
}
public void printKeys() {
out.format("Mail keys:%n");
for (String k : aliases)
out.format(" %s%n", k);
}
}
public class RestoreAliases {
private static Map<String, String> defaultAliases = new HashMap<String, String>();
static {
defaultAliases.put("Duke", "duke@i-love-java");
defaultAliases.put("Fang", "fang@evil-jealous-twin");
}
public static void main(String... args) {
try {
Constructor ctor = EmailAliases.class.getDeclaredConstructor(HashMap.class);
ctor.setAccessible(true);
EmailAliases email = (EmailAliases)ctor.newInstance(defaultAliases);
email.printKeys();
// production code should handle these exceptions more gracefully
} catch (InstantiationException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
} catch (InvocationTargetException x) {
x.printStackTrace();
} catch (NoSuchMethodException x) {
x.printStackTrace();
}
}
}
Этот пример использование Class.getDeclaredConstructor() найти конструктора с единственным параметром типа . Отметьте, что достаточно передать HashMap.class начиная с параметра любому get*Constructor() метод требует class только в целях типа. Должный , следующее выражение оценивает к true:
HashMap.class == defaultAliases.getClass()
Пример тогда создает новый экземпляр class, используя этого конструктора с .
$ java RestoreAliases Mail keys: Duke Fang