Java基础-反射
Class也是类,因此也继承Object类Class类对象不是new出来的,而是系统创建的对于某个类的Class类对象,在内存中只有一份,因为类只加载一次每个类的实例都会记得自己是由哪个Class实例所生成的通过Class对象,可以完整地得到一个类的完整结构,通过一系列APIClass类对象是放在堆的,可以理解为是把方法区中的元数据保存到Class类对象中,方便获取其中的成员类的字节码二进制数据,
·
1.快速入门
1.案例引入
2.代码实例
package Reflection_;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @author 孙显圣
* @version 1.0
*/
public class ReflectionQuestion {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//使用反射来根据配置文件来调用方法
//1.读取配置文件,获取类的全路径和方法
Properties properties = new Properties();
properties.load(new FileInputStream("src\\cat.properties"));
String fullclasspath = properties.getProperty("fullclasspath");
String method = properties.getProperty("method");
//2.加载类,返回Class类型的对象cls
Class<?> cls = Class.forName(fullclasspath);
//3.获取加载类的对象实例
Object o = cls.newInstance();
//4.获取加载类的方法对象
Method method1 = cls.getMethod(method);
//5.调用这个方法
method1.invoke(o);
}
}
3.反射机制原理图
2.反射相关类
1.反射获取类的成员
代码实例
package Reflection_;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author 孙显圣
* @version 1.0
*/
public class Refection01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
//类加载,获取Class类型
Class<?> cls = Class.forName("Reflection_.Cat");
//反射获取属性
Field name = cls.getField("name"); //不能获取私有的
System.out.println(name);
//反射获取构造器
Constructor<?> constructor = cls.getConstructor(String.class);
System.out.println(constructor);
//反射获取方法
Method hi = cls.getMethod("hi");
System.out.println(hi);
}
}
结果
2.反射调用优化
1.关闭访问检查
- Method,Field,Constructor对象都有setAccessible方法
- setAccessible作用是启动和禁用访问安全检查的开关,true为取消
2.代码实例
package Reflection_;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author 孙显圣
* @version 1.0
*/
public class Refection02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
//传统方法来调用hi
new Cat().hi();
//使用反射来调用hi
Class<?> cls = Class.forName("Reflection_.Cat");
//获取方法对象
Method hi = cls.getMethod("hi");
//获取加载类的对象实例
Object o = cls.newInstance();
//关闭访问检查,提高速度
hi.setAccessible(true);
//执行方法
hi.invoke(o);
}
}
3.Class类
1.类图
2.基本介绍
- Class也是类,因此也继承Object类
- Class类对象不是new出来的,而是系统创建的
- 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
- 每个类的实例都会记得自己是由哪个Class实例所生成的
- 通过Class对象,可以完整地得到一个类的完整结构,通过一系列API
- Class类对象是放在堆的,可以理解为是把方法区中的元数据保存到Class类对象中,方便获取其中的成员
- 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据
3.Class类常用方法
代码实例
package Reflection_;
import java.lang.reflect.Field;
/**
* @author 孙显圣
* @version 1.0
*/
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//定义全路径
String allClassPath = "Reflection_.Cat";
//获取Cat类的Class类对象
Class<?> cls = Class.forName(allClassPath);
//显示该对象是哪个类的Class对象
System.out.println(cls);
//显示运行类型
System.out.println(cls.getClass());
//获取包名
System.out.println(cls.getPackage().getName());
//获取全类名
System.out.println(cls.getName());
//通过反射创建对象
Cat o = (Cat) cls.newInstance();
o.hi(); //调用Cat类的方法
//通过反射获取属性
Field name = cls.getField("name");
//通过反射给属性赋值
name.set(o,"小猫");
System.out.println(name.get(o));
//遍历所有属性
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field.get(o));
}
}
}
结果
4.获取Class类对象
代码实例
package Reflection_;
/**
* @author 孙显圣
* @version 1.0
*/
public class Class02 {
public static void main(String[] args) throws Exception {
//获取反射对象的六种方式
//1. Class.forName
String classAllPath = "Reflection_.Cat"; //一般通过读取配置文件获取,在框架中用的较多
Class<?> aClass = Class.forName(classAllPath);
//2. 类名.class,应用场景:用于参数传递
System.out.println(Cat.class);
//3. 对象.getClass(),应用场景:有对象实例,获取运行类型
System.out.println(new Cat().getClass());
//4. 通过类加载器获取
ClassLoader classLoader = Cat.class.getClassLoader(); //获取类加载器
Class<?> aClass1 = classLoader.loadClass(classAllPath);
//5.基本数据类型 类型.class
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
System.out.println(integerClass);
System.out.println(characterClass);
//6.基本数据类型对应的包装类 类型.TYPE
Class<Integer> type = Integer.TYPE;
Class<Character> type1 = Character.TYPE;
System.out.println(type);
System.out.println(type1);
}
}
结果
5.哪些类型有Class对象
4.类加载
1.基本介绍
- 静态加载:编译时加载相关的类,如果没有则报错
- 动态加载:运行时才加载需要的类,如果运行时不使用该类,即使不存在该类,则不报错,降低了依赖性
- 类加载时机:
- 当创建对象时
- 当子类被加载时,父类也会被加载
- 调用类中的静态成员时
- 通过反射(动态加载)
2.静态加载与动态加载实例
在这里如果没有Dog类则直接编译报错,但是如果没有Person类,只要不执行case2则不会报错
3.类加载流程图
4.简要理解类加载
- 加载:得到Class类对象
- 连接:静态默认初始化,常量直接初始化
- 合并初始化:将静态代码合并,根据语句内容进行初始化
5.反射获取类的结构信息
第一组
代码实例
package Reflection_;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author 孙显圣
* @version 1.0
*/
public class ReflectionUtils {
public static void main(String[] args) {
}
@Test
public void api_01() throws Exception {
//得到Class对象
Class<?> personCls = Class.forName("Reflection_.Person");
// getName:获取全类名
System.out.println(personCls.getName());
// getSimpleName:获取简单类名
System.out.println(personCls.getSimpleName());
// getFields:获取所有public修饰的属性,包含父类以及本类的
Field[] fields = personCls.getFields();
for (Field field : fields) {
System.out.println(field);
}
// getDeclaredFields:获取本类所有属性
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类所有属性:" + declaredField);
}
// getMethods:获取所有public修饰的方法,包括本类以及父类的
Method[] methods = personCls.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// getDeclaredMethods:获取本类所有方法
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类所有方法:" + declaredMethod);
}
// getConstructors: 获取所有public修饰的构造器,包括本类的
Constructor<?>[] constructors = personCls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// getDeclaredConstructors: 获取本类所有的构造器
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
System.out.println("本类所有构造器:" +declaredConstructors);
// getPackage:以Package形式返回包信息
System.out.println(personCls.getPackage());
// getSuperClass:以Class形式返回父类信息
System.out.println(personCls.getSuperclass());
// getInterfaces:以Class[]形式返回接口信息
Class<?>[] interfaces = personCls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println("所有接口信息:" + anInterface);
}
// getAnnotations:以Annotation[]形式返回注解信息
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
interface B {
}
class A {
public String hobby;
public void hi() {
}
}
@SuppressWarnings("all")
@Deprecated
class Person extends A implements B{
//属性
public String name;
protected int age;
String job;
private double sal;
//构造器
//方法
public void m1() {
}
protected void m2() {
}
void m3() {
}
private void m4() {
}
}
结果
第二组
代码实例
@Test
public void api_02() throws ClassNotFoundException {
//得到Class对象
Class<?> personCls = Class.forName("Reflection_.Person");
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("该类的字段名:" + declaredField.getName() +
" 该类的修饰符int形式:" +declaredField.getModifiers() +
" 该类的Class类型:" + declaredField.getType());
}
}
结果
第三组
代码实例
@Test
public void api_03() throws ClassNotFoundException {
//得到Class对象
Class<?> personCls = Class.forName("Reflection_.Person");
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("该类的方法名:" + declaredMethod.getName() +
" 该类的方法修饰符int形式:" +declaredMethod.getModifiers() +
" 该类的方法返回类型:" + declaredMethod.getReturnType());
//获取参数类型数组
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("参数类型:" + parameterType);
}
}
}
结果
第四组
代码实例
@Test
public void api_04() throws ClassNotFoundException {
//得到Class对象
Class<?> personCls = Class.forName("Reflection_.Person");
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("该类的构造器名:" + declaredConstructor.getName() +
" 该类的构造器int形式修饰符:" + declaredConstructor.getModifiers()
);
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("参数类型:" + parameterType);
}
}
}
结果
6.反射爆破
1.反射爆破创建实例
代码实例
package Reflection_;
import java.lang.reflect.Constructor;
/**
* @author 孙显圣
* @version 1.0
*/
public class CreateInstance {
public static void main(String[] args) throws Exception {
//获取Class类对象
Class<?> userClass = Class.forName("Reflection_.User");
//1.使用无参构造方法创建实例
Object o = userClass.newInstance();
System.out.println(o);
//2.使用public的有参构造方法创建实例
//获取有参构造器对象
Constructor<?> constructor = userClass.getConstructor(String.class);
//创建实例
Object o1 = constructor.newInstance("小明");
System.out.println(o1);
//3.使用非public的有参构造方法创建实例
//获取构造器
Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);
//反射爆破
declaredConstructor.setAccessible(true);
//创建实例
Object o2 = declaredConstructor.newInstance("杰克", 20);
System.out.println(o2);
}
}
class User {
private String name = "李华";
private int age = 18;
public User() {
}
public User(String name) {
this.name = name;
}
private User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
结果
2.反射爆破操作属性
代码实例
package Reflection_;
import java.lang.reflect.Field;
/**
* @author 孙显圣
* @version 1.0
*/
public class AccessProperty {
public static void main(String[] args) throws Exception {
//获取Class实例
Class<Student> studentClass = Student.class;
//反射创建一个实例
Student student = studentClass.newInstance();
//1.操作public的属性
//获取public的属性
Field age = studentClass.getField("age");
//操作
age.set(student, 100);
System.out.println(age.get(student));
//2.操作非public且静态的属性
//获取私有属性
Field name = studentClass.getDeclaredField("name");
//反射爆破
name.setAccessible(true);
//操作
name.set(null, "李华");
System.out.println(name.get(null)); //注意这里是因为是静态的属性才能填null,如果不是静态的则必须填对象
}
}
class Student {
public int age;
private static String name;
@Override
public String toString() {
return "Student{" +
"age=" + age +
'}';
}
}
结果
3.反射爆破操作方法
代码实例
package Reflection_;
import java.lang.reflect.Method;
/**
* @author 孙显圣
* @version 1.0
*/
public class AccessMethod {
public static void main(String[] args) throws Exception {
//获取Class对象
Class<Boss> bossClass = Boss.class;
//创建实例
Boss boss = bossClass.newInstance();
//1.操作public的方法
//获取方法
Method hi = bossClass.getMethod("hi", String.class);
//操作
hi.invoke(boss, "李华");
//2.操作非public的方法
//获取方法
Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
//爆破
say.setAccessible(true);
//操作
Object invoke = say.invoke(null, 1, "2", '3');//注意,因为这里是静态的方法所以才能是null
System.out.println(invoke);
}
}
class Boss {
public int age;
private static String name;
private static String say(int n, String s, char c) {
return n + "" + s + "" + c;
}
public void hi(String s) {
System.out.println("hi:" + s);
}
}
结果
7.本章练习
练习一
题目
代码
package Reflection_;
import java.lang.reflect.Field;
/**
* @author 孙显圣
* @version 1.0
*/
public class HomeWork01 {
public static void main(String[] args) throws Exception{
//获取Class类
Class<PrivateTest> privateTestClass = PrivateTest.class;
//创建实例
PrivateTest privateTest = privateTestClass.newInstance();
//获取属性
Field name = privateTestClass.getDeclaredField("name");
//反射爆破
name.setAccessible(true);
//修改属性
name.set(privateTest, "cat");
//输出属性
System.out.println(name.get(privateTest));
}
}
class PrivateTest {
private String name = "hellokitty";
public String getName() {
return name;
}
}
结果
练习二
题目
代码
package Reflection_;
import java.io.File;
import java.lang.reflect.Constructor;
/**
* @author 孙显圣
* @version 1.0
*/
public class HomeWork02 {
public static void main(String[] args) throws Exception{
//获取File类的Class对象
Class<File> fileClass = File.class;
//打印所有构造器
Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//获取构造器
Constructor<File> declaredConstructor = fileClass.getDeclaredConstructor(String.class);
//创建实例
File file = declaredConstructor.newInstance("src\\Reflection_\\a.txt");
file.createNewFile();
}
}
结果
更多推荐
已为社区贡献10条内容
所有评论(0)