Java反射详解

一,反射
–1,概述
反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。private的只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。
Java 反射机制在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。此外,在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值。

--2,作用
	--拿到.class文件里的数据进行解析.
	--获取文件里的所有数据(公开的.私有的.构造.属性.方法)
	--并把所有数据封装在Class对象身上.
--3,获取Class对象
	Class.forName(“类的全路径”);
	类名.class
	对象.getClass();
--4,常用方法

二,反射的应用
–1,创建Student类
package cn.tedu.reflect;
//配合 测试 反射
public class Student {
//构造方法-generate-constructor-多选ctrl/单选-ok
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}

	    String  name ;
	    int age ;
	    double score ;

	    public void study(){
	        System.out.println("study()");
	    }
	    public void coding(){
	        System.out.println("coding()");
	    }

	}

--2,测试
	package cn.tedu.reflect;

	import java.lang.reflect.Constructor;
	import java.lang.reflect.Field;
	import java.lang.reflect.Method;
	import java.util.Arrays;

	//测试 反射 获取Class对象
	public class Test2_ReflectStudent {
	    public static void main(String[] args) throws Exception {
	//        method();//获取Class对象
	//        method2();//获取构造方法
	//        method3();//获取成员方法
	//        method4();//获取成员变量
	        method5();//通过反射的技术创建对象
	    }
	    //创建对象
	    public static void method5() throws Exception {
	        //1,获取Class对象
	        Class<Student> clazz = Student.class ;
	        //2,调用实例化方法 --也要触发构造方法,而且触发的是无参构造
	        //newInstance()必须提供无参构造,否则[抛出异常:java.lang.InstantiationException: cn.tedu.reflect.Student
	        Student s = clazz.newInstance();
	        System.out.println("s = " + s);
	        //重写toString()前:s = cn.tedu.reflect.Student@1b6d3586
	       //重写toString()后:s = Student{name='null', age=0, score=0.0}

	        //怎么触发含参构造--触发public Student(String name)
	        //getConstructor(m);--m参数要 匹配构造方法里 参数的类型 的Class对象
	        Constructor<Student> c = clazz.getConstructor(String.class);//指定
	        //newInstance(x)--x是你创建对象时具体的参数
	        Student s2 = c.newInstance("jack");
	        System.out.println("s2 = " + s2);

	        //TODO 触发public Student(String name, int age)
	        Constructor<Student> c2 = clazz.getConstructor(String.class,int.class);
	        Student s3 = c2.newInstance("xiongda",20) ;
	        System.out.println("s3 = " + s3);
	    }
	    //获取成员变量
	    public static void method4() {
	        //1,获取Class对象
	        Class clazz = Student.class ;
	        //2,获取所有成员变量 -- 只能获取公开的变量
	        Field[] fs = clazz.getFields();
	        //3,遍历数组,得到每个变量f
	        for (Field f : fs) {
	            //4,获取变量名称
	            System.out.println(f.getName());
	            //5,获取变量类型
	            System.out.println(f.getType().getName() );
	        }
	    }
	    //获取成员方法
	    public static void method3() {
	        //1,获取Class对象
	        Class<Student> clazz = Student.class ;
	        //2,获取所有成员方法们 -- 包括自己的和父类的 的公开的方法们
	        Method[] ms = clazz.getMethods() ;
	        //3,遍历数组,得到每个方法m
	        for (Method m : ms) {
	            //4,获取方法名称
	            System.out.println(m.getName());
	            //5,获取方法的参数的类型
	            Class<?>[] cs = m.getParameterTypes();
	            System.out.println(Arrays.toString(cs));
	        }
	    }
	    //获取构造方法
	    public static void method2() {
	        //1,获取Class对象 --封装了.class文件里的所有数据
	        Class clazz = Student.class ;
	        //2,获取所有构造方法们  , 并存入数组 -- 只能反射 公开的 资源
	        Constructor[] cs = clazz.getConstructors();
	        //3,获取每个构造方法c
	        for (Constructor c : cs) {
	            //4,获取构造方法的名字
	            System.out.println( c.getName() );
	            //5,获取构造方法的参数类型 们
	            Class[] css = c.getParameterTypes();
	            System.out.println( Arrays.toString(css) );
	        }
	    }
	    //获取Class对象
	    public static void method() throws ClassNotFoundException {
	        Class c = Class.forName("cn.tedu.reflect.Student");//参数是类的全路径
	        Class c2 = Student.class ;
	//        Class c3 = new Student().getClass() ;//使用了父类Object提供的getClass()
	//        System.out.println("c3 = " + c3);
	//        System.out.println("c2 = " + c2);
	//        System.out.println("c = " + c);
	    }
	}

