Java 中的反射机制
一、概念
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
二、作用
1.反编译:由字节码文件转成java源代码文件(xxx.class–>xxx.java);
2.通过反射机制访问Java对象的属性、方法和构造方法等。
三、jdk中提供的反射机制中的类
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
四、功能的实现
准备工作,我们先写一个实体类,名字叫Employee
package com;
public class Student {
private String name;
private int age;
private boolean gender;
public Student() {
}
public Student(String name) {
this.name = name;
}
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 setGender(boolean gender) {
this.gender = gender;
}
public boolean getGender() {
return this.gender;
}
}
1.反射机制获取类有三种方法,获取Student类型
// 第一种方式:Java中每一个类型都会有一个class属性
Class c1 = Student.class;
// 第二种方式:
//要抛出java.lang.ClassNotFoundException异常
Class c2 = Class.forName(“com.Student”);
// 第三种方式:
Class c3 = new Student().getClass();
2.创建对象,获取类后,创建该类的对象,利用newInstance()方法
Class c = Class.forName(“com.Student”);
// 创建此Class对象所表示的类的一个新实例
// 调用了Student的无参的构造方法。要抛出 java.lang.InstantiationException异常。
Object o = c.newInstance();
- 获取属性,分为所有的属性和指定的属性
a) 获取所有属性的方法:
package com;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
Class c = Class.forName("com.Student");
// 获取所有属性
Field[] fs = c.getDeclaredFields();
// 定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
// 通过追加的方法,将每个属性拼接到此字符串中
// 最外边的public定义
sb.append(Modifier.toString(c.getModifiers()) + " class "
+ c.getSimpleName() + " {\n");
// 里边的每一个属性
for (Field field : fs) {
sb.append(" ");// 空格
sb.append(Modifier.toString(field.getModifiers()) + " "); // 获得属性的修饰符,例如public、static等。
sb.append(field.getType().getSimpleName() + " ");// 属性的类型的名字
sb.append(field.getName() + ";\n");// 属性的名字+回车
}
sb.append("}");
System.out.println(sb);
}
}
b) 获取特定的属性,对比着传统的方法来学习;
package com;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws ClassNotFoundException,
SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException, InstantiationException {
// 原始的方式
Student e = new Student();
e.setName("xzk");
System.out.println(e.getName());
// 获取类Employee
Class c = Class.forName("com.Student");
// 获取name属性
Field fName = c.getDeclaredField("name");
// 创建一个Employee类的对象o
Object o = c.newInstance();
// 设置name属性是可修改的。打破了类的封装性!!!使用反射机制可以打破类的封装性!极不安全!!
fName.setAccessible(true);
// 设置o对象的name属性的值为110
fName.set(o, "xzk");
// 输出测试
System.out.println(fName.get(o));
}
}
4.获取方法构造方法不再详述,来看一下方法的关键字:
普通方法关键字 | 含义 |
---|---|
getDeclaredMethods() | 获取所有的方法 |
getReturnType() | 获得方法的返回类型 |
getParameterTypes() | 获得方法的传入参数类型 |
getDeclaredMethod(“方法名”,参数类型.class,…) | 获得特定的方法 |
构造方法关键字 | 含义 |
---|---|
getDeclaredConstructors() | 获取所有的构造方法 |
getDeclaredConstructor(参数类型.class,…) | 获取特定的构造方法 |
父类和父接口 | 含义 |
---|---|
getSuperclass() | 获取某类的父类 |
getInterfaces() | 获取某类实现的接口 |
这样我们就可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。
五、反射加载配置文件
在设计模式学习当中,学习抽象工厂的时候就用到了反射机制来更加方便的读取数据库连接字符串等。
<该内容过几日再详解。。。>