这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战java
前言:目前不少三方框架都有用到反射的知识,本文将要介绍反射经常使用API。json
Java的反射(reflection)机制是指在程序的运行状态中,能够构造任意一个类的对象,能够了解任意一个对象所属的类,能够了解任意一个类的成员变量和方法,能够调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。数组
- 优势
反射提升了Java程序的灵活性和扩展性,下降耦合性,提升自适应能力。它容许程序建立和控制任何类的对象,无需提早硬编码目标类;反射是其它一些经常使用语言,如C、C++、Fortran 或者Pascal等都不具有的markdown
- 缺点
- 性能问题:使用反射基本上是一种解释操做,用于字段和方法接入时要远慢于直接代码。所以Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
- 使用反射会模糊程序内部逻辑:程序人员但愿在源代码中看到程序的逻辑,反射等绕过了源代码的技术,于是会带来维护问题。反射代码比相应的直接代码更复杂。
反射则是一开始并不知道咱们要初始化的类对象是什么,天然也没法使用 new关键字来建立对象,这时,咱们使用JDK提供的反射API进行反射调用。反射就是在运行状态中,对于任意一个类,都能知道,调用且改变这个类的全部属性和方法。app
Java反射机制主要提供了如下功能:框架
public static String str = new String("shixf");
public static void main(String[] args) {
//1.经过类名获取
Class<String> stringClass = String.class;
//2.经过对象获取
Class<? extends String> strClass = str.getClass();
//3.经过全类名获取
try {
//str.getClass().getName() == java.lang.String
Class<?> aClass = Class.forName(str.getClass().getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
复制代码
通常咱们经常用"instanceof" 关键字来判断某个类是否为一个类的实例,同时也能够借助反射中Class对象的 " isInstance()" 方法来判断是否为某个类的实例,它是一个native方法。函数
public native boolean isInstance(Object obj);
//判断是否为某个类的类型
public native boolean isAssignableFrom(Class<?> cls);
复制代码
public static Object createInstance_1(Class cls){
if(null != cls){
Object o = null;
try {
o = cls.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
return null;
}
public static Object createInstance_2(Class cls){
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = null;
//根据构造器建立实例
Object obj = null;
try {
constructor = c.getConstructor(String.class);
obj = constructor.newInstance("23333");
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
复制代码
/** * @param parameterTypes ...表明可传入该类型的数组,单个实例,或者不传参数, * 得到使用特殊的参数类型的public构造函数(包括父类) */
public Constructor<T> getConstructor(Class<?>... parameterTypes) /** * 得到类的全部公共构造函数 */ public Constructor<?>[] getConstructors() /** * 得到使用特定参数类型的构造函数(包括私有) */ public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) /** * 得到类的全部构造函数 */ public Constructor<?>[] getDeclaredConstructors() 复制代码
/** * 获取命名的公共字段(包含父类的public成员变量) */
public Field getField(String name) /** * 得到类的全部公共字段(包含父类的public成员变量) */ public Field[] getFields() /** * 获取类自己的属性成员(包括私有、共有、保护) */ public Field getDeclaredField(String name) /** * 获取类自己的全部属性成员(包括私有、共有、保护) */ public Field[] getDeclaredFields() 复制代码
/** * 使用特定参数类型,得到命名的公共方法 */
public Method getMethod(String name, Class<?>... parameterTypes) /** * 得到类的全部公共方法 */ public Method[] getMethods() /** * 得到类声明的命名的方法,包括私有的。 */ public Method getDeclaredMethod(String name, Class<?>... parameterTypes) /** * 得到类声明的全部命名的方法,包括私有的。 */ public Method[] getDeclaredMethods() 复制代码
注意:当咱们获取到一个方法时,能够调用invoke()方法来调用这个方法。以及须要注意的 “wrong number of arguments”异常post
/** * * @param obj * @param args 此处须要注意,该参数为Object * @return */
public Object invoke(Object obj, Object... args) 复制代码
public class GetMethod {
private static GetMethod getMethod = new GetMethod();
private static String[] strArray = {"1","2","3"};
public static void main(String[] args) {
getMethod();
}
public void printStr(String[] str){
for (String s : str) {
System.out.println(s);
}
}
public static void getMethod(){
Class<?> cls = getMethod.getClass();
try {
Method printStr = cls.getMethod("printStr",String[].class);
//此处须要强制转换为Object,不然抛出wrong number of arguments
printStr.invoke(cls.newInstance(),(Object) strArray);
} catch (Exception e) {
e.printStackTrace();
}
}
}
复制代码
数组在 Java 里是比较特殊的一种类型,它能够赋值给一个 Object Reference 其中的 Array 类为 java.lang.reflflect.Array类。咱们经过 Array.newInstance() 建立数组对象,它的原型是 :性能
public static Object newInstance ( Class <?> componentType , int length );
复制代码
当咱们对一个泛型类进行反射时,须要获得泛型中的真是数据类型,来完成如json反序列化的操做。此时须要经过Type体系来完成。Type接口包含了一个实现类(Class)个四个接口,分别是:ui
TypeVariable: 泛型类型变量,能够泛型上下限等信息。
ParameterizedType 具体的泛型类型,能够得到元数据中泛型签名类型(泛型真是类型)
GenericArrayType 当须要描述的类型是泛型类的数组时,好比List[] , map[],此接口会做为Type的实现。
WildcardType 通配符泛型,得到上下限信息。
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
public class TypeVariableTest<K extends Comparable & Serializable, V> {
private K key;
private V value;
public static void main(String[] args) {
try {
Field fKey = TypeVariableTest.class.getDeclaredField("key");
Field fValue = TypeVariableTest.class.getDeclaredField("value");
TypeVariable genericTypeKey = (TypeVariable)fKey.getGenericType();
TypeVariable genericTypeValue = (TypeVariable)fValue.getGenericType();
System.out.println("genericTypeKey.getName(): " + genericTypeKey.getName());
System.out.println("genericTypeValue.getName(): " + genericTypeValue.getName());
System.out.println(genericTypeKey.getGenericDeclaration());//class Reflect.TypeVariableTest
System.out.println(genericTypeValue.getGenericDeclaration());//class Reflect.TypeVariableTest
System.out.println("K的上界");
for (Type bound : genericTypeKey.getBounds()) {
System.out.println(bound);
//interface java.lang.Comparable
//interface java.io.Serializable
}
System.out.println("V的上界");
for (Type bound : genericTypeValue.getBounds()) {
System.out.println(bound);
//class java.lang.Object
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
复制代码
public class ParameterizedTypeTest {
Map<String, String> mMap;
public static void main(String[] args) {
try {
Field map = ParameterizedTypeTest.class.getDeclaredField("mMap");
System.out.println("get mMap GenericType: " + map.getGenericType());//java.util.Map<java.lang.String, java.lang.String>
ParameterizedType pType = (ParameterizedType)map.getGenericType();
System.out.println(pType.getRawType());//interface java.util.Map
for (Type actualTypeArgument : pType.getActualTypeArguments()) {
System.out.println(actualTypeArgument);//俩边class java.lang.String
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
复制代码
public class GenericArrayTypeTest<T> {
List<String>[] lists;
public static void main(String[] args) {
try {
Field field = GenericArrayTypeTest.class.getDeclaredField("lists");
GenericArrayType genericArrayType = (GenericArrayType)field.getGenericType();
System.out.println(genericArrayType.getGenericComponentType());//java.util.List<java.lang.String>
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
复制代码
public class WildcardTypeTest {
private List<? extends Number> up;//上限
private List<? super String> down;//下限
public static void main(String[] args) {
try {
Field up = WildcardTypeTest.class.getDeclaredField("up");
Field down = WildcardTypeTest.class.getDeclaredField("down");
//先拿到泛型类型
ParameterizedType parameterizedTypeUp = (ParameterizedType)up.getGenericType();
ParameterizedType parameterizedTypeDown = (ParameterizedType)down.getGenericType();
//在从泛型类型里拿到通配符类型
WildcardType wildcardTypeUp = (WildcardType)parameterizedTypeUp.getActualTypeArguments()[0];
WildcardType wildcardTypeDown = (WildcardType)parameterizedTypeDown.getActualTypeArguments()[0];
System.out.println(wildcardTypeUp.getUpperBounds()[0]);//class java.lang.Number
System.out.println(wildcardTypeDown.getLowerBounds()[0]);//class java.lang.String
System.out.println(wildcardTypeUp);//? extends java.lang.Number
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
复制代码