java-反射-暴力反射

反射

1.类加载器

在这里插入图片描述

2.获取class文件对象的方式(重点)


/*
    获取class文件对象的方式(重点):
        1.使用Object类中的方法getClass
            Class<?> getClass() 返回此 Object 的运行时类。
        2.java中会为每种数据类型都赋予一个class属性,这个class属性返回就是class文件对象
            基本数据类型:int.class,double.class,char.class,boolean.class...
            引用数据类型:int[].class,ArrayList<String>.class,String.class,Person.class...
        3.可以使用Class类中的静态方法forName获取class文件对象
            static Class<?> forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。
            参数:
                String className:全类名(包名+类名),可以确定类的唯一性
                com.itheima.demo01Reflect.Person
    注意:
        class文件对象是由类加载器创建的,我们无论使用那种方式获取的class文件对象都是唯一的
 */
public class Demo01Reflect {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.使用Object类中的方法getClass,Person类默认继承了Object类,所以可以使用Object类中的方法
        Person p = new Person();
        Class c1 = p.getClass();
        System.out.println(c1);//class com.itheima.demo01Reflect.Person

        //2.java中会为每种数据类型都赋予一个class属性,这个class属性返回就是class文件对象
        System.out.println(int.class);
        System.out.println(double.class);
        System.out.println(String.class);
        Class c2 = Person.class;
        System.out.println(c2);//class com.itheima.demo01Reflect.Person

        //3.可以使用Class类中的静态方法forName获取class文件对象
        Class c3 = Class.forName("com.zl.demo01Reflect.Person");
        System.out.println(c3);

        //class文件对象是由类加载器创建的,我们无论使用那种方式获取的class文件对象都是唯一的
        System.out.println(c1==c2);//true 引用数据类型==比较的是对象的地址值
        System.out.println(c1==c3);//true
        System.out.println(c2==c3);//true
    }
}

3.Class类常用方法


/*
    Class类常用方法
        String getSimpleName(); 获得类名字符串:类名
        String getName();  获得类全名:包名+类名
    使用Class类中的forName方法,获取class文件对象,会执行类中的静态代码块(数据库:JDBC)
 */
public class Demo02ClassMethod {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取Person类的class文件对象
        Class clazz = Class.forName("com.zl.demo01Reflect.Person");

        String simpleName = clazz.getSimpleName();
        System.out.println(simpleName);//Person

        String name = clazz.getName();
        System.out.println(name);//com.zl.demo01Reflect.Person
    }
}

4.反射概述

在这里插入图片描述

5.反射的准备工作


public class Person {
    /*static {
        System.out.println("静态代码块!");
    }*/
    private String name;
    private int age;
    public String sex;

    public Person() {
        System.out.println("Person类的空参数构造方法!");
    }

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        System.out.println("Person类的满参数构造方法!");
    }

    private Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person类的私有构造方法!");
    }

    private void method(){
        System.out.println("Person类的私有方法!");
    }

    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;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

6.使用反射技术获取类中的构造方法,并使用获取到的构造方法实例化对象

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

/*
    使用反射技术获取类中的构造方法,并使用获取到的构造方法实例化对象
    实现步骤:
        1.获取类的class文件对象
        2.使用class文件对象中的方法getConstructor|getConstructors获取类中的(公共)构造方法
        3.使用构造方法Constructor类中的方法newInstance实例化对象
 */
