Step By Step(Java反射編)
159211 ワード
この記事では、Javaの反射に関する概念を多く紹介することは考えられません.Javaの初心者にとってもよく知られていないと思います.この記事では、従来のように実行可能なサンプルコードと豊富な注釈情報を提供し、Javaの反射の各技術段階をできるだけカバーし、反射のメカニズムと応用シーンをより多くの視点から分析します.効率の面で望ましくない点もあります 1. クラス属性の反射: 各Javaオブジェクトには、Java反射の中で最も重要なエントリポイントとして、反射に関連するほとんどのアプリケーションがここから始まる属性(metadata)情報を記述するクラスオブジェクトが含まれます. 1) 反射クラスの名前:
2) クラス名を表す文字列を使用して、クラスのオブジェクトインスタンスを取得します.
3) 反射クラスの修飾子:
4) クラスのドメインフィールド、コンストラクション関数、およびドメインメソッドのアクセス修飾子情報を取得します.
5) スーパークラスの名前を取得するには、次の手順に従います.
6) 実装されたインタフェースを取得するには、次の手順に従います. JavaではC++のように多重継承をサポートするのではなく、単一継承とマルチ実装というより安全で合理的な方法が提供されています.ここでの単一継承は、1つのスーパークラスを継承(extends)し、マルチ実装は複数のインタフェースを実現できることを意味します.次の例では、クラスが実装するインタフェースを取得します.
7) パッケージ名の取得:
2. 配列ベースの反射: 1) 反射による配列インスタンスの作成:
2) 元のタイプと元のタイプ配列のタイプ名を取得します.
配列の名前の前に[,これは配列名の表現であり,二次元配列は[[,後のIはint,Bはbyteを表す.これはJVMが提供する一連のタイプの名称符号化仕様であり,JNIでの応用がまだ比較的広いため,後のローカルコード(JNI)に関するBlogでより明確なリストと使用方法を与える. 3) 現在のオブジェクトが配列であるかどうかを判断します.
4) 配列の次元を取得するには、次の手順に従います.
5) 配列要素を反射して表示するには、次の手順に従います.
6) 配列オブジェクトに基づいて、同じ配列オブジェクトを反射のメカニズムで作成します.
3. オブジェクトフィールドに基づく反射: 1) オブジェクトのpublicドメインフィールドと宣言されたすべてのドメインフィールド(スーパークラスを含まない)をリストします.
2) ドメインフィールドの文字列名に基づいて、ドメインフィールドの値を取得します.
3) 指定したドメインフィールドの値を取得および設定します.
4. 汎用情報の反射: 1) クラスの汎用インタフェース情報の取得
2) クラスの汎用インタフェース、インタフェース、汎用スーパークラス、およびスーパークラス情報の比較を取得します.
3) 戻り値とパラメータリストの汎用タイプ情報を含むドメインメソッドの署名情報を出力します.
4) オブジェクトフィールドのタイプ情報を出力します.
5. 列挙された反射: 1) 列挙された定数のリストを取得するには、次の手順に従います.
6. ドメインメソッドの反射: 1) クラスコンストラクタの反射オブジェクトから新しいインスタンスを作成します.
2) ドメインメソッドの名前とパラメータリスト署名によって、このメソッド(静的メソッド)を取得して実行します.
3) このメソッド(非静的メソッド)は、ドメインメソッドの名前とパラメータリスト署名によって取得され、実行されます.
4) 呼び出したオブジェクトを反射するプライベートドメインメソッド:
5) スタックフレームから現在のメソッドの名前を取得します.
7. 反射ベースのメソッド呼び出しと通常のメソッド呼び出しの効率の違い: 私達は本編の初めの部分ですでに反射が確かに私達のプログラムに極めて大きい柔軟性をもたらすことができることに言及して、現在多くの流行の枠組みはすべてJavaが提供する反射のメカニズムに非常に依存して、反射はほとんど至る所見られます.しかしこれは私達が彼の理由を乱用することになることができなくて、やはりあの言葉、無料の昼食がなくて、反射の柔軟性は極めて大きい効率の犠牲で交換しますはい、次の例を参照してください.
1 public static void main(String[] args) {
2 String str = "Hello";
3 //1. Java (Class), class , :
4 //c = str.class;
5 Class<? extends String> c = str.getClass();
6 //2. Java
7 System.out.println(c.getName());
8 }
9 /* :
10 java.lang.String
11 */
2) クラス名を表す文字列を使用して、クラスのオブジェクトインスタンスを取得します.
1 public static void main(String[] args) {
2 try {
3 //1. , ( String metadata )
4 Class<?> cls = Class.forName("java.lang.String");
5 //2. Class<String> newInstance
6 //String , 。
7 // newInstance 。
8 String s = (String) cls.newInstance();
9 } catch (ClassNotFoundException e) {
10 e.printStackTrace();
11 } catch (InstantiationException e) {
12 e.printStackTrace();
13 } catch (IllegalAccessException e) {
14 e.printStackTrace();
15 }
16 }
3) 反射クラスの修飾子:
1 public static void main(String[] args) {
2 String str = "Hello";
3 Class<? extends String> c = str.getClass();
4 // , public、final abstract
5 int m = c.getModifiers();
6 if (Modifier.isPublic(m))
7 System.out.println("public");
8 if (Modifier.isAbstract(m))
9 System.out.println("abstract");
10 if (Modifier.isFinal(m))
11 System.out.println("final");
12 }
13 /* :
14 public
15 final
16 */
4) クラスのドメインフィールド、コンストラクション関数、およびドメインメソッドのアクセス修飾子情報を取得します.
1 public class MyTest {
2 public static void main(String[] args) {
3 MyTest pp = new MyTest();
4 pp.doClass("java.lang.String");
5 }
6 protected void doClass(String className) {
7 try {
8 Class<?> c = Class.forName(className);
9 System.out.println(Modifier.toString(c.getModifiers()) + ' ' + c + " {");
10 // metadata , ,
11 // getFields() public
12 Field fields[] = c.getDeclaredFields();
13 for (Field f : fields) {
14 if (Modifier.isPrivate(f.getModifiers())) {
15 System.out.println("Field '" + f.getName() + "' is private.");
16 } else if (Modifier.isProtected(f.getModifiers())) {
17 System.out.println("Field '" + f.getName() + "' is protected.");
18 } else if (Modifier.isPublic(f.getModifiers())) {
19 System.out.println("Field '" + f.getName() + "' is public.");
20 } else if (Modifier.isFinal(f.getModifiers())) {
21 System.out.println("Field '" + f.getName() + "' is final.");
22 } else if (Modifier.isStatic(f.getModifiers())) {
23 System.out.println("Field '" + f.getName() + "' is static.");
24 }
25 }
26 // ,getConstructors public 。
27 // , getDeclaredConstructors
28 Constructor<?>[] constructors = c.getConstructors();
29 for (Constructor<?> ctor : constructors) {
30 if (Modifier.isProtected(ctor.getModifiers())) {
31 System.out.println("Constructor '" + ctor.getName() + "' is protected.");
32 } else if (Modifier.isPrivate(ctor.getModifiers())) {
33 System.out.println("Constructor '" + ctor.getName() + "' is private.");
34 } else if (Modifier.isPublic(ctor.getModifiers())) {
35 System.out.println("Constructor '" + ctor.getName() + "' is public.");
36 }
37 }
38 // , 。
39 // getMethods() public
40 Method methods[] = c.getDeclaredMethods();
41 for (Method m : methods) {
42 if (Modifier.isProtected(m.getModifiers())) {
43 System.out.println("Method '" + m.getName() + "' is protected.");
44 } else if (Modifier.isPrivate(m.getModifiers())) {
45 System.out.println("Method '" + m.getName() + "' is private.");
46 } else if (Modifier.isPublic(m.getModifiers())) {
47 System.out.println("Method '" + m.getName() + "' is public.");
48 } else if (Modifier.isStatic(m.getModifiers())) {
49 System.out.println("Method '" + m.getName() + "' is static.");
50 } else if (Modifier.isNative(m.getModifiers())) {
51 System.out.println("Method '" + m.getName() + "' is native.");
52 } else if (Modifier.isAbstract(m.getModifiers())) {
53 System.out.println("Method '" + m.getName() + "' is abstract.");
54 } else if (Modifier.isFinal(m.getModifiers())) {
55 System.out.println("Method '" + m.getName() + "' is final.");
56 }
57 }
58 System.out.println("}");
59 } catch (ClassNotFoundException e) {
60 System.err.println("Error: Class " + className + " not found!");
61 } catch (Exception e) {
62 System.err.println(e);
63 }
64 }
65 }
5) スーパークラスの名前を取得するには、次の手順に従います.
1 public static void main(String[] args) {
2 Class<?> subclass = LinkedList.class;
3 // Class 。
4 Class<?> superclass = subclass.getSuperclass();
5 while (superclass != null) {
6 String className = superclass.getName();
7 System.out.println(className);
8 subclass = superclass;
9 superclass = subclass.getSuperclass();
10 }
11 }
12 /* :
13 java.util.AbstractSequentialList
14 java.util.AbstractList
15 java.util.AbstractCollection
16 java.lang.Object
17 */
6) 実装されたインタフェースを取得するには、次の手順に従います. JavaではC++のように多重継承をサポートするのではなく、単一継承とマルチ実装というより安全で合理的な方法が提供されています.ここでの単一継承は、1つのスーパークラスを継承(extends)し、マルチ実装は複数のインタフェースを実現できることを意味します.次の例では、クラスが実装するインタフェースを取得します.
1 public static void main(String[] args) {
2 Class<?>[] interfaces = LinkedList.class.getInterfaces();
3 if ((interfaces != null) && (interfaces.length > 0)) {
4 if (LinkedList.class.isInterface())
5 System.out.print(" extends ");
6 else
7 System.out.print(" implements ");
8 for (int i = 0; i < interfaces.length; i++) {
9 if (i > 0)
10 System.out.print(", ");
11 System.out.print(interfaces[i].getName());
12 }
13 }
14 }
15 /* :
16 implements java.util.List, java.util.Deque, java.lang.Cloneable, java.io.Serializable
17 */
7) パッケージ名の取得:
1 public static void main(String[] args) {
2 System.out.println(String.class.getPackage().getName());
3 }
4 /* :
5 java.lang
6 */
2. 配列ベースの反射: 1) 反射による配列インスタンスの作成:
1 public static void main(String[] args) {
2 int[] dim1 = { 5 };
3 // Array newInstance , dim1
4 //oneDimA ,
5 int[] oneDimA = (int[]) Array.newInstance(int.class, dim1);
6 //
7 int[] oneDimB = (int[]) Array.newInstance(int.class, 5);
8 System.out.println("The length of oneDimA is " + oneDimA.length);
9 System.out.println("The length of oneDimB is " + oneDimB.length);
10 if (Arrays.equals(oneDimA, oneDimB))
11 System.out.println("OneDimA is equal to oneDimB");
12
13 int[] dimStr = { 5, 10 };
14 // dimStr 5*10 String 。
15 String[][] twoDimStr = (String[][]) Array.newInstance(String.class,dimStr);
16 System.out.println("The length of twoDimStr is " + twoDimStr.length);
17 for (int i = 0; i < twoDimStr.length; ++i) {
18 System.out.print(twoDimStr[i].length + "\t");
19 }
20 }
21 /* :
22 The length of oneDimA is 5
23 The length of oneDimB is 5
24 OneDimA is equal to oneDimB
25 The length of twoDimStr is 5
26 10 10 10 10 10
27 */
2) 元のタイプと元のタイプ配列のタイプ名を取得します.
1 public static void main(String[] args) {
2 System.out.println(int.class.getName());
3 System.out.println(int[].class.getName());
4 System.out.println(byte.class.getName());
5 System.out.println(byte[].class.getName());
6 }
7 /* :
8 int
9 [I
10 byte
11 [B
12 */
配列の名前の前に[,これは配列名の表現であり,二次元配列は[[,後のIはint,Bはbyteを表す.これはJVMが提供する一連のタイプの名称符号化仕様であり,JNIでの応用がまだ比較的広いため,後のローカルコード(JNI)に関するBlogでより明確なリストと使用方法を与える. 3) 現在のオブジェクトが配列であるかどうかを判断します.
1 public static void main(String[] args) {
2 Object o = new int[10];
3 boolean b = o.getClass().isArray();
4 if (b) {
5 System.out.println("object is an array");
6 }
7 }
8 /* :
9 object is an array
10 */
4) 配列の次元を取得するには、次の手順に従います.
1 public class MyTest {
2 public static void main(String[] args) {
3 Object o = new int[1][2][3];
4 System.out.println("The length is " + Array.getLength(o));
5 System.out.println("The Dimension is " + getDim(o));
6 }
7 public static int getDim(Object array) {
8 int dim = 0;
9 Class<?> cls = array.getClass();
10 while (cls.isArray()) {
11 ++dim;
12 //getComponentType Class ,
13 // null。
14 cls = cls.getComponentType();
15 }
16 return dim;
17 }
18 }
19 /* :
20 The length is 1
21 The Dimension is 3
22 */
5) 配列要素を反射して表示するには、次の手順に従います.
1 public class MyTest {
2 public static void main(String args[]) {
3 Object array = Array.newInstance(int.class, 3);
4 fillArray(array);
5 displayArray(array);
6 }
7 private static void fillArray(Object array) {
8 // ,
9 // length ,
10 // , for
11 int length = Array.getLength(array);
12 for (int i = 0; i < length; i++) {
13 // array i i*i。
14 Array.setInt(array, i, i*i);
15 }
16 }
17 private static void displayArray(Object array) {
18 int length = Array.getLength(array);
19 for (int i = 0; i < length; i++) {
20 // array i , int 。
21 int value = Array.getInt(array, i);
22 System.out.println("Position: " + i + ", value: " + value);
23 }
24 }
25 }
26 /* :
27 Position: 0, value: 0
28 Position: 1, value: 1
29 Position: 2, value: 4
30 */
6) 配列オブジェクトに基づいて、同じ配列オブジェクトを反射のメカニズムで作成します.
1 public class MyTest {
2 public static void main(String args[]) {
3 int[] ints = new int[2];
4 Object ret = buildNewArrayWithReflection(ints);
5 if (ret != null) {
6 Arrays.equals(ints, (int[])ret);
7 System.out.println("The both array are equal.");
8 }
9 }
10 private static Object buildNewArrayWithReflection(Object source) {
11 if (!source.getClass().isArray()) {
12 System.out.println("The argument is NOT an array.");
13 return null;
14 }
15 Class<?> arrayClass = source.getClass();
16 String arrayName = arrayClass.getName();
17 Class<?> componentClass = arrayClass.getComponentType();
18 String componentName = componentClass.getName();
19 System.out.println("Array: " + arrayName + ", Component: " + componentName);
20 int length = Array.getLength(source);
21 Object ret = Array.newInstance(componentClass, length);
22 System.arraycopy(source, 0, ret, 0, length);
23 return ret;
24 }
25 }
26 /* :
27 Array: [I, Component: int
28 The both array are equal.
29 */
3. オブジェクトフィールドに基づく反射: 1) オブジェクトのpublicドメインフィールドと宣言されたすべてのドメインフィールド(スーパークラスを含まない)をリストします.
1 public class MyTest {
2 public static void main(String args[]) {
3 Class<Point> cls = java.awt.Point.class;
4 Field[] fieldPublic = cls.getFields();
5 System.out.println("Here are public fields.");
6 for (Field f : fieldPublic) {
7 System.out.println(f.getType());
8 }
9 Field[] fieldDeclared = cls.getDeclaredFields();
10 System.out.println("Here are all declared fields including private "
11 + "and static and protect.");
12 for (Field f : fieldDeclared) {
13 System.out.println(f.getType());
14 }
15 }
16 }
17 /* :
18 Here are public fields.
19 int
20 int
21 Here are all declared fields including private and static and protect.
22 int
23 int
24 long
25 */
2) ドメインフィールドの文字列名に基づいて、ドメインフィールドの値を取得します.
1 public class MyTest {
2 public static void main(String args[]) throws Exception {
3 Object o = new TestClass();
4 // Field 。
5 Field field = o.getClass().getField("firstValue");
6 // Class 。
7 Class<?> type = field.getType();
8 // , Field.getXxx() 。
9 if (type.toString().equals("double"))
10 System.out.println(field.getDouble(o));
11 else if (type.toString().equals("int"))
12 System.out.println(field.getInt(o));
13 }
14 }
15
16 class TestClass {
17 public double firstValue = 3.14;
18 }
19 /* :
20 3.14
21 */
3) 指定したドメインフィールドの値を取得および設定します.
1 public class MyTest {
2 public static void main(String args[]) throws Exception {
3 Bean demo = new Bean();
4 Class<? extends Bean> cl = demo.getClass();
5
6 Field field = cl.getField("id");
7 field.set(demo, new Long(10));
8 Object value = field.get(demo);
9 System.out.println("Value = " + value);
10
11 field = cl.getField("now");
12 field.set(null, new Date());
13 value = field.get(null);
14 System.out.println("Value = " + value);
15 }
16 }
17 class Bean {
18 public static Date now;
19 public Long id;
20 public String name;
21 }
22 /* :
23 Value = 10
24 Value = Sun Sep 04 11:38:15 CST 2011
25 */
4. 汎用情報の反射: 1) クラスの汎用インタフェース情報の取得
1 public static void main(String args[]) throws Exception {
2 Class<?> c = Class.forName("java.util.ArrayList");
3 System.out.format("Class:%n %s%n", c.getCanonicalName());
4 System.out.format("Modifiers:%n %s%n",
5 Modifier.toString(c.getModifiers()));
6
7 System.out.format("Type Parameters:%n");
8 //
9 TypeVariable[] tv = c.getTypeParameters();
10 if (tv.length != 0) {
11 System.out.format(" ");
12 for (TypeVariable t : tv)
13 System.out.format("%s ", t.getName());
14 System.out.println();
15 } else {
16 System.out.format(" -- No Type Parameters --%n%n");
17 }
18
19 System.out.format("Implemented Interfaces:%n");
20 // , , 。
21 //getInterfaces() 。
22 Type[] intfs = c.getGenericInterfaces();
23 if (intfs.length != 0) {
24 for (Type intf : intfs)
25 System.out.format(" %s%n", intf.toString());
26 System.out.format("%n");
27 } else {
28 System.out.format(" -- No Implemented Interfaces --%n%n");
29 }
30 }
31 /* :
32 Class:
33 java.util.ArrayList
34 Modifiers:
35 public
36 Type Parameters:
37 E
38 Implemented Interfaces:
39 java.util.List<E>
40 interface java.util.RandomAccess
41 interface java.lang.Cloneable
42 interface java.io.Serializable
43 */
2) クラスの汎用インタフェース、インタフェース、汎用スーパークラス、およびスーパークラス情報の比較を取得します.
1 public static void main(String args[]) throws Exception {
2 //1.
3 Class<?> ts = TreeMap.class.getSuperclass();
4 System.out.println(ts + "
");
5 //2. , 。
6 Type t = TreeMap.class.getGenericSuperclass();
7 System.out.println(t + "
");
8 //3.
9 Class<?>[] is = TreeMap.class.getInterfaces();
10 for (int i = 0; i < is.length; i++) {
11 System.out.println(is[i]);
12 }
13 System.out.println();
14 //2. , 。
15 Type[] ts2 = TreeMap.class.getGenericInterfaces();
16 for (int i = 0; i < ts2.length; i++) {
17 System.out.println(ts2[i]);
18 }
19 }
20 /* :
21 class java.util.AbstractMap
22
23 java.util.AbstractMap<K, V>
24
25 interface java.util.NavigableMap
26 interface java.lang.Cloneable
27 interface java.io.Serializable
28
29 java.util.NavigableMap<K, V>
30 interface java.lang.Cloneable
31 interface java.io.Serializable
32 */
3) 戻り値とパラメータリストの汎用タイプ情報を含むドメインメソッドの署名情報を出力します.
1 import static java.lang.System.out;
2 public class MyTest {
3 private static final String fmt = "%24s: %s%n";
4 public static void main(String args[]) throws Exception {
5 Class<?> c = Class.forName("java.util.ArrayList");
6 Method[] allMethods = c.getDeclaredMethods();
7 for (Method m : allMethods) {
8 //1. , ,
9 out.format("%s%n", m.toGenericString());
10 //2.
11 out.format(fmt, "ReturnType", m.getReturnType());
12 //3. , ,
13 out.format(fmt, "GenericReturnType", m.getGenericReturnType());
14 //4.
15 Class<?>[] pType = m.getParameterTypes();
16 //5. , ,
17 Type[] gpType = m.getGenericParameterTypes();
18 for (int i = 0; i < pType.length; i++) {
19 out.format(fmt, "ParameterType", pType[i]);
20 out.format(fmt, "GenericParameterType", gpType[i]);
21 }
22 }
23 }
24 }
25 /* ( , ):
26 ... ...
27 public void java.util.ArrayList.add(int,E)
28 ReturnType: void
29 GenericReturnType: void
30 ParameterType: int
31 GenericParameterType: int
32 ParameterType: class java.lang.Object
33 GenericParameterType: E
34 ... ...
35 public <T> T[] java.util.ArrayList.toArray(T[])
36 ReturnType: class [Ljava.lang.Object;
37 GenericReturnType: T[]
38 ParameterType: class [Ljava.lang.Object;
39 GenericParameterType: T[]
40 ... ...
41 */
4) オブジェクトフィールドのタイプ情報を出力します.
1 public class MyTest<T> {
2 public String name = "Alice";
3 public List<Integer> list;
4 public T val;
5
6 public static void main(String args[]) throws Exception {
7 Class<?> c = Class.forName("MyTest");
8 for (Field f : c.getFields()) {
9 //getType getGenericType
10 //getReturnType getGenericReturnType
11 System.out.format("Type: %s%n", f.getType());
12 System.out.format("GenericType: %s%n", f.getGenericType());
13 }
14 }
15 }
16 /* :
17 Type: class java.lang.String
18 GenericType: class java.lang.String
19 Type: interface java.util.List
20 GenericType: java.util.List<java.lang.Integer>
21 Type: class java.lang.Object
22 GenericType: T
23 */
5. 列挙された反射: 1) 列挙された定数のリストを取得するには、次の手順に従います.
1 import static java.lang.System.out;
2 public class MyTest {
3 public static void main(String args[]) throws Exception {
4 //
5 if (!Eon.class.isEnum())
6 return;
7 Class<?> c = Eon.class;
8 out.format("Enum name: %s%nEnum constants: %s%n", c.getName(),
9 Arrays.asList(c.getEnumConstants()));
10 Eon[] vs = Eon.values();
11 for (Eon e : vs) {
12 out.println("The name is " + e.name() + "\tThe ordinal is " + e.ordinal());
13 }
14 }
15 }
16
17 enum Eon {
18 HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC
19 }
20 /* :
21 Enum name: Eon
22 Enum constants: [HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC]
23 The name is HADEAN The ordinal is 0
24 The name is ARCHAEAN The ordinal is 1
25 The name is PROTEROZOIC The ordinal is 2
26 The name is PHANEROZOIC The ordinal is 3
27 */
6. ドメインメソッドの反射: 1) クラスコンストラクタの反射オブジェクトから新しいインスタンスを作成します.
1 public static void main(String args[]) throws Exception {
2 // Point
3 // Point(int x,int y);
4 Constructor<Point> con = Point.class.getConstructor(new Class[] {
5 int.class, int.class });
6 // Object , Point
7 //int , Integer.
8 Point obj = (Point) con.newInstance(new Object[] {
9 new Integer(123), new Integer(123) });
10 System.out.println(obj);
11 }
12 /* :
13 java.awt.Point[x=123,y=123]
14 */
2) ドメインメソッドの名前とパラメータリスト署名によって、このメソッド(静的メソッド)を取得して実行します.
1 public static void main(String args[]) throws Exception {
2 // 。
3 Method m = Math.class.getMethod("sqrt", new Class[] { double.class });
4 // , null, ,
5 // this , ,
6 // 。 Math.sqrt double
7 // 。invoke Object ,
8 // , 。
9 Double o = (Double)m.invoke(null, 10);
10 System.out.println(o.doubleValue());
11 }
12 /* :
13 3.1622776601683795
14 */
3) このメソッド(非静的メソッド)は、ドメインメソッドの名前とパラメータリスト署名によって取得され、実行されます.
1 public class MyTest {
2 public static void main(String args[]) throws Exception {
3 String firstWord = "Hello ";
4 String secondWord = "everybody.";
5 String bothWords = append(firstWord, secondWord);
6 System.out.println(bothWords);
7 }
8
9 public static String append(String firstWord, String secondWord) {
10 String result = null;
11 Class<String> c = String.class;
12 //
13 Class<?>[] parameterTypes = new Class[] { String.class };
14 Method concatMethod;
15 //
16 Object[] arguments = new Object[] { secondWord };
17 try {
18 //
19 concatMethod = c.getMethod("concat", parameterTypes);
20 // , ,
21 // firstWord.concat(secondword);
22 result = (String) concatMethod.invoke(firstWord, arguments);
23 } catch (NoSuchMethodException e) {
24 System.out.println(e);
25 } catch (IllegalAccessException e) {
26 System.out.println(e);
27 } catch (InvocationTargetException e) {
28 System.out.println(e);
29 }
30 return result;
31 }
32 }
33 /* :
34 Hello everybody.
35 */
4) 呼び出したオブジェクトを反射するプライベートドメインメソッド:
1 public class MyTest {
2 public static void main(String args[]) throws Exception {
3 TestClass tc = new TestClass();
4 Class<?> c = tc.getClass();
5 Method m = c.getDeclaredMethod("m");
6 // private
7 // true, IllegalAccessException
8 m.setAccessible(true);
9 Object o = m.invoke(tc);
10 }
11 }
12 class TestClass {
13 private void m() {
14 System.out.println("This is private method TestClass.m().");
15 }
16 }
17 /* :
18 This is private method TestClass.m().
19 */
5) スタックフレームから現在のメソッドの名前を取得します.
1 public static void main(String args[]) throws Exception {
2 System.out.println(new Exception().getStackTrace()[0].getMethodName());
3
4 // 0 getStackTrace()
5 System.out.println(Thread.currentThread().getStackTrace()[1].getFileName());
6 System.out.println(Thread.currentThread().getStackTrace()[1].getClassName());
7 System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName());
8 System.out.println(Thread.currentThread().getStackTrace()[1].getLineNumber());
9
10 }
11 /* :
12 main
13 MyTest.java
14 MyTest
15 main
16 12
17 */
7. 反射ベースのメソッド呼び出しと通常のメソッド呼び出しの効率の違い: 私達は本編の初めの部分ですでに反射が確かに私達のプログラムに極めて大きい柔軟性をもたらすことができることに言及して、現在多くの流行の枠組みはすべてJavaが提供する反射のメカニズムに非常に依存して、反射はほとんど至る所見られます.しかしこれは私達が彼の理由を乱用することになることができなくて、やはりあの言葉、無料の昼食がなくて、反射の柔軟性は極めて大きい効率の犠牲で交換しますはい、次の例を参照してください.
1 public class MyTest {
2 public static void main(String args[]) throws Exception {
3 try {
4 final int CALL_AMOUNT = 1000000;
5 final MyTest ri = new MyTest();
6 int idx = 0;
7 //1. ( )
8 long millis = System.currentTimeMillis();
9 for (idx = 0; idx < CALL_AMOUNT; ++idx)
10 ri.getValue();
11 System.out.println("Calling method " + CALL_AMOUNT
12 + " times programatically took "
13 + (System.currentTimeMillis() - millis) + " millis");
14
15 //2. , 。
16 millis = System.currentTimeMillis();
17 for (idx = 0; idx < CALL_AMOUNT; idx++) {
18 Method md = ri.getClass().getMethod("getValue", null);
19 md.invoke(ri, null);
20 }
21 System.out.println("Calling method " + CALL_AMOUNT
22 + " times reflexively with lookup took "
23 + (System.currentTimeMillis() - millis) + " millis");
24
25 //3. ,
26 // , , 。
27 Method md = ri.getClass().getMethod("getValue", null);
28 millis = System.currentTimeMillis();
29 for (idx = 0; idx < CALL_AMOUNT; idx++)
30 md.invoke(ri, null);
31 System.out.println("Calling method " + CALL_AMOUNT
32 + " times reflexively with cache took "
33 + (System.currentTimeMillis() - millis) + " millis");
34 } catch (final NoSuchMethodException ex) {
35 throw new RuntimeException(ex);
36 } catch (final InvocationTargetException ex) {
37 throw new RuntimeException(ex);
38 } catch (final IllegalAccessException ex) {
39 throw new RuntimeException(ex);
40 }
41 }
42 public String getValue() {
43 return this.value;
44 }
45 private String value = "some value";
46 }
47 /* :
48 Calling method 1000000 times programatically took 0 millis
49 Calling method 1000000 times reflexively with lookup took 1422 millis
50 Calling method 1000000 times reflexively with cache took 110 millis
51 */