Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
了解Java反射机制前先了解一下类加载器相关的知识。java文件 经过编译 ->Class文件(字节码文件) 最后虚拟机执行的就是字节码文件, 但是字节码文件又不会自己跑到虚拟机当中, 这时候就得需要一个”人“,把字节码文件放到虚拟机当中,而这个人就是 类加载器。
类加载时机(何时加载字节码文件):
总结:用到就加载,不用不加载
类加载过程
验证
准备
解析
解析过程拆解:
name的类型是引用类型(String),String是其他的类的名字,最初加载String类的时候不知道String类在哪里,这时的String使用符号(ex:&&&)替代。在解析的过程中,就会找实际的String类在哪里,并把临时的符号变成实际的String引用
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 获取系统类加载器的父类加载器,平台类加载器
ClassLoader clasLoader1 = systemClassLoader.getParent();
//获取平台类加载器的父类加载器, 启动类加载器
ClassLoader classLoader2 = clasLoader1.getParent();
System.out.println("系统类加载器" + systemClassLoader);
System.out.println("平台类加载器" + clasLoader1);
System.out.println("启动类加载器" + classLoader2);
1.4 双亲委派模型方法名 | 说明 |
---|---|
public static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
public InputStream getResourceAsStream(String name) | 加载某一个资源文件 |
//获得系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 利用类加载器去加载一个指定的文件
// 参数:文件的路径
// 返回值:字节流
// 这里直接填写prop.properties,相对的在src下边
InputStream resourceAsStream = systemClassLoader.getResourceAsStream("prop.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
System.out.println(properties);
resourceAsStream.close();
2. 反射
2.1 反射的概述Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类所有的属性与方法;对于任意一个对象,都能够调用它的任意属性和方法(利用反射调用它类中的属性和方法时,无视修饰符)。
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制(先获取配置文件中的信息,动态获取信息并创建对象和调用方法)
public class Student {private String name;
private int age;
public Student() {}
public Student(String name, int age) {this.name = name;
this.age = age;
}
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;
}
public void study(){System.out.println("学生在学习");
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Class>clazz = Class.forName("全类名");
Classclazz2 = Student.class;
Student s = new Student();
//每一个对象都对应着一个字节码文件,所以getClass方法是定义在Object中的
Class clazz3 = s.getClass();
System.out.println(clazz == clazz2);//true
System.out.println(clazz3 == clazz2);//true
2.3 获取Class类对象中的内容Java当中什么都可以看成一个对象,只要是对象,就可以用类去描述。从class类中获取的成员变量就可以把它认为是成员变量对象(Field),以此类推…
如何学习?
大概步骤(以获取构造方法为例)
-获取class对象
-获得Constructor对象
-创建对象
明白几个问题
-获取对象不就是为了创建对象么?
-获取属性不就是为了给他赋值和取值么?
-获取方法不就是为了调用么?
学习
-把整个流程以及为什么用反射了解清楚,方法忘了就去api手册查,重复多了自然也就记住了
总结
-先获取整体(Class对象),在获取部分(成员属性,构造方法,成员男方法),然后操作部分
如图所示:Class对象加载到内存当中,我们可以去获取想要的信息
方法名 | 说明 |
---|---|
Constructor>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor getConstructor(Class>… parameterTypes) | 返回单个公共构造方法对象 |
Constructor getDeclaredConstructor(Class>… parameterTypes) | 返回单个构造方法对象 |
public class Student {private String name;
private int age;
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;
}
public void study() {System.out.println("我的名字是:" + name);
System.out.println("学生在打篮球");
}
private Student(String name) {System.out.println("name的值为:" + name + "age的值为:" + age);
System.out.println("private ... student ... 有参构造方法");
}
public Student() {System.out.println("public ... student ... 无参构造方法");
}
public Student(String name, int age) {System.out.println("name的值为:" + name + "age的值为:" + age);
System.out.println("public ... student ... 有参构造方法");
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
main
private static void method4() throws ClassNotFoundException, NoSuchMethodException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//小括号中一定要和构造方法的形参保持一致
Constructor>constructor = clazz.getConstructor();
System.out.println(constructor);
Constructor>constructor2 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor2);
//会报错,没有形参为int的构造方法
Constructor>constructor3 = clazz.getConstructor(int.class);
System.out.println(constructor3);
}
private static void method2() throws ClassNotFoundException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor>declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);
}
}
private static void method1() throws ClassNotFoundException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>[] constructors = clazz.getConstructors();
for (Constructor>constructor : constructors) {System.out.println(constructor);
}
}
2.4.2 通过Constructor对象中的方法创建对象方法名 | 说明 |
---|---|
T newInstance(Object…initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {// method1();
// method2();
// method3();
//获取一个私有的构造方法,并创建对象
//1.获取class对象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//2.获取一个私有化的构造方法
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//被private修饰的成员,不能直接使用
//如果使用反射前行获取并使用,需要临时取消访问检查
constructor.setAccessible(true);
//3.直接创建对象
Student student = (Student) constructor.newInstance("李白");
System.out.println(student);
}
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException { //简写格式
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Student student = (Student) clazz.newInstance();//这个方法过时了
}
private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>constructor = clazz.getConstructor();
Student student = (Student) constructor.newInstance();
System.out.println(student);
}
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { // 获取class对象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//获取构造方法对象
Constructor>constructor = clazz.getConstructor(String.class, int.class);
//利用newInstance方法,创建Student对象
Student student = (Student) constructor.newInstance("李白", 61);
System.out.println(student);
}
2.4.3 小结方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共(public)成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
private static void method4() throws ClassNotFoundException, NoSuchFieldException {//1.获取class对象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取name这个成员变量
Field field = clazz.getDeclaredField("money");
//3.打印
System.out.println(field);
}
private static void method3() throws ClassNotFoundException, NoSuchFieldException {//想要获取的成员变量必须是真是存在的,且是public的
//1.获取class对象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取name这个成员变量
Field field = clazz.getField("money");
//3.打印
System.out.println(field);
}
private static void method2() throws ClassNotFoundException {//1.获取class对象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取Field对象
Field[] fields = clazz.getDeclaredFields();
//3.遍历
for (Field field : fields) {System.out.println(field);
}
}
private static void method1() throws ClassNotFoundException {//1.获取class对象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取Field对象
Field[] fields = clazz.getFields();
//3.遍历
for (Field field : fields) {System.out.println(field);
}
}
2.5.2 给成员变量赋值方法名 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {// method1();
//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取成员变量的Field对象
Field field = clazz.getDeclaredField("money");
//3.取消访问检查
field.setAccessible(true);
//4.调用get方法来取值
//4.1创建一个对象
Person person = (Person) clazz.newInstance();
//4.2获取指定对象的money的值
Object o = field.get(person);
//5.打印
System.out.println(o);
}
private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
// 2.获取name这个Field对象
Field field = clazz.getField("name");
//3.利用set方法进行赋值
//3.1先创建一个Student对象
Person person = (Person) clazz.newInstance();
//3.2有了对象才可以给指定对象赋值
field.set(person,"李白");
System.out.println(person);
}
2.6 反射获取成员方法并使用
2.6.1 Class类获取成员方法对象的方法方法名 | |
---|---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class>… parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class>… parameterTypes) | 返回单个成员方法对象 |
private static void method5() throws ClassNotFoundException, NoSuchMethodException {//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取私有的方法
Method look = clazz.getDeclaredMethod("look");
System.out.println(look);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取有形参的方法
Method method1 = clazz.getMethod("method2", String.class);
System.out.println(method1);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取无参数的方法
Method method1 = clazz.getMethod("method1");
System.out.println(method1);
}
private static void method2() throws ClassNotFoundException {//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取成员方法对象
Method[] methods = clazz.getDeclaredMethods();// 返回所有成员方法的数组,不包含继承的
for (Method method : methods) {System.out.println(method);
}
}
private static void method1() throws ClassNotFoundException {//1.获取class对象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.获取成员方法对象
Method[] methods = clazz.getMethods();// 继承父类的方法也在里边
for (Method method : methods) {System.out.println(method);
}
}
以上就是今天要讲的内容,本文仅仅简单介绍了Java的反射机制,因为有关反射的方法众多,本文只介绍了较为常用的一些去供大家学习和了解!
本文中的案例大家不要光看哦,试着放到程序中运行一下,对加深理解有很大的帮助的!
最后,创作不易,如果本文对您有一点帮助的话,就点赞、收藏、关注支持鼓励一下吧,您的支持是我创作的动力!
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
售后响应及时
7×24小时客服热线数据备份
更安全、更高效、更稳定价格公道精准
项目经理精准报价不弄虚作假合作无风险
重合同讲信誉,无效全额退款