public class Demo03ReflectConstructor {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取类的class文件对象
        Class clazz = Class.forName("com.zl.demo01Reflect.Person");
        //2.使用class文件对象中的方法getConstructor|getConstructors获取类中的(公共)构造方法
        /*
            获取多个构造方法:
                Constructor<?>[] getConstructors()  获取类的所有公共构造方法
                Constructor<?>[] getDeclaredConstructors()  获取类声明的所有构造方法(包括公共的,受保护的,默认的,私有的)。
         */
        Constructor[] cons = clazz.getConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }
        System.out.println("----------------------------");
        Constructor[] declaredCons = clazz.getDeclaredConstructors();
        for (Constructor con : declaredCons) {
            System.out.println(con);
        }
        System.out.println("----------------------------");
        /*
            获取指定的构造方法:
                Constructor<T> getConstructor(Class<?>... parameterTypes)  获取指定公共构造方法。
                Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  获取指定构造方法(包括公共的,受保护的,默认的,私有的)。
                参数:
                    ...:可变参数,调用方法是可变参数的方法,参数可以传递任意个
                    Class<?>... parameterTypes:传递构造方法参数的class文件对象
                        (String.class,int.class,double.class...)
           注意:
                类中没有指定的构造方法,会抛出NoSuchMethodException:没有这样的方法异常
         */
        //public Person()
        Constructor con1 = clazz.getConstructor();
        System.out.println(con1);//public com.zl.demo01Reflect.Person()

        //public Person(String name, int age, String sex)
        Constructor con2 = clazz.getConstructor(String.class, int.class, String.class);
        System.out.println(con2);//public com.zl.demo01Reflect.Person(java.lang.String,int,java.lang.String)

        //private Person(String name, int age)
        Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(con3);//private com.zl.demo01Reflect.Person(java.lang.String,int)

        //3.使用构造方法Constructor类中的方法newInstance实例化对象
        /*
            java.lang.reflect.Constructor<T>类
                T newInstance(Object... initargs)  实例化对象的方法(创建对象的方法)
                参数:
                    Object... initargs:创建对象传递的实际参数 new Person("张三",18,"男")
                返回值:
                    T:返回的就是创建好的对象,类型是Object
                        Object obj = new Person();
         */
        //public Person()
        Object obj1 = con1.newInstance();//此方法相当于new Person();
        System.out.println(obj1);//com.zl.demo01Reflect.Person@4554617c  Person{name='null', age=0, sex='null'}

        //public Person(String name, int age, String sex)
        Object obj2 = con2.newInstance("张三", 18, "男");//此方法相当于new Person("张三", 18, "男");
        System.out.println(obj2);//Person{name='张三', age=18, sex='男'}

        /*
            private Person(String name, int age)
            私有构造方法没有权限使用,要使用会抛出IllegalAccessException:非法访问异常
            解决:
                可以使用Constructor父类AccessibleObject中的方法解决
                java.lang.reflect.AccessibleObject类
                    void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。
                        值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
                        值为 false 则指示反射的对象应该实施 Java 语言访问检查。
           注意:
                暴力反射不推荐,破坏了类的封装性(私有,不让外界使用)
         */
        con3.setAccessible(true);//取消java语言访问检查==>暴力反射
        Object obj3 = con3.newInstance("隔壁老王", 30);
        System.out.println(obj3);//Person{name='隔壁老王', age=30, sex='null'}
    }
}

7.使用反射技术获取构造方法并实例化对象的简化方式(重点)

import java.lang.reflect.Constructor;

/*
    使用反射技术获取构造方法并实例化对象的简化方式(重点)
    java.lang.Class类
        T newInstance() 根空参数构造方法实例化对象返回
    实现步骤:
        1.获取类的class文件对象
        2.使用class文件对象中的方法newInstance实例对象
    注意
        1.类中必须有空参数构造方法
        2.空参数构造方法修饰符是public,不能是private
 */
public class Demo04ReflectConstructor {
    public static void main(String[] args) throws Exception {
        //1.获取类的class文件对象
        Class clazz = Class.forName("com.zl.demo01Reflect.Person");
        //2.使用class文件对象中的方法newInstance实例对象
        //Constructor con = clazz.getConstructor();
        //Object obj = con.newInstance();
        //System.out.println(obj);
        Object obj = clazz.newInstance();
        System.out.println(obj);//Person{name='null', age=0, sex='null'}
        Person p = (Person)obj;
        p.setName("翠花");
        System.out.println(p.getName());
    }
}

8.使用反射技术获取类中的成员方法,并运行获取到成员方法(重点)


import java.lang.reflect.Method;

/*
    使用反射技术获取类中的成员方法,并运行获取到成员方法
    实现步骤:
        1.获取类的class文件对象
        2.使用class文件对象中的方法getMethod|getMethods获取类中(公共的)成员方法
        3.使用成员方法Method类中的方法invoke,运行获取到的成员方法
 */
public class Demo05ReflectMethod {
    public static void main(String[] args) throws Exception {
        //1.获取类的class文件对象
        Class clazz = Person.class;
        //2.使用class文件对象中的方法getMethod|getMethods获取类中(公共的)成员方法
        /*
            获取多个成员方法:
                Method[] getMethods()  获取本类和父类继承的,接口实现的所有的公共构造方法
                Method[] getDeclaredMethods()  获取本类声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
            Method类中的方法getName,获取方法名称
                String getName() 以 String 形式返回此 Method 对象表示的方法名称。
         */
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        System.out.println("--------------------------------");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method);
        }
        System.out.println("--------------------------------");
        /*
            获取指定的成员方法:
                Method getMethod(String name, Class<?>... parameterTypes)  获取指定公共成员方法。
                Method getDeclaredMethod(String name, Class<?>... parameterTypes)  获取指定已声明(公共、保护、默认(包)访问和私有)方法。
                参数:
                    String name:方法的名称
                    Class<?>... parameterTypes:方法参数的class文件对象
           注意:
            获取指定的成员方法不存在,会抛出NoSuchMethodException:没有这样的方法异常
         */
        //public String getName()
        Method getNameMethod = clazz.getMethod("getName");
        System.out.println(getNameMethod);//public java.lang.String com.zl.demo01Reflect.Person.getName()

        //public void setName(String name)
        Method setNameMethod = clazz.getMethod("setName", String.class);
        System.out.println(setNameMethod);

        //private void method()
        Method privateMethod = clazz.getDeclaredMethod("method");
        System.out.println(privateMethod);//private void com.zl.demo01Reflect.Person.method()

        //3.使用成员方法Method类中的方法invoke,运行获取到的成员方法
        /*
            java.lang.reflect.Method类 extends AccessibleObject类
                Object invoke(Object obj, Object... args)  运行指定的成员方法
                参数:
                    Object obj:方法的运行需要对象的支持,运行哪个类的方法,就需要传递哪个类的对象
                        运行Person类的方法,需要传递Person对象(快速方式获取)
                    Object... args:运行方法传递的实际参数
                返回值:
                    Object:方法的返回值
                        方法的返回值类型不是ovid,返回的就是方法的返回值
                        方法的返回值类型是void,返回null
         */
        Object obj = clazz.newInstance();//new Person()
        //public String getName()
        Object v1 = getNameMethod.invoke(obj);//就相当于调用getName方法获取name的值
        System.out.println("v1:"+v1);//v1:null name的默认值

        //public void setName(String name)
        Object v2 = setNameMethod.invoke(obj, "柳岩");//就相当于调用setName方法给name赋值
        System.out.println("v2:"+v2);//v2:null 方法没有返回值

        v1 = getNameMethod.invoke(obj);//就相当于调用getName方法获取name的值
        System.out.println("v1:"+v1);//v1:柳岩

        /*
            private void method() 私有方法没有权限执行,会抛出非法访问异常:IllegalAccessException
            使用暴力反射,取消java语言的访问权限检查
         */
        privateMethod.setAccessible(true);
        privateMethod.invoke(obj);//Person类的私有方法!
    }
}

