Создание Новых Экземпляров Класса (Учебные руководства Java™> API Reflection> Элементы)


След: API Reflection
Урок: Элементы
Раздел: Конструкторы
Создание Новых Экземпляров Класса
Домашняя страница > API Reflection > Элементы

Создание Новых Экземпляров Класса

Есть два отражающих метода для того, чтобы создать экземпляры классов: java.lang.reflect.Constructor.newInstance() и Class.newInstance(). Прежний предпочитается и таким образом используется в этих примерах потому что:

Иногда это может быть требуемым, чтобы получить внутреннее состояние от объекта, который только устанавливается после конструкции. Рассмотрите сценарий, где необходимо получить внутренний набор символов, используемый java.io.Console. ( Console набор символов сохранен в частном поле и является не обязательно тем же самым как набором символов значения по умолчанию виртуальной машины Java, возвращенным java.nio.charset.Charset.defaultCharset()). ConsoleCharset пример показывает, как это могло бы быть достигнуто:


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() только успешно выполнится, если конструктор будет, имеет нулевые параметры и уже доступен. Иначе, необходимо использовать Constructor.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

Другое общее применение Constructor.newInstance() должен вызвать конструкторов, которые берут параметры. RestoreAliases пример находит определенного конструктора единственного параметра и вызывает это:


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() найти конструктора с единственным параметром типа java.util.HashMap. Отметьте, что достаточно передать HashMap.class начиная с параметра любому get*Constructor() метод требует class только в целях типа. Должный ввести стирание, следующее выражение оценивает к true:

HashMap.class == defaultAliases.getClass()

Пример тогда создает новый экземпляр class, используя этого конструктора с Constructor.newInstance().

$ java RestoreAliases
Mail keys:
  Duke
  Fang

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Получение и Парсинг Модификаторов Конструктора
Следующая страница: Поиск и устранение неисправностей



Spec-Zone.ru - all specs in one place