[2014-09-11]JAVA笔记_反射(Reflection)
2014-09-11 13:06
543 查看
一、简介
JAVA 的反射机制可以在java运行时动态获取类的信息以及动态调用对象的方法。
二、功能
· 在运行时判断任意一个对象所属的类。
· 在运行时构造任意一个类的对象。
· 在运行时判断任意一个类所具有的成员变量的方法。
· 在运行是调用任意一个对象的方法。
三、 在JDK中,主要由一下类来实现Java反射机制,这些类都位于 java.lang.reflec 包中
· Class 类: 代表一个类。(特殊:位于java.lang包下。每个类都会有与之关联的Class)
· Field 类: 代表类的成员变量(成员变量也成为类的属性)。
· Methoud 类: 代表类的方法。
· Constructor 类: 代表类的构造方法。
· Array 类: 提供了动态创建数组,以及访问数组的元素的静态方法。
四、 使用反射调用类的方法
· Java 中,无论生成某个类的多少个对象,这些对象都会对应于同一个 Class 对象。
例子:使用反射调用某个类中的某个方法
总结: 想要使用反射机制调用某个类中的方法,大致步骤如下:
1. 获得类对应的Class对象。
2. 可以使用 newInstance() 方法生成类的实例。
3. 获得 Method 对象。使用Class对象的 getMethod() 方法。参数1:需要获得方法的名称; 参数2: 这个方法接受哪些参数,把这些参数所对应的Class对象以数组或者离散的方式传入进去。
4. Method 对象获得后使用 invoke() 方法实现真正的调用。参数1: 你所需要调用的是哪个对象的方法; 参数2: 方法接受的参数。
备注:步骤3和4中的参数2,是对应关系。可以把第一个看成描述参数,第二个是实际参数。
五、 获取某个类或某个对象所对应的 Class 对象的常用的3中方式:
1. 使用 Class 类的静态方法 forName(): Class.forName("java.lang.String");
2. 使用类的.class 语法:String.class;
3. 使用对象的 getClass() 方法:String s = "aaa"; Class<?> class = s.getClass();
六、通过类的构造方法来生成对象
若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
1) 先获得 Class 对象,然后通过该 Class 对象的 newInstance()方法直接生成即可:
Class<?> classType = String.class;
Object obj = classType.newInstance();
2) 先获得 Class 对象,然后通过该对象获得对应的 Constructor 对象,再通过该 Constructor对象的 newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});
Object obj = cons.newInstance(new Object[]{“hello” , 3});
七、常用方法
·Class类是Reflectoin API 中的核心类,它有以下方法:
- getName(): 获得类的完整名字。
- getFields(): 获得类的 public 类型的属性。
- getDeclaredFields():获得类的所有属性。
- getMethods(): 获得类的 public 类型的方法。
- getDeclaredMethods():获得类的所有方法。
- getMehod(String name, Class[] parameterTypes): 获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。
- getConstructors():获得类的 public 类型的构造方法。
- getConstructor(Class[] paramterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
- newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
八、 Array类
java.lang.Array 类提供了动态创建和访问数组元素的各种静态方法。
一维数组
二维数组:
Integer.TYPE 返回的是int, 而Integer.class返回的是 Integer 类所对应的 Class 对象。
九、使用反射访问私有成员变量、方法
java访问私有成员变量
package com.bob.reflection;
public class PrivateMember {
private String name = "zhangsan";
private String name2 = "lisi";
public String getName(){
return name;
}
}
JAVA 的反射机制可以在java运行时动态获取类的信息以及动态调用对象的方法。
二、功能
· 在运行时判断任意一个对象所属的类。
· 在运行时构造任意一个类的对象。
· 在运行时判断任意一个类所具有的成员变量的方法。
· 在运行是调用任意一个对象的方法。
三、 在JDK中,主要由一下类来实现Java反射机制,这些类都位于 java.lang.reflec 包中
· Class 类: 代表一个类。(特殊:位于java.lang包下。每个类都会有与之关联的Class)
· Field 类: 代表类的成员变量(成员变量也成为类的属性)。
· Methoud 类: 代表类的方法。
· Constructor 类: 代表类的构造方法。
· Array 类: 提供了动态创建数组,以及访问数组的元素的静态方法。
四、 使用反射调用类的方法
· Java 中,无论生成某个类的多少个对象,这些对象都会对应于同一个 Class 对象。
/** * 读取命令行参数指定的类名,然后打印这个类所具有的方法 */ package com.bob.reflection; import java.lang.reflect.Method; public class DumpMethods { public static void main(String[] args) throws Exception { //使用反射第一步首先获你想操作类的对应的Class对象 Class<?> classType = Class.forName("java.lang.String"); //通过Class的静态方法获取类名 Method[] methodType = classType.getDeclaredMethods(); //获得所有声明的方法 for(Method method : methodType){ System.out.println(method); } } }
例子:使用反射调用某个类中的某个方法
package com.bob.reflection; import java.lang.reflect.Method; public class InvokeTest { public int add(int param1, int param2){ return param1 + param2; } public String echo(String message){ return "Hello:" + message; } public static void main(String[] args) throws Exception { // InvokeTest test = new InvokeTest(); // System.out.println(test.add(1, 2)); // System.out.println(test.echo("Bob")); //使用反射完成功能 //第一步还是获取类所对应的Class对象 Class<?> classType = InvokeTest.class; //通过类名.class语法方式获得类的Class对象 //使用newInstance()方法生成invokeTest实例 Object invokeTest = classType.newInstance(); //获取类中的指定方法。参数1:方法名; 参数2:方法参数对应的Class对象所构成的Class类型数组 Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class} ); //addMethod方法会对应上add方法 //使用Method类中的invoke()方法调用目标方法。 //参数1:调用哪个对象的方法; 参数2:方法实际接受的参数 Object result = addMethod.invoke(invokeTest, new Object[]{1, 2}); //调用invokeTest对象的addMethod()方法,传递参数 System.out.println((Integer)result); //可以不加Integer,默认返回的是对象 System.out.println("-----------------------------"); //获得类中的指定方法。调用方法前先获得Method对象 Method echoMethod = classType.getDeclaredMethod("echo", new Class[]{String.class}); //调用对应的目标方法 Object result2 = echoMethod.invoke(invokeTest, new Object[]{"Tom"}); //调用invokeTest对象的echoMethod方法,传入参数 System.out.println((String)result2); //可省略强制转换。invoke()方法的返回值总是对象,如果实际是基本类型会自动转换。 } }
总结: 想要使用反射机制调用某个类中的方法,大致步骤如下:
1. 获得类对应的Class对象。
2. 可以使用 newInstance() 方法生成类的实例。
3. 获得 Method 对象。使用Class对象的 getMethod() 方法。参数1:需要获得方法的名称; 参数2: 这个方法接受哪些参数,把这些参数所对应的Class对象以数组或者离散的方式传入进去。
4. Method 对象获得后使用 invoke() 方法实现真正的调用。参数1: 你所需要调用的是哪个对象的方法; 参数2: 方法接受的参数。
备注:步骤3和4中的参数2,是对应关系。可以把第一个看成描述参数,第二个是实际参数。
五、 获取某个类或某个对象所对应的 Class 对象的常用的3中方式:
1. 使用 Class 类的静态方法 forName(): Class.forName("java.lang.String");
2. 使用类的.class 语法:String.class;
3. 使用对象的 getClass() 方法:String s = "aaa"; Class<?> class = s.getClass();
六、通过类的构造方法来生成对象
若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
1) 先获得 Class 对象,然后通过该 Class 对象的 newInstance()方法直接生成即可:
Class<?> classType = String.class;
Object obj = classType.newInstance();
2) 先获得 Class 对象,然后通过该对象获得对应的 Constructor 对象,再通过该 Constructor对象的 newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});
Object obj = cons.newInstance(new Object[]{“hello” , 3});
package com.bob.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectionTester { //实现对Customer对象的拷贝 public Object copy(Object object) throws Exception{ Class<?> classType = object.getClass(); //返回调用getClass()方法运行期的Class对象 // System.out.println(classType.getName()); //要实现将原有的对象拷贝到新的对象首先创建一个新的对象,然后将属性拷贝到新对象 Constructor cons = classType.getConstructor(new Class[]{}); //{}里面代表构造方法的参数 Object objectCopy = cons.newInstance(new Object[]{}); //通过构造方法生成对象 //以上两行代码等价于下面一行。(无参时) //Object objectCopy = classType.newInstance(); //获得对象的所有成员变量 Field[] fields = classType.getDeclaredFields(); for(Field field : fields){ String name = field.getName(); //获得所有属性的名字 //要调用方法需要首先获得Method对象,Method对象的第一个参数是方法的名称。 //方法名规律是属性的首字母大写+前缀 String firstLetter = name.substring(0, 1).toUpperCase(); //将属性的值从第0个开始拷贝到第0个(首字母),然后转换为大写 String getMethodName = "get" + firstLetter + name.substring(1); //获得方法的名称 String setMethodName = "set" + firstLetter + name.substring(1, name.length()); //从第1个开始,到最后一个 //转向Method对象。描述方法 Method getMethod = classType.getMethod(getMethodName, new Class[]{}); Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()}); //获取属性的类型 //调用方法 Object value = getMethod.invoke(object, new Object[]{}); //在目标对象上调用目标对象的方法 setMethod.invoke(objectCopy, new Object[]{value}); //将值拷贝到指定对象 } return objectCopy; } public static void main(String[] args) throws Exception { Customer customer = new Customer("Tom", 20); customer.setId(new Long(10010)); ReflectionTester reflectionTester = new ReflectionTester(); Customer obj2 = (Customer)reflectionTester.copy(customer); // Object obj =reflectionTester.copy(customer); // Customer obj2 = (Customer)obj; System.out.println(obj2.getId() + ", " + obj2.getName() + ", " + obj2.getAge()); } } class Customer{ private Long id; //使用包装类型 private String name; private int age; public Customer(){ } public Customer(String name, int age){ this.name = name; this.age = age; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
七、常用方法
·Class类是Reflectoin API 中的核心类,它有以下方法:
- getName(): 获得类的完整名字。
- getFields(): 获得类的 public 类型的属性。
- getDeclaredFields():获得类的所有属性。
- getMethods(): 获得类的 public 类型的方法。
- getDeclaredMethods():获得类的所有方法。
- getMehod(String name, Class[] parameterTypes): 获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。
- getConstructors():获得类的 public 类型的构造方法。
- getConstructor(Class[] paramterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
- newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
八、 Array类
java.lang.Array 类提供了动态创建和访问数组元素的各种静态方法。
一维数组
package com.bob.reflection; import java.lang.reflect.Array; public class ArrayTester1 { public static void main(String[] args) throws Exception { Class<?> classType = Class.forName("java.lang.String"); //获得字符串类的Class对象 Object array = Array.newInstance(classType, 10); //参数1:数组当中的每个元素的类型 Array.set(array, 5, "hello"); //设置array数组的第5个索引的值 String str = (String)Array.get(array, 5); //获取array数组的第5个元素 System.out.println(str); } }
二维数组:
Integer.TYPE 返回的是int, 而Integer.class返回的是 Integer 类所对应的 Class 对象。
package com.bob.reflection; import java.lang.reflect.Array; public class ArrayTester2 { public static void main(String[] args) { int[] dims = new int[]{5, 10, 15}; Object array = Array.newInstance(Integer.TYPE, dims); //数组的维度由dims决定 Object arrayObj = Array.get(array, 3); // Class<?> clasType = arrayObj.getClass().getComponentType(); arrayObj = Array.get(arrayObj, 5); Array.setInt(arrayObj, 10, 37); int[][][] arrayCase = (int[][][]) array; System.out.println(arrayCase[3][5][10]); } }
九、使用反射访问私有成员变量、方法
package com.bob.reflection; public class Private { private String sayHello(String name){ //私有方法 return "Hello: " + name; } }
package com.bob.reflection; import java.lang.reflect.Method; public class PrivateTest { public static void main(String[] args) throws Exception { Class<?> classType = Class.forName("com.bob.reflection.Private"); //通过构造方法创建对象 Object pri = classType.getConstructor(new Class[]{}).newInstance(new Object[]{}); //使用getDeclaredMethod()方法获得声明的方法。getMethod()方法只能获得public权限的方法 Method myMethod = classType.getDeclaredMethod("sayHello", new Class[]{String.class}); //AccessibleObject类提供了一个标志控制是否执行java访问控制检查 myMethod.setAccessible(true); //压制java语言的访问控制检查。Method类继承自AccessibleObject类 String str = (String)myMethod.invoke(pri, new Object[]{"Bob"}); System.out.println(str); } }
java访问私有成员变量
package com.bob.reflection;
public class PrivateMember {
private String name = "zhangsan";
private String name2 = "lisi";
public String getName(){
return name;
}
}
package com.bob.reflection; import java.lang.reflect.Field; public class PrivateMemberTest { public static void main(String[] args) throws Exception{ // Class<?> classType = Class.forName("com.bob.reflection.PrivateMember"); Class<?> classType = PrivateMember.class; Object obj = classType.getConstructor(new Class[]{}). newInstance(new Object[]{}); Field member = classType.getDeclaredField("name"); //获得私有属性名称 Field member2 = classType.getDeclaredField("name2"); member.setAccessible(true); //压制java语言默认访问控制检查 member2.setAccessible(true); //压制java对第二个属性的访问修饰检查 member.set(obj, "Bob"); member2.set(obj, "Tom"); Object obj2 = classType.getMethod("getName", new Class[]{}) .invoke(obj, new Object[]{}); System.out.println((String)obj2); System.out.println(member2.get(obj)); //直接是用Field的get() } }
相关文章推荐
- Java高级语法笔记-反射机制(Reflection) (1)
- 黑马程序员---------Java反射(Reflection)笔记
- Java Reflection(反射) 入门学习笔记 之一
- JAVA学习笔记(六十一)- 反射Reflection
- java学习笔记 反射reflection相关知识点小结
- Java学习笔记之反射(Reflection)
- Java Reflection(反射) 入门学习笔记 之三 (Array)
- Java学习笔记之反射(Reflection)
- 从class.forName()说java中的reflection(反射/映像)
- Java反射经典实例 Java Reflection Cookbook
- Java Reflection (JAVA反射) 研究
- Java Reflection (JAVA反射)详解
- java反射reflection需要注意的几点
- 利用Java Reflection(反射)原理,在hibernate里面实现对单表、视图的动态组合查询
- Java Reflection (JAVA反射转载)
- Java Reflection (JAVA反射)
- Java反射经典实例 Java Reflection Cookbook
- Java反射经典实例 Java Reflection Cookbook
- Java Reflection (JAVA反射)
- Java反射经典实例 Java Reflection Cookbook