🌈Java✨学习笔记✨ (十三)⏩ 反射常用方法整理

551 阅读5分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

⭐8月更文挑战第21天⭐,和小伙伴们一起复习巩固Java😁

Code皮皮虾 一个沙雕而又有趣的憨憨少年,和大多数小伙伴们一样喜欢听歌、游戏,当然除此之外还有写作的兴趣,emm...,日子还很长,让我们一起加油努力叭🌈

欢迎各位小伙伴们关注我的公众号:JavaCodes,名称虽带Java但涉及范围可不止Java领域噢😁,会长期分享博文或者福利,期待您的关注❤

😉毛遂自荐

毛遂自荐,给大家推荐一下自己的专栏😁,欢迎小伙伴们收藏关注😊

小白学Java

MybatisPlus专栏

App爬虫专栏

PC端爬虫专栏

大厂面试题专栏

1、Java反射机制概述

反射机制有什么用?

通过java语言中的反射机制可以操作字节码文件。优点类似于黑客。(可以读和修改字节码文件)通过反射机制可以操作代码片段。(class文件)

反射机制的相关类在哪个包下?

java.lang.reflect.*

反射机制相关的重要的类有哪些?

java.lang.Class:代表整个字节码,代表一个类型,代表整个类。 java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。 java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法。 java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)


2、获取Class的三种方式

2.1、第一种

Class c = Class.forName("完整类名带包名");

try {
  	Class c1 = Class.forName("java.lang.String");   //c1代表String类型
    Class c2 = Class.forName("java.util.Date");  //c2代表Date类型
    Class c3 = Class.forName("java.lang.Integer");  //c3代表Integer类型
    Class c4 = Class.forName("java.lang.System");  //c4代表System类型
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Class.forName()

  1. 静态方法
  2. 方法的参数是一个字符串
  3. 字符串需要的是一个完整类名
  4. 完整类名必须带有包名。java.lang包也不能省略

2.2、第二种

Class c = 对象.getClass();

在这里插入图片描述

public static void main(String[] args) {
        Class c1 = null;
        Class c2 = null;
        Class c3 = null;
        try {
            c1 = Class.forName("java.lang.String");
            c2 = Class.forName("java.util.Date");
            c3 = Class.forName("java.lang.Integer");
            Class c4 = Class.forName("java.lang.System");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        String str = "abcd";  //字符串对象
        Class aClass = str.getClass();    //aClass代表String.class的字节码文件,aClass代表Stirng类型·
        System.out.println(aClass == c1);  //true(==判断的是对象的内存地址)

        Date date = new Date();
        Class cdate = date.getClass();
        System.out.println(cdate == c2);  //true(cdate和c2两个变量中保存的内存地址都是一样的,都指向方法区中的字节码文件)
}

在这里插入图片描述


2.3、第三种

Class c = 任何类型.class;

public static void main(String[] args) {
        Class c1 = null;
        Class c2 = null;
        Class c3 = null;
        try {
            c1 = Class.forName("java.lang.String");
            c2 = Class.forName("java.util.Date");
            c3 = Class.forName("java.lang.Integer");
            Class c4 = Class.forName("java.lang.System");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        //Java语言中任何一种类型,包括基本数据类型,它都有.class属性
        Class stringClass = String.class;  //stringClass代表Stirng类型
        Class dateClass = Date.class; //dateClass代表Date类型

        System.out.println(stringClass == c1);
        System.out.println(dateClass == c2);
    }

在这里插入图片描述


3、通过反射实例化对象

public class Main {

    public static void main(String[] args) {
        try {
        	//通过反射机制,获取Class,通过Class来实例化对象
            Class aClass = Class.forName("com.dong.Person");
            Object o = aClass.newInstance();
            System.out.println(o);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }

}

//Person类
class Person {

}

在这里插入图片描述

成功创建对象

newInstance()这个方法会调用Person这个类的无参构造方法,完成对象的创建。

class Person {
    public Person() {
        System.out.println("运行无参构造方法");
    }
}

在这里插入图片描述

如果定义了有参构造方法但没有无参构造方法就会报错

class Person {
    private String name;

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

在这里插入图片描述

所以,一般最好带上无参构造方法


4、通过反射机制访问对象属性

Student类

public class Student {
    private String name;
    protected int age;
    boolean sex;
    public int no;
    public static final double MATH_PI = 3.1415926;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class student = Class.forName("com.dong.Student");

        Object o = student.newInstance();  //o就是Student对象(底层调用无参数构造方法)

        //获取no属性(根据属性的名称来获取Field)
        Field no = student.getDeclaredField("no");

        no.set(o,123);  //给obj对象的no属性赋值123

        System.out.println(no.get(o));
}

在这里插入图片描述

获取私有属性

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class student = Class.forName("com.dong.Student");

        Object o = student.newInstance();  //o就是Student对象(底层调用无参数构造方法)

        //获取私有的name
        Field name = student.getDeclaredField("name");

        //给name属性赋值
        name.set(o,"皮皮虾");

        System.out.println(name.get(o));
}

在这里插入图片描述

访问报错

解决办法:打破封装 在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class student = Class.forName("com.dong.Student");

        Object o = student.newInstance();  //o就是Student对象(底层调用无参数构造方法)

        //获取私有的name
        Field name = student.getDeclaredField("name");

        //打破封装
        name.setAccessible(true);

        //给name属性赋值
        name.set(o,"皮皮虾");

        System.out.println(name.get(o));
}

在这里插入图片描述

setAccessible(true)这样设置后,在外部也可以访问private
反射机制缺点:打破封装可能会给不法分子留下机会!!!


5、通过反射机制调用方法(重点)

User类

public class User {

    int no;
    int age;

    /**
     * 登陆方法
     */
    public boolean login(String name,String password) {
        if ("admin".equals(name) && "123".equals(password)) {
            return true;
        }
        return false;
    }

    /**
     * 退出
     */
    public void logout() {
        System.out.println("系统已经安全退出");
    }
}

测试

public class Main {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class aClass = Class.forName("com.dong.User");

        //创建对象
        Object obj = aClass.newInstance();

        //获取Method
        Method login = aClass.getDeclaredMethod("login", String.class, String.class);
        Object admin = login.invoke(obj, "admin", "123");
        System.out.println(admin);

        Method logout = aClass.getDeclaredMethod("logout");
        logout.invoke(obj);

    }

}

在这里插入图片描述

getDeclaredMethod():参数1:指明获取的方法的名称,参数2:指明获取的方法的形参列表
invoke():参数1:方法的调用者,参数2:给方法形参赋值的实参

反射机制,让代码很具有通用性,可变化的内容都是写到配置文件中,将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,但是java代码不需要任何改动。这就是发射机制能力。


6、通过反射机制调用指定构造器

在这里插入图片描述

public class Main {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class aClass = Class.forName("com.dong.User");


        Constructor declaredConstructor = aClass.getDeclaredConstructor(int.class, int.class);

        Object o = declaredConstructor.newInstance(1, 2);
        System.out.println(o);
    }

}

在这里插入图片描述

getDeclaredConstructor():参数:指明构造器的参数列表


❤最后

我是 Code皮皮虾,一个热爱分享知识的 皮皮虾爱好者,未来的日子里会不断更新出对大家有益的博文,期待大家的关注!!!

创作不易,如果这篇博文对各位有帮助,希望各位小伙伴可以==一键三连哦!==,感谢支持,我们下次再见~~~


一键三连.png