最近的开发,遇到一个调用其他工程类方法的问题,用到一个简单的方法--java反射。利用反射机制,获取类实例,再获取相应方法,最后执行,得到结果。
具体应用为:
Class<?> CIRWindowsAPI = Class.forName("com.fujitsu.ci.runtime.common.CIRWindowsAPI");
Method isUNCPath = CIRWindowsAPI.getDeclaredMethod("isUNCPath", String.class);
Object result = isUNCPath.invoke(null, f.getPath());
return Boolean.valueOf(result.toString());
关于java反射还不了解,于是上网搜索相关内容,整理如下:
1.Class类
在java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例。
由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式:
- 对象.getClass( )
- 类.Class
- forName( )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
class Test { } public class Demo { public static void main(String[] args) { //方式一: Test t = new Test(); Class<? extends Test> c1 = t.getClass(); System.out.println(c1); //方式二: //为了避免特殊性,这里不用Test类,而用java库中的String类 Class<String> c2 = String. class ; System.out.println(c2); //方式三: //forName()方法会抛出异常 Class<?> c3 = null ; try { c3 = Class.forName( "Test" ); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c3); } } |
其中,forName( )方法需要重点掌握,因为它可以在类不确定的情况下实例化Class,更具灵活性
2.Class类的应用
获取类的结构
要通过反射获取类的结构我们这里要导入一个新的包java.lang.reflect
实例a:取得类的构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.lang.reflect.Constructor; import java.util.Arrays; public class Demo { //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了 public static void main(String[] args) throws Exception { Class<?> c = null ; try { c = Class.forName( "java.lang.Boolean" ); } catch (ClassNotFoundException e) { e.printStackTrace(); } //这里的getConstructors()方法返回的是一个Constructor数组 Constructor<?>[] cons = c.getConstructors(); //打印的方式你可以自己写,为了方便我用Arrays.toString(),凑合着看 System.out.println(Arrays.toString(cons)); } } |
实例b:取得类所实现的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import java.util.Arrays; public class Demo { public static void main(String[] args) throws Exception { Class<?> c = null ; try { c = Class.forName( "java.lang.Boolean" ); } catch (ClassNotFoundException e) { e.printStackTrace(); } Class<?>[] in = c.getInterfaces(); System.out.println(Arrays.toString(in)); } } |
实例c:取得父类
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Demo { public static void main(String[] args) throws Exception { Class<?> c = null ; try { c = Class.forName( "java.lang.Boolean" ); } catch (ClassNotFoundException e) { e.printStackTrace(); } //注意了,这里不会是数组,why? Class<?> su = c.getSuperclass(); System.out.println(su); } } |
别忘了,java中是单继承,父类只有一个
实例d:取得类的全部方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import java.lang.reflect.Method; public class Demo { public static void main(String[] args) throws Exception { Class<?> c = null ; try { c = Class.forName( "java.lang.Boolean" ); } catch (ClassNotFoundException e) { e.printStackTrace(); } Method[] m = c.getMethods(); //好吧,这次我就大发慈悲的写个打印列表出来 for ( int i = 0 ; i < m.length; i++) { System.out.println(m[i]); } } } |
实例e:取得本类的全部属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.lang.reflect.Field; class Person { private String name; private int age; } public class Demo { public static void main(String[] args) throws Exception { Class<?> c = null ; try { c = Class.forName( "Person" ); } catch (ClassNotFoundException e) { e.printStackTrace(); } Field[] f = c.getDeclaredFields(); for ( int i = 0 ; i < f.length; i++) { System.out.println(f[i]); } } } |
getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性
实例f:获取本类中属性的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import java.lang.reflect.Field; class Person { public String name; private int age; public Person(String name, int age) { this .name = name; this .age = age; } } public class Demo { public static void main(String[] args) throws Exception { Person p = new Person( "zhangsan" , 12 ); Class<?> c = p.getClass(); //获取公共属性的值 Field f1 = c.getField( "name" ); //get(p)表明要获取是哪个对象的值 String str = (String) f1.get(p); System.out.println( "姓名: " + str); //获取私有属性的值 Field f2 = c.getDeclaredField( "age" ); //age是私有属性,所以要设置安全检查为true f2.setAccessible( true ); int age = ( int ) f2.get(p); System.out.println( "年龄: " + age); } } |
要注意的是:setAccessible()方法可以设置是否访问和修改私有属性
3.
反射的应用
实例g:通过反射修改属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import java.lang.reflect.Field; class Person { private String name; public Person(String name) { this .name = name; } public String toString() { return "姓名: " + this .name; } } public class Demo { public static void main(String[] args) throws Exception { Person p = new Person( "王二狗" ); System.out.println(p); Class<?> c = p.getClass(); //定义要修改的属性 Field f = c.getDeclaredField( "name" ); f.setAccessible( true ); //修改属性,传入要设置的对象和值 f.set(p, "张二蛋" ); System.out.println(p); } } |
几个方法都是有联系的,如果看不懂就先熟悉上面几个例子
实例h:通过反射调用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import java.lang.reflect.Method; class Person { public void print( int i) { System.out.println( "我在写数字: " + i); } public static void say(String str) { System.out.println( "我在说: " + str); } } public class Demo { public static void main(String[] args) throws Exception { Person p = new Person(); Class<?> c = p.getClass(); //getMethod()方法需要传入方法名,和参数类型 Method m1 = c.getMethod( "print" , int . class ); //invoke()表示调用的意思,需要传入对象和参数 m1.invoke(p, 10 ); Method m2 = c.getMethod( "say" , String. class ); //这里的null表示不由对象调用,也就是静态方法 m2.invoke( null , "你妹" ); } } |
这里演示了一个普通的有参方法和一个静态方法
既然有参数的都写出来了,那么无参的就更简单了,直接传入一个对象即可
实例i:通过反射操作数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.lang.reflect.Array; public class Demo { public static void main(String[] args) throws Exception { int [] arr = { 1 , 2 , 3 , 4 , 5 }; Class<?> c = arr.getClass().getComponentType(); System.out.println( "数组类型: " + c.getName()); int len = Array.getLength(arr); System.out.println( "数组长度: " + len); System.out.print( "遍历数组: " ); for ( int i = 0 ; i < len; i++) { System.out.print(Array.get(arr, i) + " " ); } System.out.println(); //修改数组 System.out.println( "修改前的第一个元素: " + Array.get(arr, 0 )); Array.set(arr, 0 , 3 ); System.out.println( "修改后的第一个元素: " + Array.get(arr, 0 )); } } |
这里要注意一点,getComponentType( )返回的是数组元素的Class。
以上是初级的理解,更多用法还需继续学习。
原文请参考:http://www.cnblogs.com/nerxious/archive/2012/12/24/2829446.html