9.使用反射技术获取类中的成员变量(字段),并给成员变量赋值或者获取成员变量的值

import java.lang.reflect.Field;

/*
    使用反射技术获取类中的成员变量(字段),并给成员变量赋值或者获取成员变量的值(了解)
    实现步骤:
        1.获取类的class文件对象
        2.使用class文件对象中的方法getField|getFields获取类中(公共的)成员变量
        3.使用成员变量Field类中的方法set给成员变量赋值,get获取成员变量的值
 */
public class Demo06ReflectField {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        //1.获取类的class文件对象
        Class clazz = Class.forName("com.zl.demo01Reflect.Person");
        //2.使用class文件对象中的方法getField|getFields获取类中(公共的)成员变量
        /*
            获取多个成员变量:
                Field[] getFields()  获取所有可访问公共字段
                Field[] getDeclaredFields()  获取所声明的所有字段(包含公共的,受保护的,默认的,私有的)
         */
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("----------------------------------");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println("----------------------------------");
        /*
            获取指定的的成员变量
                Field getField(String name)  获取指定公共成员字段。
                Field getDeclaredField(String name)  获取指定已声明字段(包含公共的,受保护的,默认的,私有的)
                参数:
                    String name:成员变量名称
           注意:
            没有指定的成员变量,会抛出NoSuchFieldException:没有这样的字段异常
         */
        //public String sex;
        Field sexField = clazz.getField("sex");
        System.out.println(sexField);//public java.lang.String com.zl.demo01Reflect.Person.sex

        //private String name;
        Field nameField = clazz.getDeclaredField("name");
        System.out.println(nameField);//private java.lang.String com.zl.demo01Reflect.Person.name

        //3.使用成员变量Field类中的方法set给成员变量赋值,get获取成员变量的值
        /*
            java.lang.reflect.Field类 extends AccessibleObject类
                Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。
                    参数:
                        Object obj:需要对象的支持,使用哪个类的字段,就传递哪个类的对象
                    返回值:
                        Object:成员变量的值
                void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
                    参数:
                        Object obj:需要对象的支持,使用哪个类的字段,就传递哪个类的对象
                        Object value:给字段赋实际使用值
         */
        Object obj = clazz.newInstance();//使用空参数构造方法创建对象
        //public String sex;
        Object v1 = sexField.get(obj);
        System.out.println("v1:"+v1);//v1:v1 sex的默认值

        sexField.set(obj,"女");

        v1 = sexField.get(obj);
        System.out.println("v1:"+v1);//v1:女

        /*
            private String name;
            私有的字段没有权限使用,需要使用暴力反射,取消java语言的权限检查
         */
        nameField.setAccessible(true);
        nameField.set(obj,"胡歌");

        Object v2 = nameField.get(obj);
        System.out.println("v2:"+v2);//v2:胡歌
    }
}

10.使用反射技术获取实现类所实现的所有接口


/*
    使用反射技术获取实现类所实现的所有接口
    Class类中的方法:
        Class<?>[] getInterfaces() 确定此对象所表示的类或接口实现的接口。
        ClassLoader getClassLoader() 返回该类的类加载器。
 */
public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取接口实现类AandBImpl的class文件对象
        Class clazz = Class.forName("com.zl.demo02Reflect.AandBImpl");
        //使用反射技术获取实现类所实现的所有接口
        Class[] interfaces = clazz.getInterfaces();
        for (Class in : interfaces) {
            /*
                interface com.zl.demo02Reflect.A
                interface com.zl.demo02Reflect.B
             */
            System.out.println(in);
        }

        //根据class文件对象,获取到类加载器
        ClassLoader classLoader = clazz.getClassLoader();
        System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值