反射的概念和基本使用(一)

博客 分享
0 234
张三
张三 2022-04-05 23:57:37
悬赏:0 积分 收藏

反射的概念 和基本使用(一)

1 反射

什么是反射

java反射 是指在运行状态中 对于任意一个类 我们都可以知到这个类的所有方法和属性 也可以调用其所有的方法和属性 这种动态获取的方式 我们称为 反射

什么是class对象

我们通过使用反射 就是通过Class类来实现的 Class 类的实例表示正在运行的 Java 应用程序中的类和接口。

也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)

反射的使用

获取class对象的三种方式

基本类
/** * * @author : look-word * @date : 2022-04-05 20:49 **/public class Student {    private String username;    private String gender;    public  String getInfo() {        this.setUsername("张三");        this.setGender("男");        return this.username+"="+this.gender;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getGender() {        return gender;    }    public void setGender(String gender) {        this.gender = gender;    }}
测试代码如下
/** * @author : look-word * @date : 2022-04-05 20:54 **/public class Test {    public static void main(String[] args) {        /*            1 创建对象 获取其class对象         */        Student student = new Student();        Class<? extends Student> aClass = student.getClass();        System.out.println(aClass.getSimpleName());        /*            2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性         */        Class<? extends Student> bClass=Student.class;        System.out.println(aClass == bClass?"两者是同一对象":"两者不是同一对象");        /*            3 通过Class类的forName方法获取         */        try {            //  Class.forName(类的相对路径)            Class<?> cClass = Class.forName("bean.Student");            System.out.println(bClass == cClass?"两者是同一对象":"两者不是同一对象");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }}
结果如下

证明

在运行期间 一个类只有一个class对象的产生

常用的是第三次 清晰 明了 因为 在一个项目中 可能会产生 相同名字的类

解决疑惑 为什么要是用 第三种

第一种对象都有了还要反射干什么。

第二种需要导入类的包,依赖太强,不导包就抛编译错误。

第三种,一个字符串可以传入也可写在配置文件中等多种方法。

获取Class类中的所有构造方法

基本类
public class Student {    //---------------构造方法-------------------    //(默认的构造方法)    Student(String str){        System.out.println("(默认)的构造方法 s = " + str);    }    //无参构造方法    public Student(){        System.out.println("调用了公有、无参构造方法执行了。。。");    }    //有一个参数的构造方法    public Student(char name){        System.out.println("姓名:" + name);    }    //有多个参数的构造方法    public Student(String name ,int age){        System.out.println("姓名:"+name+" 年龄:"+ age);//这的执行效率有问题,以后解决。    }    //受保护的构造方法    protected Student(boolean n){        System.out.println("受保护的构造方法 n = " + n);    }    //私有构造方法    private Student(int age){        System.out.println("私有的构造方法   年龄:"+ age);    }}
测试代码
/** * 测试构造方法 * @author : look-word * @date : 2022-04-05 21:18 **/public class TestConstructor {/** * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员; * * 1.获取构造方法: * 		1).批量的方法: * 			public Constructor[] getConstructors():所有"公有的"构造方法            public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) * 		2).获取单个的方法,并调用: * 			public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法: * 			public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有; * * 			调用构造方法: * 			Constructor-->newInstance(Object... initargs)*/    public static void main(String[] args) throws Exception {        Class<?> student = Class.forName("bean.Student");        /*            1 获取所有共有的构造方法         */        System.out.println("\n1 获取所有共有的构造方法");        Constructor<?>[] constructors = student.getConstructors();        for (Constructor<?> constructor : constructors) {            System.out.println(constructor);        }        /*            2 获取共有的无参构造方法 可以写 null 或者 不填         */        System.out.println("\n2 获取共有的无参构造方法 可以写 null 或者 不填");        Constructor<?> constructor2 = student.getConstructor();        constructor2.newInstance();        /*            3 获取 给定参数共有的构造方法 public bean.Student(java.lang.String,int)         */        System.out.println("\n 3 获取 给定参数共有的构造方法 public bean.Student(java.lang.String,int)");        Constructor<?> constructor3 = student.getConstructor(String.class, int.class);        constructor3.newInstance("张三",19);        /*            4 获取 私有给定参数的构造方法 私有 不给定参数 不传参数即可         */        Constructor<?> constructor4 = student.getDeclaredConstructor(int.class);        /*            获取私有的属性 或者构造方法是 需要 设置无障碍 俗称 暴力访问            不设置 会出异常 java.lang.IllegalAccessException         */        constructor4.setAccessible(true);        constructor4.newInstance(19);    }}
执行结果

注意

获取私有属性的时候 一定要设置无障碍

setAccessible(true);

不设置 会出异常 java.lang.IllegalAccessException

newInstance(Object... initargs) 创建一个新实例
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

每次是用 newInstance创建的对象 都是不同的对象 代表不同的实例

操作成员变量

基本类
 public class Student {	public Student(){			}	//**********字段*************//	public String name;	protected int age;	char sex;	private String phoneNum;		@Override	public String toString() {		return "Student [name=" + name + ", age=" + age + ", sex=" + sex				+ ", phoneNum=" + phoneNum + "]";	}}
测试代码
/** * @author : look-word * @date : 2022-04-05 21:55 **/public class TestField {/* * 获取成员变量并调用: * * 1.批量的 * 		1).Field[] getFields():获取所有的"公有字段" * 		2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有; * 2.获取单个的: * 		1).public Field getField(String fieldName):获取某个"公有的"字段; * 		2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的) * * 	 设置字段的值: * 		Field --> public void set(Object obj,Object value): * 					参数说明: * 					1.obj:要设置的字段所在的对象; * 					2.value:要为字段设置的值;*/    public static void main(String[] args) throws Exception{        Class<?> aClass = Class.forName("bean.Student");        Student student = new Student();        /*            获取所有的共有字段         */        System.out.println("-------------------获取所有的共有字段--------------------");        Field[] fields = aClass.getFields();        for (Field field : fields) {            /*                filed => public java.lang.String bean.Student.username                filed => 成员变量             */            /*               我理解为 给某个对象的 成员变量 赋值               当前的filed 为 username 因为这里只能获取为 共有属性的成员变量             * field.set(student,"zhangsan");             */            field.set(student,"zhangsan");            System.out.println(student);            /*                field.get(student);                获取某student中的 field 的 内容             */            Object o = field.get(student);            System.out.println(o);            /*             *  打印filed的内容 => public java.lang.String bean.Student.username             */            System.out.println(field);        }        System.out.println("-------------------给私有字段赋值--------------------");        Field phone = aClass.getDeclaredField("phone");        phone.setAccessible(true);// 设置无障碍         phone.set(student,"110");// 赋值给student对象        System.out.println("-------------------获取私有字段--------------------");        Field phone1 = aClass.getDeclaredField("phone");        phone1.setAccessible(true);// 设置无障碍        System.out.println(phone1.get(student));//取出student对象中的phone属性的值    }}
注意

在操作私有属性的时候 不管是获取还是设置值 都需要设置无障碍

setAccessible(true);// 设置无障碍

posted @ 2022-04-05 22:41 look-word 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员