三,暴力反射
–作用 : 不仅能获取到类的public资源,也可以获取到类里的private资源
–API :
–普通反射
–getConstructor()
–getConstructors()
–getMethod()
–getMethods()
–getField()
–getFields()
–暴力反射
–getDeclaredConstructor()
–getDeclaredConstructors()
–getDeclaredMethod()
–getDeclaredMethods()
–getDeclaredField()
–getDeclaredFields()
–1,创建Person类
package cn.tedu.reflect;

	//配置暴力反射
	public class Person {

	    public String name;
	    public int age;
	    private double score;

	    public void eat() {
	        System.out.println("eat()");
	    }
	    public void sleep(int a, String b) {
	        System.out.println("sleep()");
	    }
	    private void game(String x) {
	        System.out.println("game()");
	    }
	}

--2,测试
	package cn.tedu.reflect;
	import java.lang.reflect.Field;
	import java.lang.reflect.Method;
	import java.util.Arrays;
	//测试 暴力反射:
	//条件 : 使用getDeclaredXxx()  + 开启私有可见的权限
	public class Test3_BaoliReflect {
	    public static void main(String[] args) throws Exception {
	//        method();//暴力反射成员方法们
	        method2();//暴力反射成员变量
	    }
	    //暴力反射成员变量们
	    public static void method2() throws Exception {
	        //1,获取Class对象
	        Class clazz = Person.class ;
	        //2,暴力反射
	        Field[] fs = clazz.getDeclaredFields();
	        //3,遍历数组,得到每个变量f
	        for (Field f : fs) {
	            //4,获取变量名称
	            System.out.println(f.getName());
	            //5,获取变量类型
	            System.out.println(f.getType().getName() );
	        }

	        //获取指定的变量
	        Field f = clazz.getDeclaredField("score") ;
	        //开启 访问权限,否则访问私有抛出异常:IllegalAccessException:
	        f.setAccessible(true);

	        Object obj = clazz.newInstance() ;
	        //设置值--set(1,2)--1是指对象名称--2是要设置的具体值
	        f.set(obj,99.9);
	        //获取值--get(1)--1是指对象名称
	        System.out.println( f.get(obj) );
	    }
	    //暴力反射成员方法们
	    public static void method() throws Exception {
	        //1,获取Class对象
	        Class<Person> clazz = Person.class ;
	        //2,暴力反射 -- getDeclaredMethods()
	        Method[] ms = clazz.getDeclaredMethods() ;
	        //3,遍历数组,得到每个方法m
	        for (Method m : ms) {
	            //4,获取方法名称
	            System.out.println(m.getName());
	            //5,获取方法的参数的类型
	            Class<?>[] cs = m.getParameterTypes();
	            System.out.println(Arrays.toString(cs));
	        }
	        //暴力反射 某个方法
	        //getDeclaredMethod(1,2)--获取指定的方法
	        //--1是指方法名--2是指方法需要的参数类型的Class对象
	        Method m = clazz.getDeclaredMethod("game",String.class) ;
	        //暴力反射:除了用对API,另外还需要开启访问权限
	        m.setAccessible(true);

	        Object obj = clazz.newInstance() ;
	        //执行方法--invoke(1,2)--1是指对象名称--2是方法需要传入的参数
	        m.invoke(obj,"tony") ;
	    }
	}

