什么是反射机制:
- 编译期:编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件
- 运行期:将可执行文件交给操作系统去执行。
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
java的反射机制提供了什么功能?
- 在运行时能够判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任一对象的方法
- 在运行时创建新类对象
new和反射创建有什么区别
- new: 静态编译,在编译期就将模块编译进来,执行该字节码文件,所有的模块都被加载;
- 反射:动态编译,编译期没有加载,等到模块被调用时才加载;
Java反射是如何使用的
获取类–获取Class对象
- 第一种方法:Class<?> classType = Class.forName() 可以通过传入一个全限定类名(包含包名)返回一个该类的Class类对象引用 。
try
{
Class a = Class.forName("mytest.testclass");//ClassPath:写需要反射的类名,一般是以包名.类名
System.out.println(a.getName());
}
catch (ClassNotFoundException e){
e.printStackTrace();
}
- 第二种方法: Class<?> classType = object.getClass() 通过引用的到Class对象。这种方式主要是需要把类先实例化出来才能继续使用
testclass test = new testclass();//实例化
Class a = test.getClass();//对象的getClass方法实现
- 第三种方法: Class<?> classType = Object.class 通过类字面常量获得,好处就是懒加载,只有使用时才会加载。
Class test = testclass.class;//直接使用类的.class方法,
第三种方法不需要进行异常捕获,上述两种方法搜需要进行异常处理
获得构造器
- getDeclaredConstructors(); 获取所有的构造函数
- getDeclaredConstructor(参数类型); 获取一个所有的构造函数
- getConstructors(); 获取所有公开的构造函数
- getConstructor(参数类型); 获取单个公开的构造函数
import java.lang.reflect.Constructor;
public class Main {
public static void main(String[] args) {
Class test = student.class;
Constructor[] constructors = test.getConstructors();//获取所有公开的构造函数
Constructor[] constructorsAll = test.getDeclaredConstructors();//获取所有的构造函数,包括私有的
try
{
Constructor constructorsSomeone= test.getConstructor(String.class);//获取指定参数的公开的构造函数
Constructor constructorsSomeoneAll = test.getDeclaredConstructor(String.class);//获取指定参数的所有构造函数
student obj = (student)constructorsSomeone.newInstance("哈哈");
obj.getname();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
class student
{
private student() {}//私有的构造函数
public student(String name)
{
System.out.println(name);
}
public student(String name,int a)
{
System.out.println(name);
}
public void getname()
{
System.out.println("呵呵");
}
}
获取修饰符
- getModifiers(); //获取所有修饰符
返回类型:整数类型,如果有两个修饰符,则返回两个修饰符之和,例如public static void getAll(){ }
返回值会是public和static之和
整数定义:- 0–默认不写
- 1–public
- 2–private
- 4–protected
- 8–static
- 16–final
- 32–synchronized
- 64–volatile
- 128–transient
- 256–native
- 512–interface
- 1024–abstract
Class test = student.class;
Constructor[] constructors = test.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor.getModifiers());
}
获取后可以根据Modifier类进行判断
Constructor[] constructors = test.getDeclaredConstructors();
for (Constructor constructor : constructors) {
Modifier.isPublic(constructor.getModifiers());
}
获取名字
返回类型:String,可以反射类名,方法名,构造函数名等等
getName(); //获取全名 例如:com.bean.Book
getSimpleName() //获取类名 例如:Book
Class test = student.class;
String name = test.getName();
String simplename = test.getSimpleName();
获得方法
- getMethods() //获取所有公开的方法
注意:它会将系统自带的方法也得到
Class test = student.class;
Method[] methods = test.getMethods(); //获取所有的公开方法
for (Method method : methods) {
System.out.println(method.getName());
}
- getDeclaredMethods() //获取所有的方法
注意:它不会获取系统自带的方法
Class test = student.class;
Method[] methods = test.getDeclaredMethods(); //获取所有的公开方法
for (Method method : methods) {
System.out.println(method.getName());
}
- getDeclaredMethod(String name) //获取单个的所有方法 参数是可指定方法名
Method method = test.getDeclaredMethod("getname"); //获取单个所有的方法
System.out.println(method.getName());
- getDeclaredMethod方法可以重载为getDeclaredMethod (String name ,Class<?>… parameterTypes)
可以获取该类的重载方法
Method method = test.getDeclaredMethod("getname",String.class);
System.out.println(method.getName());
获取字段
- getFields() //获取所有的公开字段
- getField(String name) //参数可以指定字段 获取单个public字段
- getDeclaredFields() //获取所有的字段
- getDeclaredField(String name) //获取单个字段 参数可以指定字段
Class test = student.class;
try
{
//Public
Field[] fields = test.getFields(); //所有公开字段
Field id = test.getField("age"); //age字段
//所有
Field[] declaredFields = test.getDeclaredFields(); //所有字段
test.getDeclaredField("name"); //name字段
System.out.println(id.getName());
}
catch (Exception ex)
{
ex.printStackTrace();
}
获取修改字段相关信息
反射只是通过Class对象获得方法和字段,要获取实例的字段就要传入一个具体的实例。
获取字段值
- Object value = field.get( Object obj) 通过get方法获得实例对象obj对应的field的值。
try
{
student stu = new student("xxx");//创建实例
Field field = student.class.getField("name");
Object value = field.get(stu);//这样获取必须传入一个实例
}
catch (Exception ex)
{
ex.printStackTrace();
}
- 如果field是静态字段则可以直接使用get(null)获取值。
- 获取基本类型字段的值 : int value = field.get(Object obj) 获取int类型的字段。还有其他类型也是用同样的方法。
- private修饰的字段无法直接获得,必须先设置file.setAccessible(true) 才能访问
获取字段相关信息并通过Modifier解析修饰符
- Annotation<?> annotation = field.getAnnotation(Class annotationClass) 返回字段上的指定注解
- Annotation[ ] annotations = field.getDeclaredAnnotations() 返回字段上的所有注解数组
- Class<?> type = field.getType() 返回 字段 的类型 的 Class对象。
- int modifier = field.getModifiers() 以int形式返回字段的修饰符。
- 通过Modifier静态方法判断是不是某一个权限修饰符,如Modifier.isPrivate(modifier)
- Modifier静态方法toString 返回权限标识符。
设置修改字段值
- field.set( Object obj, Object value) 通过set方法设置实例对象obj对应的file字段的值为value。
- 设置基本类型字段的值 :field.set(Object obj,int value) 获取int类型的字段。还有其他类型也是用同样的方法。
- private修饰的字段无法直接设置,必须先设置field.setAccessible(true) 才能设置。
- 被final修饰的字段,可以通过反射临时修改值,但是不会把原始值修改了,所以final是绝对不可变的。
获取包
返回类型:package
getPackage();
Package aPackage = test.getPackage();
获取接口
返回类型:Class[] interfaces
getInterfaces()
Class[] interfaces = test.getInterfaces();
获取父类/超类
返回类型:Class superclass
getSuperclass()
Class superclass = test.getSuperclass();
获取方法相关信息
和字段一样需要传入一个实例对象。
- 获取字段相关信息并通过Modifier解析修饰符
- Annotation<?> annotation = method.getAnnotation(Class annotationClass) 返回方法上的指定注解
- Annotation[ ] annotations = method.getDeclaredAnnotations() 返回方法上的所有注解数组
- Class<?> type = field.getReturnType() 返回 方法返回值类型 的 Class对象。
- getModifiers()方法使用与获取字段的使用方式相同
- 通过反射调用方法
- method.invoke(Object obj, Object… args) 传入实例对象obj和方法对应的参数。
- private修饰的方法无法反射,必须先设置method.setAccessible(true) 才能反射调用。
创建实例对象其他办法
- 通过反射得来的构造器创建实例
Constructor<?> constructor = test.getConstructor(new Class[]{});
Student student1 = (Student)constructor.newInstance();
Constructor<?> constructor2 = test.getConstructor(new Class[]{int.class});
Student student2 = (Student)constructor2.newInstance(12);
- 通过Class对象创建实例
Student student = Student.class.newInstance();
- 还有通过 new 、 反序列化、colon( ) 方法创建对象,Java中所以一共有5种方法创建实例对象
参考链接:
JAVA 反射用法
java反射方法和使用
欢迎关注我的个人博客zenshin’blog