反射包: java.lang.reflect
Type接口
Java 中所有类型的父接口(也是 Class 类的父接口);
public interface Type{
default String getTypeName(){
return toString();
}
}
Type 接口的子接口:
- ParameterizedType # 参数化类型(泛型);
- GenericArrayType # 数组类型;
- TypeVariable # 类型变量;
ParameterizedType 接口介绍
public interface ParameterizedType extends Type{
//获取<> 中所有的泛型类型;Map<string,Integer> --> java.lang.String;java.lang.Integer
Type[] getActualTypeArguments();
//获取变量类型;List<String> --> java.util.List
Type getRawType();
//Map.Entry<Long,Short> mp3 --> java.util.Map; O<T>.I<S> --> O<T>
Type getOwnerType();
}
//例 f.getGenericType() instanceof ParameterizedType
Field[] fields = ParameterizedBean.class.getDeclaredFields();
for(Field f : fields){
if(f.getGenericType() instanceof ParameterizedType ){
ParameterizedType pType = (ParameterizedType)f.getGenericType();
pType.getTypeName();
Type[] types = pType.getActualTypeArguments();
//Type 可以强转为 Class
//Class c = (Class)types[0]
for(Type t : types){
t.getTypeName()
}
}
}
Class类
public final class Class{}
1、类本身也是一种类型;
2、class是由JVM在执行过程中动态加载的,每加载一种class,JVM就为其创建一个 Class类型的实例;
3、JVM为每个加载的 class 及 interface创建了对应的Class实例,来保存 class 及 interface 的所有信息;
name、package、super、interface、field、method;
4、JVM 总是动态加载 class,可以在运行期根据条件来控制加载 class;
5、通过 Class 实例获取 class 信息的方法称为反射(Reflection);
获取一个class的Class实例有三种方式
- Class cls = String.class;
- String s = “hello”; Class cls = s.getClass();
- Class.forName(“java.lang.String”) # 全类名;
Class实例的常用方法:
- cls.getName() # 获取全类名;
- cls.getSimpleName() # 类名;
- cls.getPackage().getName() # 包名;
- Type getGenericSuperclass() # 返回直接父类(包含泛型参数);
- isInterface();
- isEnum();
- isArray();
- isPrimitive();
注意:数组也是一种类,类名是: [Ljava.lang.String
“[” : 表示一维数组;
“[[” : 表示二维数组;
“L” :表示一个对象;
通过 Class 实例,创建对应类型:
Class cls = String.class;
String s = (String) cls.newInstance();
局限:只能调用 public 的无参构造方法;
Field
访问字段:
1.Field getField(name) : 根据字段名获取某个 public 的field(包括父类);
2、Field getDeclaredField(name) : 根据字段名获取当前类的某个 Field(不包括父类,可以获取private属性)
3、Field[] getFields() : 获取所有 public 的 field(含父类);
4、Field[] getDeclaredFields() : 获取当前类的所有 filed (不包括父类);
Field对象包含的信息:
1、Object get(Object obj) : Returns the value of the field represented by this Field, on the specified object.
例:
Object p = new Person("ming");
Class cls = p.getClass(); // 等价于 Person.class
Field f = cls.getDeclaredField("name");
// 注意:private 字段无法访问,get之前需要先: f.setAccessible(true);
Object value = f.get(p);
2、getName() :返回字段名称;
3、getType() : 返回字段类型, 一个 Class 实例;
4、getAnnotation(xxx.class) : 获取 xxx 注解;
5、Type getGenericType() # 字段类型(能正确表示出泛型) java.util.List<java.lang.String> ,ParameterizedType的实例;
6、field.set(Object,Object) # 设置字段值:(指定的实例,待修改的值);
7、getModifiers() : 字段修饰符,是一个 int;
int m = f.getModifiers();
Modifiers.isFinal(m); // true
Modifier.isPublic(m); //fasle
Modifier.isProtected(m)
Modifier.isPrivate(m)
Modifier.isStatic(m)
Method
通过 Class 获取 Method:
Method getMethod(name,Class…) # 获取某个 public 的 Method(包括父类);
Method getDeclaredMethod(name,Class…) # 获取当前类的某个 Method(不包括父类);
Method[] getMethods() # 获取所有 public 的Method(包括父类);
Method[] getDeclaredMethods() # 获取当前类的所有Method(不包括父类);
System.out.println(stdClass.getDeclaredMethod("getGrade",int.class));
# private int Student.getGrade(int)
Method 对象包含一个方法的所有信息
getName() : 返回方法名称;
getReturnType() : 返回方法的返回值类型,一个 Class 实例;
Type getGenericReturnType() :
getParameterTypes() : 返回方法的参数类型,是一个 Class 数组
getParameterAnnotations() : 返回方法参数的所有注解,是一个Annotation[][]
getMdifiers() :
方法的调用
Object invoke(Object instance , Object… parameters);
//例:
String s = "hello World";
Method m = String.class.getMethod("subString", int.class);
String r = (String)m.invoke(s,6);
调用静态方法:
如果获取到的 Method 表示一个静态方法,调用静态方法时,由于无需指定实例对象,invoke 方法传入的第一个参数永远为 null;
//以 Integer.parseInt(String)为例
Method m = Integer.class.getMethod("parseInt",String.class);
Integer n = (Integer)m.invoke(null,"1234");
调用非public方法
通过 Class.getDeclaredMethod() 获取该方法实例;
通过 Method.setAccessible(true) 允许其调用;
使用反射调用方法时,仍然遵循多态原则:
即总是调用实际类型的复写方法(如果存在);
//获取 Person 的 hello 方法;
Method h = Person.class.getMethod("hello");
//对 Student 实例调用 hello 方法;
h.invoke(new Stdent());
构造方法
通过 Class 实例获取 Constructor 的方法:
getConstructor(Class…) # 获取某个 public 的 Constructor;
getDeclaredConstructor(Class…) # 获取某个 Constructor;
getConstructors() # 获取所有 public 的Constructor;
getDeclaredConstructors() # 获取所有 Constructor;
Person.class.newInstance() <==> Person p = new Person();
例:
//获取构造方法 Integer(int);
Constructor cons1 = Integer.class.getConstructor(int.class);
//调用构造方法
Integer n1 = (Integer)cons1.newInstance(123);
调用非 public 的 Constructor 时,必须首先通过 setAccessible(true) 设置允许访问;
获取继承关系
Class 对象 <==> 一个类的类型;
获取父类的Class:
Class<? super Integer> Integer.class**.getSuperclass();** // 没有显示泛型参数,返回父类的Class
Type Integer.class.getGenericSuperclass(); //包含泛型参数,返回父类的 Type;
注:如果此 Class 表示 Object 类、一个接口、一个基本类型 或 void,则返回 null;
获取 interface
Class[] is = Integer.class.getInterfaces();
注意:只返回当前类直接实现的接口类型,并不包括其父类实现的接口类型;
通过 Class 对象的 isAssignableFrom() 方法可以判断一个向上转型是否可以实现;
例:
Number.class.isAssignableFrom(Integer.class); // true , 因为 Integer 可以赋值给Number;