在这里插入图片描述
补充:反射注解方法
–改造Person类
package cn.tedu.reflect;

	import org.junit.Test;

	//配置暴力反射
	public class Person {
	    @Test
	    public void show(){
	        System.out.println(123);
	    }

	    public String name;
	    public int age;
	    private double score;

	    public void eat() {
	        System.out.println("eat()");
	    }
	    public void sleep(int a, String b) {
	        System.out.println("sleep()");
	    }
	    private void game(String x) {
	        System.out.println("game()");
	    }
	}

--改造测试类
	package cn.tedu.reflect;
	import org.junit.Test;

	import java.lang.reflect.Field;
	import java.lang.reflect.Method;
	import java.util.Arrays;
	//测试 暴力反射:
	//条件 : 使用getDeclaredXxx()  + 开启私有可见的权限
	public class Test3_BaoliReflect {
	    public static void main(String[] args) throws Exception {
	//        method();//暴力反射成员方法们
	//        method2();//暴力反射成员变量
	        method3();//反射注解方法
	    }
	    //反射注解方法
	    public static void method3() throws Exception {
	        //1,获取Class对象
	        Class clazz = Person.class ;
	        //2,获取show()
	        Method m = clazz.getDeclaredMethod("show",null);
	        //3,获取Test注解的标志
	        // getDeclaredAnnotation(1)--参数1是注解类型 的class对象
	        Test test = m.getDeclaredAnnotation(Test.class) ;

	        Object obj = clazz.newInstance() ;
	        //4,判断有注解的话,就运行
	        if(test != null){
	            m.invoke(obj) ;//运行方法
	        }

	    }
	    //暴力反射成员变量们
	    public static void method2() throws Exception {
	        //1,获取Class对象
	        Class clazz = Person.class ;
	        //2,暴力反射
	        Field[] fs = clazz.getDeclaredFields();
	        //3,遍历数组,得到每个变量f
	        for (Field f : fs) {
	            //4,获取变量名称
	            System.out.println(f.getName());
	            //5,获取变量类型
	            System.out.println(f.getType().getName() );
	        }

	        //获取指定的变量
	        Field f = clazz.getDeclaredField("score") ;
	        //开启 访问权限,否则访问私有抛出异常:IllegalAccessException:
	        f.setAccessible(true);

	        Object obj = clazz.newInstance() ;
	        //设置值--set(1,2)--1是指对象名称--2是要设置的具体值
	        f.set(obj,99.9);
	        //获取值--get(1)--1是指对象名称
	        System.out.println( f.get(obj) );
	    }
	    //暴力反射成员方法们
	    public static void method() throws Exception {
	        //1,获取Class对象
	        Class<Person> clazz = Person.class ;
	        //2,暴力反射 -- getDeclaredMethods()
	        Method[] ms = clazz.getDeclaredMethods() ;
	        //3,遍历数组,得到每个方法m
	        for (Method m : ms) {
	            //4,获取方法名称
	            System.out.println(m.getName());
	            //5,获取方法的参数的类型
	            Class<?>[] cs = m.getParameterTypes();
	            System.out.println(Arrays.toString(cs));
	        }
	        //暴力反射 某个方法
	        //getDeclaredMethod(1,2)--获取指定的方法
	        //--1是指方法名--2是指方法需要的参数类型的Class对象
	        Method m = clazz.getDeclaredMethod("game",String.class) ;
	        //暴力反射:除了用对API,另外还需要开启访问权限
	        m.setAccessible(true);

	        Object obj = clazz.newInstance() ;
	        //执行方法--invoke(1,2)--1是指对象名称--2是方法需要传入的参数
	        m.invoke(obj,"tony") ;
	    }
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值