什么是反射机制:
编译期:编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件
运行期:将可执行文件交给操作系统去执行。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
java的反射机制提供了什么功能?
在运行时能够判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任一对象的方法
在运行时创建新类对象
new和反射创建有什么区别
new: 静态编译,在编译期就将模块编译进来,执行该字节码文件,所有的模块都被加载;
反射:动态编译,编译期没有加载,等到模块被调用时才加载;
Java反射是如何使用的
获取类–获取Class对象
第一种方法:Class<?> classType = Class.forName() 可以通过传入一个全限定类名(包含包名)返回一个该类的Class类对象引用 。
try { Class a = Class.forName("mytest.testclass" ); System.out.println(a.getName()); } catch (ClassNotFoundException e){ e.printStackTrace(); }
第二种方法: Class<?> classType = object.getClass() 通过引用的到Class对象。这种方式主要是需要把类先实例化出来才能继续使用
testclass test = new testclass(); Class a = test.getClass();
第三种方法: Class<?> classType = Object.class 通过类字面常量获得,好处就是懒加载,只有使用时才会加载。
Class test = testclass.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 { Field[] fields = test.getFields(); Field id = test.getField("age" ); Field[] declaredFields = test.getDeclaredFields(); test.getDeclaredField("name" ); System.out.println(id.getName()); } catch (Exception ex){ ex.printStackTrace(); }
获取修改字段相关信息
反射只是通过Class对象获得方法和字段,要获取实例的字段就要传入一个具体的实例。
获取字段值
1) 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(); }
2) 如果field是静态字段则可以直接使用get(null)获取值。 3) 获取基本类型字段的值 : int value = field.get(Object obj) 获取int类型的字段。还有其他类型也是用同样的方法。 4) 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形式返回字段的修饰符。 1) 通过Modifier静态方法判断是不是某一个权限修饰符,如Modifier.isPrivate(modifier) 2) 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解析修饰符 1) Annotation> annotation = method.getAnnotation(Class annotationClass) 返回方法上的指定注解
2) Annotation[ ] annotations = method.getDeclaredAnnotations() 返回方法上的所有注解数组
3) Class> type = field.getReturnType() 返回 方法返回值类型 的 Class对象。 4) getModifiers()方法使用与获取字段的使用方式相同
通过反射调用方法 1) method.invoke(Object obj, Object… args) 传入实例对象obj和方法对应的参数。 2) 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 );
Student student = Student.class .newInstance () ;
还有通过 new 、 反序列化、colon( ) 方法创建对象,Java中所以一共有5种方法创建实例对象
参考链接:JAVA 反射用法 java反射方法和使用