Spec-Zone .ru
спецификации, руководства, описания, API
|
Отражение обеспечивает средство для того, чтобы оно вызвало методы на 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.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