Java反射API

反射包: 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实例有三种方式

  1. Class cls = String.class;
  2. String s = “hello”; Class cls = s.getClass();
  3. Class.forName(“java.lang.String”) # 全类名;

Class实例的常用方法:

  1. cls.getName() # 获取全类名;
  2. cls.getSimpleName() # 类名;
  3. cls.getPackage().getName() # 包名;
  4. Type getGenericSuperclass() # 返回直接父类(包含泛型参数);
  5. isInterface();
  6. isEnum();
  7. isArray();
  8. 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;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值