【Java反射】触手可及
我是【envoke】,一个想在编程路上越走越远的人。
热爱技术、热爱开源、热爱编程。
- Stay hungry, stay foolish.(求知若饥,虚心若愚)
- Go big or go home.(要么牛逼,要么滚蛋)
如果您也对Java感兴趣,或者我的文章能帮助到您,给个点赞或关注把! 加入【Go Big】一起探讨、一起吹逼、一起前行。群号:243108249
相关阅读:
目录结构
反射
反射可谓是设计框架的灵魂
什么是反射 ?
动态获取对象信息(类的名称、类的属性、类的方法
),并且根据对象信息进行对象创建、字符赋值、调用对象方法
的功能称之为反射机制。
反射的原理
在程序运行的时候获取到想要创造实例的类的信息,使用Class类来创建一个对应的实例。避免了使用new关键字,达到在程序运行时动态创建实例的效果。
反射的优点:
可以通过反射机制实现帮助程序实现扩展功能。比如说:实现spring ioc、pring mvc等。
反射的缺点:
- 违背了面向对象的原则,即使是private修饰的也能进行使用
- 性能上存在问题,java反射究竟消耗多少效率
应用场景:
- JDBC驱动加载(Class.forName())
- SpringIOC容器实现(< bean id=“user” class=“类的全路径”> )
- 自定义注解
- mybatis逆向工程、JPA、MybatisPlus等
获取反射的类模板
想要使用反射,我们先要获取类的模板Class,下面提供了三种获取类模板信息的方法
我们这里有一个贫血对象
public class Person {
private String name;
private Long id;
public Person(String name, Long id) {
System.out.println(">>>有参构造执行<<<");
this.name = name;
this.id = id;
}
public Person() {
System.out.println(">>>无参构造执行<<<");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private void showName(String name){
System.out.println("反射执行方法, name: " + name);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", id=" + id +
'}';
}
}
通过类名的方式获取:
Class personClass = Person.class;
通过类的全路径获取:使用最多
Class<?> personClass = Class.forName("com.live.collection.Person");
通过对象的方式获取:基本上不用,我都有对象了,为何还要用反射呢
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
反射创建对象
上一步我们已经拿到了类模板信息,接下来,我们就开始使用类模板信息创建对象了
创建对象主要有两种方式: 类模板直接创建,走的是无参构造:
Class<?> personClass = Class.forName("com.live.collection.Person");
Person person = (Person) personClass.newInstance();
System.out.println(person);
执行结果
>>>无参构造执行<<<
Person{name='null', id=null}
通过构造方法创建:
无参构造创建:
Class<?> personClass = Class.forName("com.live.collection.Person");
// 没有传递参数,获取的是无参构造函数
Constructor<?> pConstructor = personClass.getConstructor();
// 采用无参构造函数创建对象
Person person1 = (Person) pConstructor.newInstance();
System.out.println(person1);
执行结果:
>>>无参构造执行<<<
Person{name='null', id=null}
有参构造创建:
Class<?> personClass = Class.forName("com.live.collection.Person");
Constructor<?> moreConstructor = personClass.getConstructor(String.class, Long.class);
Person person2 = (Person) moreConstructor.newInstance("张三", 18L);
System.out.println(person2);
执行结果:
>>>有参构造执行<<<
Person{name='张三', id=18}
反射给对象的字段赋值
对象创建完成,接下来该给对象的字段赋值。
Class<?> personClass = Class.forName("com.live.collection.Person");
Person person = (Person) personClass.newInstance();
Field nameField = personClass.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(person, "小新");
Field idField = personClass.getDeclaredField("id");
idField.setAccessible(true);
idField.set(person, 9L);
System.out.println(person);
执行结果:
>>>无参构造执行<<<
Person{name='小新', id=9}
反射调用方法
反射如何调用对象的方法呢?
Class<?> personClass = Class.forName("com.live.collection.Person");
Person person = (Person) personClass.newInstance();
// 获取声明的方法,第一个参数为方法名称,第二个至后面都是参数类型列表(即每个参数的类型)
Method showNameMethod = personClass.getDeclaredMethod("showName", String.class);
// 设置权限
showNameMethod.setAccessible(true);
showNameMethod.invoke(person, "张三");
反射权限问题
上面在给对象的属性赋值,或者在调用方法时,我们会看到一个方法
setAccessible();
接下来我们谈论下该方法的作用
当我们的字段、方法、构造方法都是private修饰时,我们对对象进行的赋值、方法调用等都会触发权限不足的异常。
解决方案:在调用之前将权限设置为true 示例:
nameField.setAccessible(true);
showNameMethod.setAccessible(true);
反射的性能分析
相关阅读: Java反射性能问题,你真的需要考虑吗?
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 一天一大 lee(前 K 个高频元素)难度:中等-Day20200907
- 一天一大 lee(二叉树的层次遍历 II)难度:简单-Day20200906
- 一天一大 lee(第k个排列)难度:中等-Day20200905
- 一天一大 lee(二叉树的所有路径)难度:简单-Day20200904
- 一天一大 lee(N 皇后)难度:困难-Day20200903
- 一天一大 lee(二叉树的中序遍历)难度:中等-Day20200914
- 一天一大 lee(二叉树的层平均值)难度:简单-Day20200912
- 一天一大 lee(组合总和 II)难度:中等-Day20200910
- 一天一大 lee(组合总和 III)难度:中等-Day20200911
- 一天一大 lee(翻转二叉树)难度:简单-Day20200916
- 一天一大 lee(表示数值的字符串)难度:中等-Day20200902
- 一天一大 lee(单词搜索)难度:简单-Day20200913
- 一天一大 lee(克隆图)难度:中等-Day20200813
- 一天一大 lee(相同的树)难度:简单-Day20200807
- 一天一大 lee(解数独)难度:困难-Day20200915