反射

反射
类的加载概述和加载时机
类的加载概述
	当程序要使用某个类时,如果该类还未加载到内存中,
	则系统会通过加载,连接,初始化散步来实现对这个类进行初始化。
	加载:
		就是指将class文件读入内存,并为之创建一个class对象。
		任何类被使用时都会创建一个class对象。
	连接:
		验证:是否有正确的内部结构,并和其他类协调一致。
		准备:负责类的静态成员分配内存,并设置默认初始化值。
		解析:把类中的符号引用转换为直接引用。
	初始化:
		先初始化父类的静态成员和静态块,然后初始化子类的静态成员和静态块,然后再初始化父类,然后再初始化子类。
类的加载时机:
	创建类的实例 new Student()
	访问类的静态变量,或者为静态变量赋值  Math.PI   Math.class
	调用类的静态方法  Math.abs()
	使用反射方法来强制创建某个类或接口对应的java.lang.Class对象
	初始化某个类的子类
	直接使用java.exe命令来运行某个主类 
类加载器的概述和分类
类加载器的概述
	负责将.class文件加载到内在中,并为之生成对应的Class对象。
类加载器的分类
	Bootstrap ClassLoader 根类加载器
	Extension ClassLoader 扩展类加载器
	Sysetm ClassLoader 系统类加载器
类加载器的作用
	Bootstrap ClassLoader 根类加载器
		也被称为引导类加载器,负责Java核心类的加载
		比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
	Extension ClassLoader 扩展类加载器
		负责JRE的扩展目录中jar包的加载。
		在JDK中JRE的lib目录下ext目录
	Sysetm ClassLoader 系统类加载器  
		负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
反射概述以及获取class文件对象的三种方式
反射概述
	JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
	对于任意一个对象,都能够调用它的任意一个方法和属性;
	这种动态获取类的信息以及动态调用对象的方法的功能称为java语言的反射机制。
	要想剖析一个类,必须先要获取到该类的字节码文件对象。
	而剖析使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象
获取class文件对象的三种方式
	Object类的getClass()方法
	静态属性class
	Class类中静态方法forName()
    
类的成员
    成员变量		Field
    构造方法		Constructor
    成员方法		Method
     
案例:
	package Demo6;

    public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Student student = new Student();
            //Object类的getClass()方法
            Class<? extends Student> s1 = student.getClass();
            //静态属性class
            Class<Student>s2 = Student.class;
            //Class类中静态方法forName(参数是全限定名)
            全限定名:包名+类名 org.westos.demo.Student
            Class<?> s3 = Class.forName("Demo6.Student");
            System.out.println(s1==s2);
            System.out.println(s1==s3);
        }
    }
结果:
	true
    true

    Process finished with exit code 0

通过反射获取构造方法
获取所有构造方法
	public Constructor<?>[] getConstructors() 获取所有的构造方法不包含私有的
	public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法 包括私有的
获取单个构造方法
	public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个的构造方法 不包含私有的
	public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取单个的构造方法包含私有的
	
案例:
	Student类的代码:
	package Demo6;

    public class Student {

        public Student() {

        }
        private Student(String name) {
            System.out.println(name);
        }
        public Student(int age) {
            System.out.println(age);
        }


        public Student(String name, int age) {
            System.out.println(name + age);

        }

    }
	
	主方法代码:
	package Demo6;

    import java.lang.reflect.Constructor;

    public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
            Class<?> s = Class.forName("Demo6.Student");
            //获取除私有构造之外的其他构造方法
            Constructor<?>[] constructor = s.getConstructors();
            for (Constructor<?> constructor1 : constructor) {
                System.out.println(constructor1);
            }
            System.out.println("======================");
            //获取包括私有构造的所有构造方法对象
            Constructor<?>[] declaredConstructors = s.getDeclaredConstructors();
            for (Constructor<?> declaredConstructor : declaredConstructors) {
                System.out.println(declaredConstructor);
            }
            System.out.println("=======================");
            //获取空参构造
            Constructor<?> c1 = s.getConstructor();
            //获取参数是一个String类型的构造方法
            Constructor<?> c2 = s.getDeclaredConstructor(String.class);
            //获取两个参数的构造方法
            Constructor<?> c3 = s.getConstructor(String.class, int.class);
            System.out.println("空参构造方法: "+ c1);
            System.out.println("一个参数构造方法: "+ c2);
            System.out.println("两个参数构造方法: "+ c3);
        }
    }

结果:
	public Demo6.Student(java.lang.String,int)
    public Demo6.Student(int)
    public Demo6.Student()
    ======================
    public Demo6.Student(java.lang.String,int)
    public Demo6.Student(int)
    private Demo6.Student(java.lang.String)
    public Demo6.Student()
    =======================
    空参构造方法: public Demo6.Student()
    一个参数构造方法: private Demo6.Student(java.lang.String)
    两个参数构造方法: public Demo6.Student(java.lang.String,int)

    Process finished with exit code 0

