反射:当一个字节码文件加载到内存的时候,JVM会对该字节码进行解剖,然后创建一个对象的Class对象,把字节码文件的信息全部都存储到该Class对象中,我们只要获取到Class对象,我们就可以使用字节码对象创建对象、设置对象的属性或者调用对象的方法等操作。
Java提供了三种方式获取类的字节码:
forName("包名.类名") forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。
类名.class
对象.getClass()
注意:在反射技术中,一个类的任何成员都有对应的类进行描述。例如:成员变量(Field类) 方法(Method类)
package com.cn.reflect;
public class Person {
private int id;
String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
private Person() {
}
public void eat(){
System.out.println(name + "高高兴兴吃饭。。。");
}
public void eat(int num){
System.out.println(name + "高高兴兴吃了" + num + "大碗饭。。。");
}
private void sleep(){
System.out.println(name + "偷偷睡觉。。。");
}
private static void work(){
System.out.println("努力工作。。。");
}
public void sum(int[] arr){
System.out.println("长度是" + arr.length);
}
@Override
public String toString() {
return "编号" + this.id + "\t姓名:" + this.name;
}
}
3种方式获取Class对象:
package com.cn.reflect;
/**
* Author:Liu Zhiyong
* Version:Version_1
* Date:2016年8月26日21:59:48
* Desc:
反射:当一个字节码文件加载到内存的时候,JVM会对该字节码进行解剖,然后创建一个对象的Class对象,把字节码文件的信息全部都存储到该Class对象中,我们只要获取到Class对象,我们就可以使用字节码对象设置对象的属性或者调用对象的方法等操作。
Java提供了三种方式获取类的字节码:
forName("包名.类名") forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。
类名.class
对象.getClass()
注意:在反射技术中,一个类的任何成员都有对应的类进行描述。例如:成员变量(Field类) 方法(Method类)
*/
public class Demo1 {
Person p;
public static void main(String[] args) throws ClassNotFoundException {
// Person p = new Person(110, "木丁西");
//推荐使用:获取Class对象的方式1:
Class c1 = Class.forName("com.cn.reflect.Person");
System.out.println(c1);
//获取Class对象的方式2:通过类名获取
Class c2 = Person.class;
System.out.println(c2);
//获取Class对象的方式3:通过对象获取
// Class c3 = new Person().getClass();
// System.out.println("c1 == c2 == c3 吗?" + (c1==c2 && c2==c3));
}
}
通过Class对象获取构造方法:
package com.cn.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Author:Liu Zhiyong
* Version:Version_1
* Date:2016年8月26日22:27:30
* Desc:
如何通过Class对象获取构造方法。
*/
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//获取到对应的Class对象
Class c1 = Class.forName("com.cn.reflect.Person");
//通过Class对象获取对应的构造方法
Constructor[] constructors = c1.getConstructors(); //获取此类所有公共的构造方法
for(Constructor c : constructors){
System.out.println(c);
}
Constructor[] constructors2 = c1.getDeclaredConstructors(); //获取此类的所有的构造方法,包括私有的在内
for(Constructor c : constructors2){
System.out.println(c);
}
Constructor<Person> c = c1.getConstructor(int.class, String.class);//获取单个的指定的构造方法
Person p = (Person)c.newInstance(120, "刘先森"); //newInstance() 创建一个对象
Constructor<Person> c2 = c1.getDeclaredConstructor();//获取单个的指定的构造方法
System.out.println(c2);
c2.setAccessible(true);//设置
Person p2 = c2.newInstance();
System.out.println(p2);
}
}
在反射技术中使用了Method类描述方法:
package com.cn.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Author:Liu Zhiyong
* Version:Version_1
* Date:2016年8月27日10:38:40
* Desc:
通过Class对象获取到对应的方法。
在反射技术中使用了Method类描述方法。
*/
public class Demo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
//获取对应 的Class对象
Class c = Class.forName("com.cn.reflect.Person");
//获取所有公共的方法
Method[] methods = c.getMethods();//getMethods()获取所有公共的方法,包括父类的
for(Method m : methods){
System.out.println(m);
}
System.out.println("==================================");
Method[] methods2 = c.getDeclaredMethods();//getDeclaredMethods()获取到所有的方法,但是不包含父类的方法
for(Method m : methods2){
System.out.println(m);
}
System.out.println("==================================");
Method method = c.getMethod("eat", null);
System.out.println(method);
System.out.println("==================================");
Method method2 = c.getMethod("eat", int.class);
System.out.println(method2);
System.out.println("==================================");
Constructor constructor = c.getConstructor(int.class, String.class);
Person p = (Person)constructor.newInstance(120, "小木");
method2.invoke(p, 3);//invoke() 第一个参数:方法的调用对象。 第二个参数:方法所需要的参数。
System.out.println("==================================");
//执行私有的方法
Method method3 = c.getDeclaredMethod("sleep", null);//获取私有方法
method3.setAccessible(true);//设置访问权限允许访问
method3.invoke(p, null);
System.out.println("==================================");
//执行静态的私有的方法
Method method4 = c.getDeclaredMethod("work", null);
method4.setAccessible(true);//设置访问权限允许访问
method4.invoke(null, null);//如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。
System.out.println("==================================");
//数组类型获取
Method method5 = c.getMethod("sum", int[].class);
method5.invoke(p, new int[]{1, 3, 5, 7, 9});
}
}
在反射技术中使用了Field类描述了成员变量:
package com.cn.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* Author:Liu Zhiyong
* Version:Version_1
* Date:2016年8月27日11:09:50
* Desc:
通过反射获取对应的成员变量
在反射技术中使用了Field类描述了成员变量。
*/
public class Demo4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InstantiationException, InvocationTargetException {
//获取到对应的Class对象
Class c = Class.forName("com.cn.reflect.Person");
//获取到所有的成员变量
Field[] fields = c.getDeclaredFields();
//fields = c.getFields();//获取所有的公共的成员变量,包括父类的
for(Field f : fields){
System.out.println(f);
}
System.out.println("=========================");
//获取一个对象
Constructor constructor = c.getConstructor(int.class, String.class);
Person p = (Person)constructor.newInstance(120, "木丁西");
//获取单个的成员变量
Field field = c.getDeclaredField("id");
//设置访问权限可以访问
field.setAccessible(true);
field.set(p, 155);//第一个参数:设置该数据的成员变量。第二个参数:属性值。
System.out.println(p);
}
}