一篇文章带你了解java反射

news/2024/5/19 2:26:52 标签: java, 反射

目录

反射

Class类中的相关方法

反射的使用示例 

获取Class对象 

反射构造方法 

 反射属性

反射私有方法 

反射的优点和缺点 


本篇博客所有的代码已上传至gitee中:反射代码 

反射

反射的定义

Java反射机制是在运行状态中,对于任意一个类,都能够知道知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,也可以修改部分类型的信息,这种动态获取信息以及动态调用对象的方法的功能称为Java的反射机制.

反射的应用

①当遇到某个类的成员变量、成员方法或属性是私有属性的时候,我们可以利用反射来获取所需的私有成员变量和方法;

反射最重要的用途是开发各种通用框架.

反射相关的类

类名作用
Class类代表类的实体,在运行的Java程序中表示类和接口
Filed类代表类的成员变量/成员属性
Method类代表类的方法
Constructor类代表类的构造方法

Class类中的相关方法

Class类是反射机制的起源,代表类的实体,在运行的Java应用程序中表示类和接口

常用获得类的相关方法

方法用途
getClassLoader()获得类的加载器
getDeclaredClasses()返回一个数组,数组中包含该类中所有的类和接口类的对象(包括私有的)
forName(String className)根据类名返回类的对象
newInstance()创建类的实例
getName()获得类的完整路径名字

常用获得类中属性的相关方法(以下方法返回值为Filed相关)

方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象

获得类中构造器相关的方法(以下方法返回值为Constructor相关)

获得类中方法相关的方法(以下返回值为Method相关)

方法用途
getMethod(String name, Class...<?> parameterTypes)
获得该类某个公有方法
getMethods()
获得该类所有的公有方法
getDeclaredMethod(String name, Class...<?> parameterTypes)
获得该类的某个方法
getDeclaredMethods()
获得该类所有方法

反射的使用示例 

首先创建一个Student类,其中包含私有属性、公有属性、私有方法、公有方法,利用反射来获取其中的私有变量和方法.

