大数据 -- java基础15 反射

1、反射:

    通过一个Class文件对象去使用该文件对象中的成员变量,构造方法,成员方法。

   我们之前去使用成员的时候,先有一个java文件,然后在实例化的时候,直接new就完事了
   Person p = new Person()
   p.eat();
   总归来说,底层还是依赖一个class文件
   也就是需要先得到一个Class文件对象。

   class类:
       成员变量:  Field
       构造方法:  Constructor
       成员方法:  Method

   获取一个类对应的Class文件对象:
       方式1: 通过Object类中的getClass()方法,返回此Object的运行时类。

       方式2: 在不new对象的前提下,获取该类的class文件对象,使用类的静态属性class来获取。

       方式3: public static Class<?> forName(String className)  返回与给定字符串名称的类或接口相关联的类对象。  -- 多数
public class Person {

    //成员变量
    private String name;
    int age;
    protected String address;
    public String id;

    //构造方法
    Person(){}

    public Person(String id){
        this.id = id;
    }

    private Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    protected Person(String name,int age,String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成员方法
    public void fun1(){
        System.out.println("这是公共的方法fun1");
    }
    private void fun2(String s){
        System.out.println("这是私有的方法fun2"+s);
    }
    protected void fun3(){
        System.out.println("这是被保护的方法fun3");
    }
    void fun4(){
        System.out.println("这是默认修饰符的方法fun4");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}



public class ReflexDemo {
    public static void main(String[] args) {

        //方式1: 通过Object类中的getClass()方法,返回此Object的运行时类
        Person p = new Person();
        Class<? extends Person> c1 = p.getClass();

        Person p2 = new Person();
        Class<? extends Person> c2 = p2.getClass();
        System.out.println(c1 == c2);       // true

        //方式2: 在不new对象的前提下,获取该类的class文件对象,使用类的静态属性class来获取
        Class<Person> c3 = Person.class;
        System.out.println(c1 == c3);       // true
        System.out.println(c2 == c3);       // true

        //方式3: public static Class<?> forName(String className)  返回与给定字符串名称的类或接口相关联的类对象。
        try {
            Class<?> c4 = Class.forName("com.wy.day27.fanshe.Person");
            System.out.println(c1 == c4);       // true
            System.out.println(c2 == c4);       // true
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2、通过反射获取Class文件对象中的构造方法并使用:

    1、获取所有的公共构造方法:
        public Constructor<?>[] getConstructors()

    2、获取所有的构造方法,包括私有,被保护的,默认的,公共的:
        public Constructor<?>[] getDeclaredConstructors()


    3、获取单个公共的构造方法:
        public Constructor<T> getConstructor(类<?>... parameterTypes)

    4、获取单个的构造方法,根据参数可以是私有,被保护的,默认的,公共的:
        public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)


    5、通过构造方法去创建对象:
        public T newInstance(Object... initargs)

        private修饰的构造方法不能随意赋值,否则报错:IllegalAccessException
        解决方法:
        暴力访问
        setAccessible(true)   值为true,表示反射的对象在使用的时候取消Java语言的访问检查
public class Person {

    //成员变量
    private String name;
    int age;
    protected String address;
    public String id;

    //构造方法
    Person(){}

    public Person(String id){
        this.id = id;
    }

    private Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    protected Person(String name,int age,String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成员方法
    public void fun1(){
        System.out.println("这是公共的方法fun1");
    }
    private void fun2(String s){
        System.out.println("这是私有的方法fun2"+s);
    }
    protected void fun3(){
        System.out.println("这是被保护的方法fun3");
    }
    void fun4(){
        System.out.println("这是默认修饰符的方法fun4");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}



public class ReflexDemo1 {
    public static void main(String[] args) throws Exception {

        //1、获取Class文件对象
        //public static Class<?> forName(String className)  返回与给定字符串名称的类或接口相关联的类对象。
        Class<?> c1 = Class.forName("com.wy.day27.fanshe.Person");


        //2、获取所有的公共构造方法
        //public Constructor<?>[] getConstructors()
        Constructor<?>[] con1 = c1.getConstructors();
        for (Constructor c : con1) {
            System.out.println(c);
        }
        System.out.println("======================================");


        //3、获取所有的构造方法,包括私有,被保护的,默认的,公共的
        //public Constructor<?>[] getDeclaredConstructors()
        Constructor<?>[] cons2 = c1.getDeclaredConstructors();
        for (Constructor c : cons2) {
            System.out.println(c);
        }
        System.out.println("======================================");


        //4、获取单个公共的构造方法
        //public Constructor<T> getConstructor(类<?>... parameterTypes)
//        Constructor<?> con3 = c1.getConstructor();     //相当于获取无参构造方法,而无参构造方法是默认类型的,报错:NoSuchMethodException
//        System.out.println(con3);

        Constructor<?> con3 = c1.getConstructor(String.class);        // 根据参数确定是public修饰的构造方法
        System.out.println(con3);
        System.out.println("======================================");


        //5、获取单个的构造方法,根据参数可以是私有,被保护的,默认的,公共的
        //public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
        Constructor<?> con4 = c1.getDeclaredConstructor(String.class, int.class);     // 根据参数确定是private修饰的构造方法
        System.out.println(con4);
        System.out.println("======================================");


        //6、通过构造方法去创建对象
        //public T newInstance(Object... initargs)
        Person p = (Person) con3.newInstance("1001");    // 给公共的构造方法赋值
        System.out.println(p);

//        Object o = con4.newInstance("你好",23);       // private修饰的构造方法不能随意赋值,否则报错:IllegalAccessException
//        System.out.println(o);


        //暴力访问
        //setAccessible(true)   值为true,表示反射的对象在使用的时候取消Java语言的访问检查
        con4.setAccessible(true);

        Person p1 = (Person) con4.newInstance("昭阳", 18);
        System.out.println(p1);
    }
}

3、通过反射获取成员变量并使用:

    1、获取所有的公共成员变量:
        public Field[] getFields()

    2、获取当前类中所有成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段:
        public Field[] getDeclaredFields()

    3、获取单个的公共成员变量:
        public Field[] getField()   根据参数确定成员变量

    4、将指定对象上的成员变量赋上一个新的值:
        void set(Object obj, Object value)

    5、获取当前类中单个的成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段:
        public Field[] getDeclaredField()


       给private修饰的成员变量赋值,需要暴力访问。
           setAccessible(true)

       public、protected、默认的不需要。
public class Person1 {

    //成员变量
    private String name;
    int age;
    protected String address;
    public String id;

    //构造方法
    public Person1(){}         // 相较于Person ,将无参构造方法加上了public

    public Person1(String id){
        this.id = id;
    }

    private Person1(String name,int age){
        this.name = name;
        this.age = age;
    }

    protected Person1(String name,int age,String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成员方法
    public void fun1(){
        System.out.println("这是公共的方法fun1");
    }
    private void fun2(){
        System.out.println("这是私有的方法fun2");
    }
    protected void fun3(){
        System.out.println("这是被保护的方法fun3");
    }
    void fun4(){
        System.out.println("这是默认修饰符的方法fun4");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}



public class ReflexDemo2 {
    public static void main(String[] args) throws Exception {

        //1、获取字节码文件对象
        Class<?> c1 = Class.forName("com.wy.day27.fanshe.Person1");


        //2、获取所有的公共成员变量
        //public Field[] getFields()
        Field[] f = c1.getFields();
        for (Field field : f) {
            System.out.println(field);
        }
        System.out.println("==========================================");


        //3、获取当前类中所有成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段
        //public Field[] getDeclaredFields()
        Field[] f1 = c1.getDeclaredFields();
        for (Field field : f1) {
            System.out.println(field);
        }
        System.out.println("=========================================");


        //获取公共的无参构造方法
        Constructor<?> con = c1.getConstructor();

        //利用无参构造方法创建对象
        Object o = con.newInstance();
        System.out.println(o);         // Person{name='null', age=0, address='null', id='null'}


        //4、获取单个的公共成员变量
        //public Field[] getField()
        Field id = c1.getField("id");     // 根据"id"获取到id成员变量

//        Field name = c1.getField("name");    // 根据"name"获取到name成员变量
//        System.out.println(name);         // 但是name是private修饰的,报错:NoSuchFieldException


        //5、将指定对象上的成员变量赋上一个新的值
        //void set(Object obj, Object value)
        id.set(o, "1002");     // 将无参构造方法创建的对象上的成员变量赋上新的值
        System.out.println(o);         // Person{name='null', age=0, address='null', id='1002'}
        System.out.println("=========================================");


        //6、获取当前类中单个的成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段
        //public Field[] getDeclaredField()
        Field name1 = c1.getDeclaredField("name");      // 根据"name"获取到name成员变量
        System.out.println(name1);

        //因为name是private修饰的,要想赋值,就需要暴力访问
        name1.setAccessible(true);

        //给成员变量赋值
        name1.set(o, "昭阳");
        System.out.println(o);            // Person{name='昭阳', age=0, address='null', id='1002'}
        System.out.println("=========================================");


        //获取被protected修饰的成员变量,不需要暴力访问
        Field address = c1.getDeclaredField("address");
        address.set(o, "安徽合肥");
        System.out.println(o);           // Person{name='昭阳', age=0, address='安徽合肥', id='1002'}
        System.out.println("==========================================");


        //获取默认的修饰符修饰的成员变量并赋值,不需要暴力访问
        Field age = c1.getDeclaredField("age");
        age.set(o, 20);
        System.out.println(o);          // Person{name='昭阳', age=20, address='安徽合肥', id='1002'}
    }
}

4、通过反射获取成员方法并使用:

    1、获取本类和父类中所有的公共方法
        public 方法[] getMethods()

    2、获取本类的所有的方法,包括私有,不能获取父类的
        public 方法[] getDeclaredMethods()

    3、获取单个公共的方法并调用
        public 方法 getMethod()

    4、通过对象调用方法
        public Object invoke(Object obj, Object... args)   第一个参数指的是调用方法的对象,第二个参数指的是实际需要传入的数据(实参)

    5、获取单个的成员方法,包括公共,受保护,默认和私有字段
        public 方法 getDeclaredMethod()


        调用private修饰的成员方法,需要暴力访问。
           setAccessible(true)

        public、protected、默认的不需要。
public class Person2 {

    //成员变量
    private String name;
    int age;
    protected String address;
    public String id;

    //构造方法
    public Person2(){}

    public Person2(String id){
        this.id = id;
    }

    private Person2(String name, int age){
        this.name = name;
        this.age = age;
    }

    protected Person2(String name, int age, String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成员方法
    public void fun1(){
        System.out.println("这是公共的方法fun1");
    }
    private void fun2(String s){
        System.out.println("这是私有的方法fun2"+s);
    }        // 相较于Person1 ,将private方法加上了参数String
    protected void fun3(){
        System.out.println("这是被保护的方法fun3");
    }
    void fun4(){
        System.out.println("这是默认修饰符的方法fun4");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}



public class ReflexDemo3 {
    public static void main(String[] args) throws Exception {

        //1、获取字节码文件对象
        Class<?> c1 = Class.forName("com.wy.day27.fanshe.Person2");


        //2、获取本类和父类中所有的公共方法
        //public 方法[] getMethods()
        Method[] methods = c1.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        System.out.println("=========================================");


        //3、获取本类的所有的方法,包括私有,不能获取父类的
        //public 方法[] getDeclaredMethods()
        Method[] methods2 = c1.getDeclaredMethods();
        for (Method m : methods2) {
            System.out.println(m);
        }
        System.out.println("=========================================");


        //4、获取单个公共的方法并调用
        //public 方法 getMethod()
        Method fun1 = c1.getMethod("fun1");        // 通过"fun1"调用了fun1()方法

//        Method fun2 = c1.getMethod("fun2", String.class);      // 调用fun2()方法
//        System.out.println(fun2);           // 但是fun2()是private修饰的,报错:NoSuchFieldException

        //获取无参构造方法
        Constructor<?> cons = c1.getConstructor();
        Object o = cons.newInstance();


        //5、通过对象调用方法
        //public Object invoke(Object obj, Object... args)   第一个参数指的是调用方法的对象,第二个参数指的是实际需要传入的数据(实参)
        fun1.invoke(o);          // 调用了fun1()方法,输出 : 这是公共的方法fun1
        System.out.println("========================================");


        //6、获取单个的成员方法,包括公共,受保护,默认和私有字段
        //public 方法 getDeclaredMethod()
        Method fun2 = c1.getDeclaredMethod("fun2", String.class);    // 调用fun2()方法

        //因为fun2()是private修饰的,要想调用,就需要暴力访问
        fun2.setAccessible(true); //只有私有的方法调用需要暴力访问
        fun2.invoke(o,"数加科技");      // 调用了fun2()方法,输出 : 这是私有的方法fun2数加科技
        System.out.println("=========================================");


        //调用被protected修饰的成员方法,不需要暴力访问
        Method fun3 = c1.getDeclaredMethod("fun3");     // 调用fun3()方法
        fun3.invoke(o);        // 这是被保护的方法fun3
        System.out.println("=========================================");


        //调用默认修饰的成员方法,不需要暴力访问
        Method fun4 = c1.getDeclaredMethod("fun4");     // 调用fun4()方法
        fun4.invoke(o);        // 这是默认修饰符的方法fun4
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值