1.java反射是什么?
java反射机制:指的是程序运行时能够获取自身的信息。在Java中只要给定类的名字,那么就可以通过反射机制来获取类的所有信息。
2.反射有什么用?
增加程序的灵活性,避免将程序写死到代码里.
优点:可以实现动态创建对象和编译,体现出很大的灵活性。
3.反射一般用在哪里?
一般用在框架体层比较多,如:初始化一些程序配置,配置文件properties可以由用户自己修改,这样就不需要一有问题就发新包给用户,
让用户进行卸载更新应用程序,提高了灵活性。
*不过直接读取properties配置文件即可,为啥还需要用反射呢?*
拿到properties,这样的话你想取里面的值就需要在应用的全局变量中存储properties,否则每次都要去getProperties(),
然后根据properties.getProperty("name"),这样子很麻烦,可以直接把配置文件中的内容反射到一个类里,这个类专门存放与配置
文件相应的变量,这样我们代码中就可以通过类的变量来获取properties配置文件中的值。
4.如何使用反射?
第一步:获取Class对象。
Class类:Java中java.lang.Class类用于表示一个类的字节码(.class)文件.
如何得到某个class文件对应的Class对象
已知类和对象的情况下
类名.class
对象.getClass() ---- Object类提供
未知类和对象的情况下
Class.forName(“包名.类名”)
Class类代表某个类的字节码,并提供了加载字节码的方法:forName(“包名.类名”)
forName方法用于加载类字节码到内存中,并封装成一个Class对象.
第二步:通过Class对象中的方法获取类中构造方法、成员变量、方法,拿到后对外提供都是对象,有Constructor、Field、Method对象。
1.创建实例(获得构造器).
Constructor类
Constructor类的实例对象代表类的一个构造方法
得到某个类所有的构造方法
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到指定的构造方法并调用
Constructor constructor = Class.forName(“java.lang.String”).getConstructor(String.class);
String str = (String)constructor.newInstance(“abc”);
Class类的newInstance()方法用来调用类的默认构造方法
String obj =(String)Class.forName("java.lang.String").newInstance();
1).class.newInstance()创建实例,相对于无参数的构造方法,如:
Person p = (Person)clazz.newInstance();
2).Constructor c = class.getConstructor(int.class,String.class);//创建实例,相对于一个带(int,String)参数的有参构造方法.
//通过构造器来创建实例。
Person p2 = (Person)c.newInstance(28,”张三”);
3)class.getConstructors();//获取说有构造器。
2.获取属性的对象。
Field类
Field类代表某个类中的一个成员变量,并提供动态的访问权限
Field对象的获得
得到所有的成员变量
Field[] fields = c.getFields(); // 取得所有public属性(包括父类继承)
Field[] fields = c.getDeclaredFields(); // 取得所有声明的属性
得到指定的成员变量
Field name = c. getField("name");
Field name = c. getDeclaredField("name");
设置Filed变量是否可以访问
field. setAccessible(boolean);
Field变量值的读取、设置
field.get(obj)
filed.set(obj,value);
获取属性:
1).class.getField(“name”);//获取公有的name的属性,即Person类中的name属性必须声明为public才行,如果是private String name声明为private私有的,获取不到。
2).Field name = class.getDeclaredField(“name”);//可以获取公有的和私有的
//拿到name的属性之后,可以设置属性的内容
name.setAccessible(true);//设置操作属性,就是允许你去操作name属性,因为name是私有的,你不是他,你操作不了。
//设置属性内容,需要传一个实例
Person person = (Person)class.newInstansnce();
name.set(person,”张三”);//这句话相当于 p.name = “张三’;
//获取属性值
System.out.println(name.get(person));//输出: 张三
//获取属性名称
System.out.println(name.getName());//输出: name
3.获取方法的对象。
Method类
Method类代表某个类中的一个成员方法
Method对象的获得
获得所有方法
getDeclaredMethods()
getMethods()
获得指定的方法
getDeclaredMethod(String?name, Class<?>...?parameterTypes)
getMethod(String?name, Class<?>...?parameterTypes)
m.setAccessible(true);
通过反射执行方法
invoke(Object?obj, Object...?args)
注意:如果执行static方法 ,第一个参数obj 传入 null
获取方法:
1).Method m = class.getDeclaredMethod(“setName”,String.class);//获取公有的和私有的方法
m.setAccessible(true);
Person p = (person)clazz.newInstance();
m.invoke(p,”张三”);//相当于 p.setName(“张三”);
//获取方法名称
System.out.println(m.getName());//输出: setName
其他方法:
boolean isArray():是否为数组类型;
? boolean isAnnotation():是否为注解类型;
? boolean isAnnotationPresent(Class annotationClass):当前类是否被annotationClass注解了;
? boolean isEnum():是否为枚举类型;
? boolean isInterface():是否为接口类型;
? boolean isPrimitive():是否为基本类型;
? boolean isSynthetic():是否为引用类型;
其他反射类:
其他反射类都在java.lang.reflect包下
1.AccessibleObject
AccessibleObject类是Constructor、Method、Field三个类的父类。
? Annotation getAnnotation(Class annotationClass):获取作用在当前成员上的annotationClass类型的注解对象;
? Annotation[] getAnnotations():获取作用在当前成员上的所有注解对象;
? boolean isAccessible():判断当前成员是否可访问;
? void setAccessible(boolean flag):设置当前成员是否可访问。
2.Construcator
? String getName():获取构造器名;
? int getModifiers():获取构造器上的所有修饰符信息;
? Class getDeclaringClass():获取构造器所属的类型;
? Class[] getParameterTypes():获取构造器的所有参数的类型;
? Class[] getExceptionTypes():获取构造器上声明的所有异常类型;
? T newInstance(Object… initargs):通过构造器反射对象调用构造器。
3.Method
? String getName():获取方法名;
? int getModifiers():获取方法上的所有修饰符信息;
? Class getDeclaringClass():获取方法所属的类型;
? Class[] getParameterTypes():获取方法的所有参数的类型;
? Class[] getExceptionTypes():获取方法上声明的所有异常类型;
? Class getReturnType():获取方法的返回值类型;
? Object invode(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,
如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数;
? setAccessible(true);
4.Field
? String getName():获取属性名;
? int getModifiers():获取属性上的所有修饰符信息;
? Class getDeclaringClass():获取属性所属的类型;
? Class getType():获取当前属性的类型;
? Object get(Object obj):获取obj对象的当前属性值;
? void set(Object obj, Object value):设置obj对象的当前属性值为value;
? XXX getXXX(Object obj):如果当前属性为基本类型,可以使用getXXX()系列方法获取基本类型属性值。假如当前属性为int类型,
那么可以使用getInt(Object obj)方法获取obj对象的当前属性值;
? void setXXX(Object obj, XXX value):如果当前属性为基本类型,可以使用setXXX()系统方法基本类型属性值。假如当前属性为int类型,
那么可以使用setInt(Object obj, int value)方法设置obj对象的当前属性值为value。
5.Modifier
Modifier类有一系列的static方法用来解析其他getModifiers()方法返回的int值。
Method m = …
int m = m.getModifiers();
boolean b1 = Modifier.isAbstract(m);//解析m中是否包含abstract修饰
boolean b2 = Modifier.isStatic(m);//解析m中是否包含static修饰
String s = Modifiers.toString(m);//把所有修饰都转换成字符串
其他补充:isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。
通常调用格式是:
Class1.isAssignableFrom (Class2)
调用者和参数都是 java.lang.Class 类型。