public class Student {
    //私有属性name
    private String name = "bit";
    //共有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student() {
        System.out.println("Student()");
    }
    //带参数的私有构造方法
    private Student(String name, int age) {
        this.age = age;
        this.name = name;
        System.out.println("Student(String,int)");
    }
    //不带参数的私有方法
    private void eat() {
        System.out.println("I am eat");
    }
    public void sleep() {
        System.out.println("I am sleeping");
    }
    //带参数的私有方法
    private void function(String str) {
        System.out.println(str);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

获取Class对象 

方法1:通过getClass来获取Class对象;

方法2:通过.class来获取

方法3:通过Class类的静态方法forName()来获取

具体获取方式如下述代码所示:

    public static void main(String[] args) throws ClassNotFoundException {
        //1、通过getClass获取Class对象
        Student s1 = new Student();
        Class<?> c1 = s1.getClass();
        //2、利用.class获取
        Class<?> c2 = Student.class;
        //3、通过Class类的静态方法forName()来获取
        Class<?> c3 = Class.forName("reflectdemo.Student");
        System.out.println(c1.equals(c2));
        System.out.println(c2.equals(c3));
        System.out.println(c1.equals(c3));
        //Class对象只有一个
    }

注:无论利用什么方法来获取Class对象,Class对象都只有一个.通过下述输出可以说明,分别利用三种不同的方法获得Class对象c1、c2、c3,最终通过对比,c1与c2与c3都相等,因此说明Class对象只有一个.

反射构造方法 

 在反射私有构造方法之前需要获取对象、然后获取与该参数类型匹配的构造方法,获取之后对其授权,授权后就可以使用该私有的构造方法.

注:在整个反射过程中都需要进行捕获异常,原因是不确定是否有该类、该构造方法,因此需要对其进行异常处理

    //反射私有的构造方法 屏蔽内容为获得公有的构造方法
    public static void reflectPrivateConstruct() {
        try {
            //获取对象
            Class<?> c1 = Class.forName("reflectdemo.Student");
            //获得该类中与参数类型匹配的构造方法
            Constructor<?> constructor = 
                    c1.getDeclaredConstructor(String.class,int.class);

            /*如果方法是 private修饰的,当你用反射去访问的时候
              setAccessible(true)之后才能访问,相当于授权
            */
            constructor.setAccessible(true);
            Student student = (Student)constructor.newInstance("lyz",19);
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

测试结果 

 

 

 反射属性

反射属性之前需要获取对象、然后获取相关的属性,获取之后对其授权,授权后就可以对其进行修改了.整个过程中需要对异常进行处理,原因与反射构造方法一样.

    //反射所有的属性,以私有属性为例
    public static void reflectPrivateFiled() {
        try {
            Class<?> c1 = Class.forName("reflectdemo.Student");
            Student student = (Student)c1.newInstance();
            Field field = c1.getDeclaredField("name");
            field.setAccessible(true);
            field.set(student,"张三");
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

测试结果 

 

 

反射私有方法 

反射方法的步骤与上述类似,本篇博客重在讲述反射的使用

    //反射私有方法
    public static void reflectPrivateMethod() {
        try {
            Class<?> c1 = Class.forName("reflectdemo.Student");
            Student student = (Student)c1.newInstance();

            //方法的名称   方法的参数
            Method method = c1.getDeclaredMethod("function", String.class);
            method.setAccessible(true);
            method.invoke(student,"我是function的参数");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

测试结果

 

反射的优点和缺点 

优点

1.对于任意一个类,都能够获得这个类中的方法和属性;对于任意一个对象,都能够调用它的任意一个方法;

2.增加程序的灵活性和可扩展性;

3.反射在各种框架中的使用十分广泛.

缺点

1.使用反射会可能导致效率变低;

2.反射绕过了源代码的技术,可能会带来维护问题.

 

 

 

 


http://www.niftyadmin.cn/n/735928.html

相关文章

Python学习宣誓

我给自己写个宣誓&#xff0c;毕竟没有具体目标很难成功&#xff0c;12月2日我就开始学习python了&#xff0c;每周六上一天课&#xff0c;虽然看起来困难很多但我一定要坚持下来&#xff0c;尽量不请假&#xff0c;一定要跟上学习进度&#xff0c;不留级。 以下就是我的具体目…

Java~枚举的使用

目录 枚举的定义 枚举的使用 values()的使用 ordinal()的使用 valueOf() 的使用 compareTo()的使用 枚举的优缺点 枚举的定义 枚举是JDK1.5以后引入的。主要用途&#xff1a;将一组常量组织起来&#xff0c;在引入枚举之前表示一组常量通常是使用定义常量的方式&…

php中上传图片,原生代码

一、实现图片上传方法一 html的写法&#xff1a; <form action"handle.php" name"form" method"post" enctype"multipart/form-data"><input type"file" name"file" /><input type"submit&qu…

优化后的快速排序(详解)

目录 快速排序 三数取中值分割法获得枢纽元 快速排序的主例程 直接插入排序代码 快速排序完整代码 快速排序 快速排序是实践中的一种快速的排序算法&#xff0c;它的平均运行时间是O(N log N)&#xff0c;该算法之所以特别快&#xff0c;是因为它有非常精炼和高度优化的…

Java实现二叉查找树及其相关操作

目录 二叉查找树 初始化 二叉查找树的查找 二叉查找树的插入 二叉查找树的删除 二叉查找树的中序遍历 findMax and findMin 二叉查找树完整代码 测试用例 完整代码已上传至gitee中&#xff1a;gitee代码仓库 二叉查找树 二叉查找树&#xff0c;又称二叉排序树…

如何编写更好的SQL查询:终极指南-第二部分

基于集合和程序的方法进行查询 > > > > >

你了解直接进行访问的数据结构吗?一篇文章带你了解简单的哈希表的实现

目录 哈希表 哈希表的实现 初始化 计算负载因子 哈希表的扩容 哈希表的插入 查找元素 完整代码 测试用例 哈希表实现代码已上传至gitee中&#xff1a;点击查看代码 哈希表 哈希表(也称散列表)&#xff1a;是根据关键码值而直接进行访问的数据结构。也就是说&…

伟大架构师的秘密

By Don Awalt and Rick McUmber RDA Corporation 企业架构师正受到其所面临的大量复杂性的挑战。开发一个能够自动处理企业任务的独立的部门应用程序是一回事。而设计并组成一个支持上万 IT 使用者的满是应用程序、服务器和数据库&#xff08;全都支持多种企业活动&#xff09;…