Java基础反射
目录:
-
-
- 前言
- 一.反射的简介
-
- 1.引出反射
- 2.反射简介
- 3.Java 反射机制原理示意图
- 4.反射优点和缺点
- 5.反射调用优化-关闭访问检查
- 二.Class类
- 三.通过反射获取类的结构信息
-
前言
最近在回顾JavaSE部分的知识,对一些薄弱的知识进行记录,学习方式,通过视频和图书的进行学习,视频看B站韩顺平老师的30天学会Java,图书看Java核心技术 卷I 基础知识(原书第10版)。
韩顺平30天学会Java地址:https://www.bilibili.com/video/BV1g84y1F7df?spm_id_from=333.999.0.0
一.反射的简介
1.引出反射
需求
代码:
package com.dudu.demo1;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;public class Cat { private String name; private int age; public void hi(){ System.out.println("喵喵叫~~~"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}class Test{ public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // 通过Cat.properties文件获取classfullpath和method的参数 Properties properties =new Properties(); properties.load(new FileInputStream("src\\Cat.properties")); String classfullpath = properties.getProperty("classfullpath"); String method = properties.getProperty("method"); System.out.println(classfullpath); System.out.println(method); // 获取到类路径 Class cls = Class.forName(classfullpath);// 加载类对象 Object o =cls.newInstance();// 加载实例 Method method1 = cls.getMethod(method);// 获取实例方法 method1.invoke(o);// 调用方式 方法.invoke(对象) }}
Cat.properties(在src目录下创建)
classfullpath=com.dudu.demo1.Catmethod=hi
分析:
- 使用常规手段是无法将一个字符串类型的类名(包含路径.类名),直接转换为实例对象,相应的就无法调用该实例对象下的方法,这个时候就可以通过反射技术实现。
- 对象通过Class下的
newInstance();
获得 - 在反射中,方法也可以看成一个对象(
Method
),通过Class下的getMethod(methodName);
获得。 - 在反射中,调用方法的方式为
方法.invoke(对象)
。
2.反射简介
3.Java 反射机制原理示意图
- Java 反射机制可以完成
- 反射相关的主要类
练习代码:
Field和Constructor的使用
// 获取属性 Field field = cls.getField("publicData"); System.out.println(field.get(o)); // 获取构造方法 Constructor constructor =cls.getConstructor(); System.out.println(constructor); Constructor constructor2 =cls.getConstructor(String.class); System.out.println(constructor2);
在Cat类中添加红框框代码:
运行效果:
- Field 对象表示某个类的成员变量
- Class下的
getField(属性名)
,不能得到私有的属性,需要先爆破。 - 在反射中获取属性:
Field对象.get(实例对象)
- Constructor 对象表示构造器
- 带参的Constructor 参数为
Class
类型,指定构造器参数类型需要传入有参数据类型对应的数据类型.Class对象
。
4.反射优点和缺点
代码:
package com.dudu.demo1;import java.lang.reflect.Method;public class Test2 { public static void main(String[] args) throws Exception { // 方式一 Cat cat = new Cat(); // 开始计时 long start = System.currentTimeMillis(); for (int i=0;i<=100000000;i++){ cat.hi(); } long end = System.currentTimeMillis(); System.out.println("耗时"+(end-start)); // 方式二 start = System.currentTimeMillis(); Class cls = Class.forName("com.dudu.demo1.Cat");// 创建class Object o = cls.newInstance();// 获取对象 Method hi = cls.getMethod("hi");// 获取方法对象 // 调用方法 for (int i=0;i<=100000000;i++){ hi.invoke(o); } end = System.currentTimeMillis(); System.out.println("耗时"+(end-start)); }}
运行效果(明显可以看出通过反射方式调用方法效率低的多):
5.反射调用优化-关闭访问检查
在前面说到访问私有属性需要爆破,这里的爆破指的就是关闭访问检测和调用getDeclaredXX实现爆破
(访问私有属性时,会出现以下异常
)
修改代码如下:
运行效果(此时私有属性也可以访问
):
二.Class类
- 简述
- 常用方法
- 获取 Class 类对象
- 哪些类型有 Class 对象
三.通过反射获取类的结构信息
- java.lang.Class 类
- Field 类
- Method 类
- Constructor 类