一:反射的概念
反射就是加载类,然后获取类的属性、方法、构造函数等。
二:加载类到内存(有硬盘字节码文件到内存)
三种加载类的方式:
1 @Test 2 // 测试加载类 3 public void test1() throws Exception { 4 // 第一种方式 5 Class clazz1 = Class.forName("com.hlcui.test.Person"); 6 // 第二种方式 7 Class clazz2 = new Person().getClass(); 8 // 第三种方式 9 Class clazz3 = Person.class; 10 }
三:反射类中的组成部分
1:使用getConstructor()、getMethod()、getField(),可以反射public修饰的成员,
如果需要反射private修饰的成员,需要使用下面的getDeclaredXXX()。
2:反射构造方法
Person定义的构造方法:
1 public Person() { 2 System.out.println("调用无参构造方法..."); 3 } 4 5 public Person(String name) { 6 System.out.println(name); 7 } 8 9 public Person(String name, int age) { 10 System.out.println(name + ":" + age); 11 } 12 13 private Person(List<String> list) { 14 System.out.println(list); 15 }
反射构造方法代码:
1 @Test 2 // 反射无参构造方法 3 public void test2() throws Exception { 4 Class clazz1 = Class.forName("com.hlcui.test.Person"); 5 Constructor c = clazz1.getConstructor(null); 6 Person p = (Person) c.newInstance(null); 7 System.out.println(p.name); 8 } 9 10 @Test 11 // 反射参数String的构造方法 12 public void test3() throws Exception { 13 Class clazz1 = Class.forName("com.hlcui.test.Person"); 14 Constructor c = clazz1.getConstructor(String.class); 15 Person p = (Person) c.newInstance("Jack"); 16 System.out.println(p.name); 17 } 18 19 @Test 20 // 反射参数为String、int的构造方法 21 public void test4() throws Exception { 22 Class clazz1 = Class.forName("com.hlcui.test.Person"); 23 Constructor c = clazz1.getConstructor(String.class, int.class); 24 Person p = (Person) c.newInstance("Jack", 27); 25 System.out.println(p.name); 26 } 27 28 @Test 29 // 反射参数为List的构造方法 30 public void test5() throws Exception { 31 Class clazz1 = Class.forName("com.hlcui.test.Person"); 32 Constructor c = clazz1.getDeclaredConstructor(List.class); 33 c.setAccessible(true); 34 Person p = (Person) c.newInstance(new ArrayList()); 35 System.out.println(p.name); 36 }
其中反射参数为List的构造方法,因为构造方法时private修饰的,所以必须使用getDeclaredConstructor()获取构造方法,
同时需要设置强制方法setAccessible(true);
也可以直接使用反射类获取对象,代码如下:
1 @Test 2 public void test6() throws Exception { 3 Class clazz1 = Class.forName("com.hlcui.test.Person"); 4 Person p = (Person) clazz1.newInstance(); 5 System.out.println(p.name); 6 }
2:反射方法
反射方法代码如下:
Person类中定义的普通方法:
1 public void abc() { 2 System.out.println("abc..."); 3 } 4 5 public String abc(String name) { 6 return name; 7 } 8 9 public void abc(String name, int[] i) { 10 System.out.println(name + ":" + i); 11 } 12 13 public Class[] abc(InputStream in) { 14 return new Class[] { String.class }; 15 } 16 17 public static void abc(int i) { 18 System.out.println(i); 19 }
反射普通方法:
1 @Test 2 // public void abc() 3 public void test7() throws Exception { 4 Person p = new Person(); 5 Class clazz1 = Class.forName("com.hlcui.test.Person"); 6 Method m = clazz1.getMethod("abc", null); 7 m.invoke(p, null); 8 } 9 10 @Test 11 // public String abc(String name) 12 public void test8() throws Exception { 13 Person p = new Person(); 14 Class clazz1 = Class.forName("com.hlcui.test.Person"); 15 Method m = clazz1.getMethod("abc", String.class); 16 System.out.println(m.invoke(p, "Tom")); 17 } 18 19 @Test 20 // public void abc(String name, int[] i) 21 public void test9() throws Exception { 22 Person p = new Person(); 23 Class clazz1 = Class.forName("com.hlcui.test.Person"); 24 Method m = clazz1.getMethod("abc", String.class, int[].class); 25 m.invoke(p, "Jack", new int[] { 1, 2, 3 }); 26 } 27 28 @Test 29 // public Class[] abc(InputStream in) 30 public void test10() throws Exception { 31 Person p = new Person(); 32 Class clazz1 = Class.forName("com.hlcui.test.Person"); 33 Method m = clazz1.getMethod("abc", InputStream.class); 34 Class[] cc = (Class[]) m.invoke(p, new FileInputStream("f:/1.txt")); 35 System.out.println(cc[0]); 36 } 37 38 @Test 39 // public static void abc(int i) 40 public void test11() throws Exception { 41 Class clazz1 = Class.forName("com.hlcui.test.Person"); 42 Method m = clazz1.getMethod("abc", int.class); 43 m.invoke(null, 27); 44 }
Person定义的main方法:
1 public static void main(String[] args) { 2 System.out.println("调用main..."); 3 }
反射main方法:
1 @Test 2 // public static void main(String[] args) 3 public void test12() throws Exception { 4 Person p = new Person(); 5 Class clazz1 = Class.forName("com.hlcui.test.Person"); 6 Method m = clazz1.getMethod("main", String[].class); 7 // m.invoke(p, (Object)new String[]{"1","2","3"}); 8 m.invoke(p, new Object[] { new String[] { "1", "2", "3" } }); 9 }
这里要注意,由于jdk5兼容了jdk1.4的特性,传入字符串数组时,它会对传入参数进行拆分,
如:new String[]{"1","2","3"}将被拆分成"1"、"2"、"3",所以直接反射会报参数个数异常,
有两种处理方法:
a:在前面加上Object b:将数组再次放到数组中
3:反射字段
Person类中定义字段:
1 public String name = "Tom"; 2 private int age = 27; 3 private static double salary = 8000.0;
反射字段:
1 @Test 2 // public String name = "Tom"; 3 public void test13() throws Exception { 4 Person p = new Person(); 5 Class clazz1 = Class.forName("com.hlcui.test.Person"); 6 Field f = clazz1.getField("name"); 7 f.set(p, "Jack"); 8 Object obj = f.get(p); 9 Class type = f.getType(); 10 if (type.equals(String.class)) { 11 String value = (String) obj; 12 System.out.println(value); 13 } 14 } 15 16 @Test 17 // private int age = 27; 18 public void test14() throws Exception { 19 Person p = new Person(); 20 Class clazz1 = Class.forName("com.hlcui.test.Person"); 21 Field f = clazz1.getDeclaredField("age"); 22 f.setAccessible(true); 23 int i = (Integer) f.get(p); 24 System.out.println(i); 25 } 26 27 @Test 28 // private static double salary = 8000.0; 29 public void test15() throws Exception { 30 Person p = new Person(); 31 Class clazz1 = Class.forName("com.hlcui.test.Person"); 32 Field f = clazz1.getDeclaredField("salary"); 33 f.setAccessible(true); 34 double d = (Double) f.get(p); 35 System.out.println(d); 36 }
反射的知识就总结到这里!