获取class
在java中一个类可以有多个对象,但只能有一个class对象,获取类的方式有3中
Person mPerson = new Person();
Class c1 = mPerson.getClass();
Class c2 = Person.class;
Class c3 = Class.forName("com.wld.java.blogs.reflect.Person");
反射常用方法
getFields() //获取所有public的属性,包括从父类以及接口继承的
getDeclaredFields() //获取当前类的所有属性,包括私有的
getField("fieldName") //获取指定的属性
getDeclaredField("fieldName") //获取指定的属性
getMethods() //获取所有public的方法,包括从父类以及接口继承的
getDeclaredMethods() //获取当前类的所有方法,包括私有的
getMethod("methodName",Class... class) //获取指定的方法
getDeclaredMethod("methodName",Class... class) //获取指定的方法
getConstructors() //获取当前类的所有public的构造函数,由于子类不能继承父类的构造函数,所以获取不到父类的构造函数
getDeclaredConstructors() //获取当前类的所有构造函数,包括私有的
getConstructor(Class... class) //获取指定的构造函数
getDeclaredConstructor(Class... class) //获取指定的构造函数
getInterfaces()//获取接口
getTypeParameters()//获取泛型参数,结果为数组,比如类Person<K, T>,获取的结果为K,T
如果要调用父类的私有属性和方法要先获取父类的class,比如获取Person父类的class
Class superc = Person.class.getSuperclass();
获取类的实例
假如有一个Person类有两个构造函数,一个是无参的构造函数,一个是有两个String类型参数的构造函数
Person mPerson1 = (Person) c.getDeclaredConstructor().newInstance();
Person mPerson2 = (Person) c.getDeclaredConstructor(String.class, String.class).newInstance("123", "456");//构造函数的参数类型
这两种方式都可以创建类的实例。如果构造函数是私有的,在用上面方法就不行了。假如有两个String参数的构造函数是私有的,在实例化之前要设置setAccessible(true);
Constructor mConstructor2 = c.getDeclaredConstructor(String.class, String.class);//构造函数的参数类型
mConstructor2.setAccessible(true);
Person mPerson2 = (Person) mConstructor2.newInstance("123", "456");//传值
改变属性的值
Class c = Person.class;
Object object = c.getDeclaredConstructor().newInstance();
Field field = c.getDeclaredField("publicPersonName");
field.set(object, "123");//如果publicPersonName是静态的,object可以为null
如果属性是私有的必须要加field.setAccessible(true),它可以改变非final类型的所有属性,包括静态的,唯独final类型是改变不了的,如果要改变final类型需要下面的这种方式
Class c = Person.class;
Object object = c.getDeclaredConstructor().newInstance();
Field field = c.getDeclaredField("privatePersonNameFinal");//字段名
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(object, "123");//对象和赋值
注意:属性privatePersonNameFinal不能是基本类型,否则不会成功,如果不是基本类型就会成功,比如
private final String privatePersonNameFinal = new String("privatePersonNameFinal私有属性");
如果换成
private final String privatePersonNameFinal = "privatePersonNameFinal私有属性";
那么属性是改变不了的。
getModifiers()//获取修饰符
比如我要判断属性name是否是final类型
Field field = c.getDeclaredField("name");
System.out.println(Modifier.isFinal(field.getModifiers()));
调用方法
Class c = Person.class;
Object object = c.getDeclaredConstructor().newInstance();
Method m = c.getDeclaredMethod("pWorkStatic", String.class);//方法名和参数类型
m.setAccessible(true);//如果方法是私有的需要添加
m.invoke(object, "789");//对象和传参。如果是static,这里的object可以为null
获取泛型的类型
比如一个类
public class Person extends Father<String, List>
我们可以获取它的类型
Type type = c.getGenericSuperclass();
System.out.println(type);
ParameterizedType p = (ParameterizedType) type;
Class c1 = (Class) p.getActualTypeArguments()[0];
Class c2 = (Class) p.getActualTypeArguments()[1];
System.out.println(c1);
System.out.println(c2);
结果为
com.wld.java.blogs.reflect.Father<java.lang.String, java.util.List> //前面com.wld.java.blogs.reflect是包名
class java.lang.String
interface java.util.List
这个可以根据它的类型来初始化,android开发中还是比较常用的,比如MVP中使用泛型的时候。
public static <T> T getT(Object o, int i) {
Type type = o.getClass().getGenericSuperclass();
if (type!=null){
if (type instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) type;
Class<T> params = (Class<T>) parameterizedType.getActualTypeArguments()[i];
if (params!=null){
try {
return params.newInstance();
} catch (InstantiationException e) {
Logger.e(e.toString());
} catch (IllegalAccessException e) {
Logger.e(e.toString());
}
}
}
}
return null;
}