通过反射获取构造方法并使用
    //Student类代码:
    	package Demo6;

        public class Student {
            String name;
            int age;

            public Student(int age) {
                this.age = age;
            }
            private Student(String name) {
                this.name=name;
            }
            public Student() {

            }
            public Student(String name, int age) {
                this.name=name;
                this.age = age;

            }

        }

    //主方法代码块:
    package Demo6;

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;

    public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class<?> s = Class.forName("Demo6.Student");
            //获取空参构造
            Constructor<?> c1 = s.getConstructor();
            //获取参数是一个String类型的构造方法
            Constructor<?> c2 = s.getDeclaredConstructor(String.class);
            //获取两个参数的构造方法
            Constructor<?> c3 = s.getConstructor(String.class, int.class);
            System.out.println("空参构造方法: "+ c1);
            System.out.println("一个参数构造方法: "+ c2);
            System.out.println("两个参数构造方法: "+ c3);
            System.out.println("=======================");
            //空参构造方法创建对象
            Object o = c1.newInstance();
            System.out.println(o);
            
            //取消私有的语法检查
            c2.setAccessible(true);
            //私有构造方法取消私有的语法检查后创建对象
            Object o1 = c2.newInstance("张三");
            System.out.println(o1);
            //有参构造方法创建对象
            Object o2 = c3.newInstance("李四", 23);
            System.out.println(o2);
        }
    }
结果:
	空参构造方法: public Demo6.Student()
    一个参数构造方法: private Demo6.Student(java.lang.String)
    两个参数构造方法: public Demo6.Student(java.lang.String,int)
    =======================
    Demo6.Student@1540e19d
    Demo6.Student@677327b6
    Demo6.Student@14ae5a5

    Process finished with exit code 0

通过反射获取成员变量并使用
获取所有成员变量
	public Field[] getFields() 获取所有的成员变量包含从父类继承过来的
	public Field[] getDeclaredFields() 获取所有的成员变量 包含私有的 也包含从父类继承过来的成员变量
获取单个成员变量
	public Field getField(String name)
	public Field getDeclaredField(String name)
案例:
	package Demo6;

    import java.lang.reflect.Field;

    public class Test2 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
            Class<?> aClass = Class.forName("Demo6.Student");
            //获取所有成员变量,包括从父类继承的。私有的成员变量获取不到
            Field[] fields1 = aClass.getFields();
            System.out.println(fields1.length);
            for (Field field : fields1) {
                System.out.println(field);
            }
            //获取所有的成员变量,包括私有的和继承父类的。
            System.out.println("======================");
            Field[] fields2 = aClass.getDeclaredFields();
            for (Field field : fields2) {
                System.out.println(field);
            }
        }
    }
结果:
	1
    public int Demo6.Student.age
    ======================
    private java.lang.String Demo6.Student.name
    public int Demo6.Student.age

    Process finished with exit code 0

通过反射获取成员方法并使用
获取所有构造方法
	public Constructor<?>[] getConstructors() 获取所有的构造方法不包含私有的
	public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法 包括私有的
获取单个构造方法
	public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个的构造方法 不包含私有的
	public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取单个的构造方法包含私有的
	
案例:
	创建对象类:
	package org.westos.demo7;

    public class Student {
        private Student() {
        }

        public void show() {
            System.out.println("show方法调用了");
        }

        protected void show2(String name) {
            System.out.println("show2方法调用了" + name);
        }

        void show3(String name, int age) {
            System.out.println("show3方法调用了" + name + "===" + age);
        }

        String show4(String name, int age) {
            System.out.println("show4方法调用了" + name + "===" + age);
            return "返回值";
        }

        private void test(String name, int age) {
            System.out.println("私有的方法调用了" + name + "==" + age);
        }
    }

	测试类:
		package Demo7;

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    public class MyTest1 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class<?> aClass = Class.forName("Demo7.Student");
            //getMethods()获取包括父类的成员方法对象数组,只能获取public修饰的成员方法对象,
            Method[] methods = aClass.getMethods();
            //遍历成员方法对象。
            for (Method method : methods) {
                System.out.println(method);
            }
            System.out.println("=============================");
            //getDeclaredMethods() 获取本类的所有成员方法,包括Private修饰的私有成员方法对象
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println(declaredMethod);
            }
            System.out.println("===============================");
            //getMethod("方法名",形参.class) 获取单个成员方法,只能获取public修饰的成员方法对象
            Method show = aClass.getMethod("show");
            System.out.println(show);
            System.out.println("================================");
            //getDeclaredMethod("方法名", 形参.class) 获取单个成员方法
            Method show3 = aClass.getDeclaredMethod("show3", String.class, int.class);
            System.out.println(show3);
            System.out.println("=================================");

            Method show4 = aClass.getDeclaredMethod("show4", String.class, int.class);
            System.out.println(show4);

            System.out.println("=================================");
            Method test = aClass.getDeclaredMethod("test", String.class, int.class);
            System.out.println(test);

            System.out.println("=================================");
            Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
            declaredConstructor.setAccessible(true);
            Object o = declaredConstructor.newInstance();
            //invoke(对象,形参)调用方法
            show.invoke(o);

            System.out.println("======================");
            show3.invoke(o,"张三",23);

            System.out.println("==========================");
            Object o1 = show4.invoke(o, "李四", 24);
            System.out.println(o1);

            System.out.println("===========================");
            test.setAccessible(true);
            test.invoke(o,"王五",25);
        }
    }

