След: API Reflection
Урок: Элементы
Раздел: Методы
Вызов Методов
Домашняя страница > API Reflection > Элементы

Вызов Методов

Отражение обеспечивает средство для того, чтобы оно вызвало методы на class. Как правило, это только было бы необходимо, если не возможно бросить экземпляр class к требуемому, вводят неотражающий код. Методы вызываются с java.lang.reflect.Method.invoke(). Первым параметром является объектный экземпляр, на который должен быть вызван этот определенный метод. (Если метод static, первый параметр должен быть null.) Последующими параметрами являются параметры метода. Если базовый метод выдаст исключение, то он будет обернут java.lang.reflect.InvocationTargetException. Исходное исключение метода может быть получено, используя исключение, объединяющее механизм в цепочку InvocationTargetException.getCause() метод.

Обнаружение и Вызов Метода с Определенным Объявлением

Рассмотрите тестовый комплект, который использует отражение, чтобы вызвать частные методы испытаний в данном class. Deet пример ищет public методы в class, которые начинаются со строки"test", имейте булев тип возврата, и сингл Locale параметр. Это тогда вызывает каждый метод соответствия.


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Locale;
import static java.lang.System.out;
import static java.lang.System.err;

public class Deet<T> {
    private boolean testDeet(Locale l) {
	// getISO3Language() may throw a MissingResourceException
	out.format("Locale = %s, ISO Language Code = %s%n", l.getDisplayName(), l.getISO3Language());
	return true;
    }

    private int testFoo(Locale l) { return 0; }
    private boolean testBar() { return true; }

    public static void main(String... args) {
	if (args.length != 4) {
	    err.format("Usage: java Deet <classname> <langauge> <country> <variant>%n");
	    return;
	}

	try {
	    Class<?> c = Class.forName(args[0]);
	    Object t = c.newInstance();

	    Method[] allMethods = c.getDeclaredMethods();
	    for (Method m : allMethods) {
		String mname = m.getName();
		if (!mname.startsWith("test")
		    || (m.getGenericReturnType() != boolean.class)) {
		    continue;
		}
 		Type[] pType = m.getGenericParameterTypes();
 		if ((pType.length != 1)
		    || Locale.class.isAssignableFrom(pType[0].getClass())) {
 		    continue;
 		}

		out.format("invoking %s()%n", mname);
		try {
		    m.setAccessible(true);
		    Object o = m.invoke(t, new Locale(args[1], args[2], args[3]));
		    out.format("%s() returned %b%n", mname, (Boolean) o);

		// Handle any exceptions thrown by method to be invoked.
		} catch (InvocationTargetException x) {
		    Throwable cause = x.getCause();
		    err.format("invocation of %s failed: %s%n",
			       mname, cause.getMessage());
		}
	    }

        // production code should handle these exceptions more gracefully
	} catch (ClassNotFoundException x) {
	    x.printStackTrace();
	} catch (InstantiationException x) {
	    x.printStackTrace();
	} catch (IllegalAccessException x) {
	    x.printStackTrace();
	}
    }
}

Deet вызывает getDeclaredMethods() который возвратит все методы, явно объявленные в class. Кроме того, Class.isAssignableFrom() используется, чтобы определить, являются ли параметры расположенного метода совместимыми с требуемым вызовом. Технически код, возможно, протестировал, является ли следующий оператор true с тех пор Locale final:

Locale.class == pType[0].getClass()

Однако, Class.isAssignableFrom() является более общим.

$ java Deet Deet ja JP JP
invoking testDeet()
Locale = Japanese (Japan,JP), 
ISO Language Code = jpn
testDeet() returned true
$ java Deet Deet xx XX XX
invoking testDeet()
invocation of testDeet failed: 
Couldn't find 3-letter language code for xx

Во-первых, отметьте это только testDeet() встречает ограничения объявления, осуществленные кодом. Затем, когда testDeet() передается несостоятельный довод, он бросает непроверенное java.util.MissingResourceException. В отражении нет никакого различия в обработке проверенных против исключений непроверенных. Они все обертываются в InvocationTargetException

Вызов Методов с Переменным Числом Параметров

Method.invoke() может использоваться, чтобы передать переменное число параметров методу. Ключевое понятие, чтобы понять - то, что методы переменной арности реализуются, как будто переменные параметры упаковываются в массиве.

InvokeMain пример иллюстрирует, как вызвать main() точка входа в любом class и передаче ряд параметров определяется во времени выполнения.


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class InvokeMain {
    public static void main(String... args) {
	try {
	    Class<?> c = Class.forName(args[0]);
	    Class[] argTypes = new Class[] { String[].class };
	    Method main = c.getDeclaredMethod("main", argTypes);
  	    String[] mainArgs = Arrays.copyOfRange(args, 1, args.length);
	    System.out.format("invoking %s.main()%n", c.getName());
	    main.invoke(null, (Object)mainArgs);

        // production code should handle these exceptions more gracefully
	} catch (ClassNotFoundException x) {
	    x.printStackTrace();
	} catch (NoSuchMethodException x) {
	    x.printStackTrace();
	} catch (IllegalAccessException x) {
	    x.printStackTrace();
	} catch (InvocationTargetException x) {
	    x.printStackTrace();
	}
    }
}

Во-первых, чтобы найти main() метод код ищет class с именем, "основным" с единственным параметром, который является массивом String С тех пор main() static, null первый параметр Method.invoke(). Вторым параметром является массив параметров, которые передадут.

$ java InvokeMain Deet Deet ja JP JP
invoking Deet.main()
invoking testDeet()
Locale = Japanese (Japan,JP), 
ISO Language Code = jpn
testDeet() returned true

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

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



Spec-Zone.ru - all specs in one place