反射

来源:互联网 发布:手机显示yy网络不给力 编辑:程序博客网 时间:2024/05/01 19:08

 一、概念


在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性,这种动态调用获取的信息以及动态调用对象的方法的功能称为反射机制。通俗的锁就是在运行状态中,获取类或对象的方法和属性。


二、获取Class对象


1.通过Object类中的getObject()方法

2.通过类名.class获取字节码文件对象

3.通过Class类中的方法forName(将类名作为字符串传递给Class类中的静态方法forName即可)


package Demo01;public class Test01 {public static void main(String[] args) throws ClassNotFoundException {//1.对象获取Person p=new Person();//2.调用Person类的父类的方法getClassClass c=p.getClass();System.out.println(c);//2.类名获取//每个类型包括基本的和引用类型都会赋予这个类型一个静态的属性,属性名字是ClassClass c1=Person.class;System.out.println(c1);//3.Class类的静态方法获取forName(字符串类名) 包名.类名Class c2=Class.forName("Demo01.Person");System.out.println(c2);}}


三、通过反射获取构造方法


1)public Constructor<T>getConstructor(Class<?>... parameterTypes):获取public修饰, 指定参数类型所对应的构造方法

2)public Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes):获取指定参数类型所对应的构造方法(包含私有的)

3)public Constructor<?>[] getConstructors():获取所有的public 修饰的构造方法

4)public Constructor<?>[]getDeclaredConstructors():获取所有的构造方法(包含私有的)


1.获取构造方法


public class ReflectDemo1 {public static void main(String[] args) throws Exception{Class c=Class.forName("Demo01.Person");System.out.println("-----------------");Constructor con=c.getConstructor();System.out.println(con);}}


2.获取构造方法,创建对象


public class ReflectDemo2 {public static void main(String[] args) throws Exception {Class c=Class.forName("Demo01.Person");Constructor con=c.getConstructor(String.class,int.class);Object obj=con.newInstance("张三",20);System.out.println(obj);}}

3.获取私有构造方法,创建对象


public class ReflectDemo2 {public static void main(String[] args) throws Exception {Class c=Class.forName("Demo01.Person");//getDeclaredConstructor:获取所有构造方法Constructor con=c.getDeclaredConstructor(String.class,int.class);//进行暴力反射con.setAccessible(true);//通过构造方法类中的功能,创建对象Object obj=con.newInstance("张三",20);System.out.println(obj);}}

四、通过反射获取成员变量


1.获取成员变量


public class FieldDemo2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {//获取Class对象Class c = Class.forName("Demo02.Person");//获取成员变量Field[] fields =  c.getDeclaredFields();for (Field field : fields) {System.out.println(field);}//获得单个成员变量Field ageField = c.getField("age");System.out.println(ageField);}}


2.获取成员变量并赋值


public class FieldDemo2 {public static void main(String[] args) throws Exception {//1,获取Class对象Class c = Class.forName("Demo01.Person");//2,获取构造方法Constructor con = c.getConstructor(String.class);//3,通过构造方法,创建对象Object obj = con.newInstance("小明");//4,获取指定的员变量Field nameField = c.getField("name");Field ageField = c.getDeclaredField("age");//通过方法,给指定对象的指定成员变量赋值或者获取值System.out.println("name = "+ nameField.get(obj));System.out.println("age = "+ ageField.get(obj));//赋值ageField.set(obj, 23);nameField.set(obj, "凯利");System.out.println("name = "+ nameField.get(obj));System.out.println("age = "+ ageField.get(obj));}}

五、通过反射获取成员方法


1.创建对象并调用方法


public class Test {public static void main(String[] args) throws Exception {//1 获取Class对象Class c = Class.forName("Demo01.Person");//2获取构造方法Constructor con = c.getConstructor(String.class, int.class);//3通过构造方法,创建对象Object obj = con.newInstance("小明", 23);//4获取指定的方法method4,返回值是String类型的Method m4 = c.getMethod("method4", String.class);//5执行找到的方法并将返回值赋给resultObject result = m4.invoke(obj, "itcast");System.out.println("result = " + result);}}

2.创建对象并调用私有方法


public class Test1 {public static void main(String[] args) throws Exception {//1 获取Class对象Class c = Class.forName("Demo01.Person");//2获取构造方法Constructor con = c.getConstructor(String.class, int.class);//3通过构造方法,创建对象Object obj = con.newInstance("小明", 23);//4获取指定的方法method4,返回值是String类型的Method m5 = c.getDeclaredMethod("method5", String.class);//5开启暴力访问m5.setAccessible(true);//6执行找到的方法并将返回值赋给resultObject result=m5.invoke(obj, "itcast");System.out.println("result = " + result);}}

六、泛型擦除


泛型擦除:程序编译后产生的.class文件中是没有泛型约束的,所以我们可以通过反射向已经定义类型的泛型中添加任意类型的


import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;public class ReflectTest {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {ArrayList<Integer> list = new ArrayList<Integer>();//添加元素到集合list.add(11);list.add(22);list.add(33);System.out.println(list);//通过反射技术,实现添加"任意类型"的元素Class c = Class.forName("java.util.ArrayList");//找到add()方法Method addMethod = c.getMethod("add", Object.class);// 执行add()方法addMethod.invoke(list, "哈哈");// list.add("哈哈");System.out.println(list);}}


小结

如果想要解剖一个类,必须先要获取到此类的字节码文件对象,所以要获取每一个字节码文件对象的Class类型的对象。反射就是获得已经封装好的类中的方法和属性。


2 0
原创粉丝点击