Java框架设计的灵魂(反射机制的基础知识介绍)
程序员文章站
2022-04-15 17:57:14
概念反射是可以在一个类运行的时候获取类的信息的机制,是Java语言的高级特性。为什么Java语言具有反射机制呢?因为在编写Java源代码(*.java)时类的信息通过编译器编译保存在Class对象中,而这个Class对象是在程序运行时被类加载器(ClassLoader)动态加载。.类加载器(ClassLoader)将类对象中文件(*.class)中的成员变量,构造方法,成员方法等加载到内存中,在运行时阶段就可以动态地获取Class对象的信息以及动态操作Class对象的属性和方法了。获取...
概念
- 反射是可以在一个类运行的时候获取类的信息的机制,是Java语言的高级特性。
-
为什么Java语言具有反射机制呢?
- 因为在编写Java源代码(*.java)时类的信息通过编译器编译保存在Class对象中,而这个Class对象是在程序运行时被类加载器(ClassLoader)动态加载。
-
.类加载器(ClassLoader)将类对象中文件(*.class)中的成员变量,构造方法,成员方法等加载到内存中,在运行时阶段就可以动态地获取Class对象的信息以及动态操作Class对象的属性和方法了。
获取Class对象的方式
- 要应用反射机制,首先要获取由ClassLoader将字节码文件装载进内存的class类对象,获取该对象会有三种方式:
/**
* 获了类对象的方式
*/ public class GetClassObject { public static void main(String[] args) throws ClassNotFoundException { // 第一种获取方式:Class.forName Class c1 = Class.forName("javademo202008.Reflect.Person"); System.out.println(c1); // 第二种获取方式:类名.class Class c2 = Person.class; System.out.println(c2); // 第三种获取方式: 对象.getClass Person person = new Person(); Class c3 = person.getClass(); System.out.println(c3); // 验证三种方式获取的是否是同一对象 System.out.println(c1 == c2 && c1 == c3); } } /**
* 人员类
*/ class Person { private String name; private String age; public Person() { } public Person(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
使用Class对象
获取到了内存中的Class类对象,接下来了解Class对象的各个功能 :
- 获取成员变量
方法 | 用途 |
---|---|
getFields() | 获得某个公有的属性对象 |
getField(String name) | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
- 获取构造方法
方法 | 用途 |
---|---|
getConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所有公有构造方法 |
getDeclaredConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
- 获取成员方法
方法 | 用途 |
---|---|
getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
- 获取类名
方法 | 用途 |
---|---|
getName() | 获得类的完整路径名字 |
/**
* 使用Class对象的各个功能
*/ public class ReflectGet { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { // 获取Person的Class对象 Class c = Person.class; // 1.获取所有成员变量 Field[] fields = c.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { System.out.println(fields[i]); } // 私有成员变量赋值 Field nameField= c.getDeclaredField("name"); nameField.setAccessible(true); Person person = new Person(); nameField.set(person,"Jack"); System.out.println(person.toString()); // 2.获取全参构造方法 Constructor constructor = c.getConstructor(String.class,String.class); System.out.println(constructor); // 创建对象 Object object = constructor.newInstance("Kate","19"); System.out.println(object.toString()); // 3.获取成员方法 Method setNameMethod = c.getMethod("setName",String.class); Method setAgeMethod = c.getMethod("setAge", String.class); // 执行方法 Person person1 = new Person(); setNameMethod.invoke(person1,"Mike"); setAgeMethod.invoke(person1,"12"); System.out.println(person1.toString()); // 4.获取类名 String className= c.getName(); System.out.println(className); } }
反射的应用案例
- 编写一个程序框架,可以创建任意类的对象,并且执行任意方法
# 定义一个配置文件 config.properties 进行类名与方法调用的配置 ClassName=javademo202008.Reflect.Person
MethodName=say # 通过该配置文件可以不改变代码,仅改变配置文件,即可实现类的更换 # ClassName=javademo202008.Reflect.People # MethodName=say
- 自定义一个人员类
/**
* 人员类
*/ public class Person { private String name; private String age; public Person() { } public Person(String name, String age) { this.name = name; this.age = age; } public void say(){ System.out.println("欢迎使用反射机制"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } }
- 框架代码
/**
* 运用反射构建一个框架
*/ public class FrameWork { public static void main(String[] args) throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException { // 加载配置文件 Properties properties = new Properties(); ClassLoader classLoader = FrameWork.class.getClassLoader(); InputStream inputStream = classLoader.getResourceAsStream("config.properties"); properties.load(inputStream); // 获取配置文件中定义类名与方法名 String className = properties.getProperty("ClassName"); String methodName = properties.getProperty("MethodName"); // 加载类 Class c = Class.forName(className); // 创建对象 Object object = c.newInstance(); // 获取方法对象 Method method = c.getMethod(methodName); // 通过反射运行 method.invoke(object); } }
本文地址:https://blog.csdn.net/jpgzhu/article/details/107895731