结果:
	public void Demo7.Student.show()
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    =============================
    private void Demo7.Student.test(java.lang.String,int)
    public void Demo7.Student.show()
    void Demo7.Student.show3(java.lang.String,int)
    java.lang.String Demo7.Student.show4(java.lang.String,int)
    protected void Demo7.Student.show2(java.lang.String)
    ===============================
    public void Demo7.Student.show()
    ================================
    void Demo7.Student.show3(java.lang.String,int)
    =================================
    java.lang.String Demo7.Student.show4(java.lang.String,int)
    =================================
    private void Demo7.Student.test(java.lang.String,int)
    =================================
    show方法调用了
    ======================
    show3方法调用了张三===23
    ==========================
    show4方法调用了李四===24
    返回值
    ===========================
    私有的方法调用了王五==25

    Process finished with exit code 0

通过反射运行配置文件内容

​ 当基于Cat开发时,只需要将配置文件里面的className更改为Demo8.Cat。基于Dog开发时,同样是将类名写入配置文件即可。提高了代码的容错。

案例:

配置文件内容


	Cat类:
		package Demo8;

        public class Cat {
            public void eat(){
                System.out.println("猫吃鱼");
            }
        }
        
    Dog类:
     	
        package Demo8;

        public class Dog {
            public void eat() {
                System.out.println("狗吃骨头");
            }
        }

	测试类:
	package Demo8;

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Properties;

    public class Test {
        public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            //加载文件peizhi.properties
            Properties properties = new Properties();
            properties.load(new FileInputStream("peizhi.properties"));
            //getProperty(key) 获取键对应的值,然后获取对应的字节码对象
            Class<?> aClass = Class.forName(properties.getProperty("className"));
            //获取键指的值的类的空参构造方法。
            Constructor<?> constructor = aClass.getDeclaredConstructor();
            //去除私有检测,防止类私有修饰
            constructor.setAccessible(true);
            //创建对象
            Object o = constructor.newInstance();
            //获取键指的值得方法名。
            Method methodName = aClass.getDeclaredMethod(properties.getProperty("methodName"));
            //调用方法。
            methodName.invoke(o);
        }
    }
    
结果:
   	狗吃骨头

	Process finished with exit code 0

通过反射越过泛型检查
需求:
	我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢
案例:	
	package Demo7;

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;

    public class Test1 {
        public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            ArrayList<Integer> list = new ArrayList<>();
            list.add(100);
            list.add(200);
            list.add(300);
            Class<? extends ArrayList> aClass = list.getClass();
            Method add = aClass.getDeclaredMethod("add", Object.class);
            add.setAccessible(true);
            add.invoke(list,"哈哈哈");
            System.out.println(list);
        }
    }

结果:
	[100, 200, 300, 哈哈哈]

	Process finished with exit code 0

通过反射写一个通用的设置某个对象的某个属性为指定的值
	public void setProperty(Object obj, String propertyName, Object value){},此方法可将obj对象中名为propertyName的属性的值设置为value。

案例:
	对象类:
		package Demo9;

        public class Student {
            private String name;
            private int age;
        }
        
    方法类: 
    	
		package Demo9;

        import java.lang.reflect.Field;

        public class Utils {
            public static void setProperty(Object obj, String propertyName, Object value) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
                Class<?> aClass = obj.getClass();
                Field field = aClass.getDeclaredField(propertyName);
                field.setAccessible(true);
                field.set(obj,value);
            }

            public static Object getProperty(Object obj, String propertyName) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
                Class<?> aClass = obj.getClass();
                Field field = aClass.getDeclaredField(propertyName);
                field.setAccessible(true);
                Object o = field.get(obj);
                return o;
            }
        }
        
	测试类:
		package Demo9;

        public class Test1 {
            public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, ClassNotFoundException {
                Student student = new Student();
                Utils.setProperty(student,"name","张三");
                Object name = Utils.getProperty(student, "name");
                System.out.println(name);
            }
        }

	结果:
		张三

		Process finished with exit code 0

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值