三. 重识Java之夯实反射

不忘初心 砥砺前行, Tomorrow Is Another Day !java

相关文章

引言

本文概要:数组

  1. 类的生命周期
  2. 基本类周边信息的获取
  3. 泛型类周边信息的获取
  4. 类内部信息获取

一. 类的生命周期

  1. 编译:生成Class相关文件
  2. 运行
    • 装载 - 连接 - 初始化
  • 装载: 类的装载是经过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,而且在堆区建立描述这个类的java.lang.Class对象。用来封装数据。 可是同一个类只会被类装载器装载一次,重要的话:类只装载一次
  • 连接: 连接就是把二进制数据组装为能够运行的状态。连接分为校验,准备,解析这3个阶段。校验通常用来确认此二进制文件是否适合当前的JVM(版本),准备就是为静态成员分配内存空间,并设置默认值。解析指的是转换常量池中的代码做为直接引用的过程,直到全部的符号引用均可以被运行程序使用(创建完整的对应关系)。
  • 初始化:初始化就是对类中的变量进行初始化值;完成以后,类型也就完成了初始化,初始化以后类的对象就能够正常使用了,直到一个对象再也不使用以后,将被垃圾回收。释放空间。 当没有任何引用指向Class对象时就会被卸载,结束类的生命周期。若是再次用到就再从新开始装载、连接和初始化的过程。

以上内容摘抄自 blog.csdn.net/harvic88092…bash

对于上述一大段理论,咱们就记住最重要标黑部分.下面开始来学习反射.函数

获取类类型

使用示例post

/**
     * 获取类类型的四种方式
     */
   private void getClassObjectMethod() throws ClassNotFoundException {
       Person person = new Person();
       Class<?> clazz1 = Person.class;
       Class<?> clazz2 = person.getClass();
       Class<?> clazz3 = Class.forName("reflectionDemo.bean.Person");
       Class<?> clazz4 = getClass().getClassLoader().loadClass("reflectionDemo.bean.Person");
       boolean result = (clazz1 == clazz2 && clazz3 == clazz4 && clazz1 == clazz3);
       System.out.println(result);
    }
复制代码

Class.forName与ClassLoader.loadClass区别学习

  • Class.forName(String className)不只会将类加载进来,并且会对其进行初始化,而ClassLoader.loadClass(String ClassName)则只是将类加载进来,而没有对类进行初始化
  • 通常来说,他们两个是通用的,但若是你加载类依赖初始化值的话,那ClassLoader.loadClass(String ClassName)将再也不适用!

二. 基本类周边信息的获取相关API

//获取类类型对象的几种方式:
Person person = new Person();  
Class a = person.getClass() //方法一
Class b = Persion.class;//方法二
Class c = Class.forName(String ClassName); //方法三
Class d = context.getClassLoader().loadClass(String ClassName);//方法四:(不建议使用)
 
//获取包名类名
public String getName();//获取完整的类名(包含包名)
public String getSimpleName();//仅获取类名
public Package getPackage()//获取类类型所对应的package对象
 
//获取超类Class对象
public Class<?> getSuperclass();//获取普通父类Class对象(不越级,仅直接继承的类)
public Type getGenericSuperclass();//获取泛型父类Type对象(见下篇)
 
//获取接口Class对象
public Class<?>[] getInterfaces();//获取普通接口的Class对象(不越级,仅直接实现的直接)
public Type[] getGenericInterfaces();//获取泛型接口的Type(见下篇)
 
//类访问修饰符
int modifiers = clazz.getModifiers();//获取类访问修饰符对应的int变量
String Modifier.toString(int modifiers) //根据整型变量来生成对应的修饰符字符串
boolean Modifier.isAbstract(int modifiers)//isXXX()系列函数用以检查特定的修饰符是否存在
复制代码



三. 泛型类周边信息的获取相关API

了解泛型类周边信息获取,须要先了解下Type相关的知识.接下来看Type.ui

//获取泛型超类的Type
public Type getGenericSuperclass();
//获取泛型接口的Type
public Type[] getGenericInterfaces();

复制代码

3.1 Type

Type的派生类:spa

  • Class
  • ParameterizedType,表明的是泛型类型形式的
  • TypeVariable,表明的是泛型变量形式的
  • GenericArrayType,表明的是数组形式的
    • 强调第一次:若是type对应的是表达式是ArrayList这种的,这个type类型应该是ParameterizedType,而不是GenericArrayType,只有相似Integer[]这种的才是GenericArrayType类型。
  • WildcardType,表明的是通配符形式的
  • 小结.
    1. 当Type值表明的是完整的泛型表达式,好比:Point<...>,那它对应的类型就是ParameterizedType.
    2. 当Type值表明的是一个肯定的类,好比:Integer,String,Double等,那它所对应的类型就是Class;
    3. 当Type值表明的仅仅是Point中用来填充泛型变量T(暂未填充值时),那它所对应的类型就是TypeVariable.
    4. 当Type值表明的是一个String[]、Interge[]等数组时,那它对应的类型就是GenericArrayType.
    5. 当type所表明的是一个是通配符相关的表达式时?,那它对应的类型就是WildcardType.
3.1.1 ParameterizedType相关API
//获取填充泛型变量的真实参数列表
Type[] getActualTypeArguments();
//获取声明此当前泛型表达式的类或接口的Class对象
Type getRawType();

复制代码

继承Type接口只有下面五个:.net

  • Class
  • ParameterizedType
  • TypeVariable
  • WildcardType
  • GenericArrayType
    因此这也是Type[ ] getActualTypeArguments()方法中Type[]数组的全部可能取值.
3.1.2 TypeVariable相关
//就是获得当前泛型变量的名称;
String  getName();
//返回表示此类型变量上边界的 Type 对象的数组。若是没有上边界,则默认返回Object;
//上边界的意思就是extends关键字后面的限定条件。
Type[]  getBounds();

复制代码
3.1.3 GenericArrayType相关

强调第二次,若是type值对应的是相似于ArrayList、List这样的类型,那type的类型应该是ParameterizedType,而不是GenericArrayType,因此当且仅当type对应的类型是相似于String[]、Integer[]这样的数组时,type的类型才是GenericArrayTypecode

//获取实际数组值所对应的Type,通常获取到后进行强制转换成Class
Type getGenericComponentType();

复制代码
3.1.4 WildcardType相关

当type所表明的表达式是类型通配符相关的表达式时,好比,,或者等,这个type的类型就是WildcardType!

//获取通配符的上边界对象列表
//上边界就是使用extends关键定所作的的限定,若是没有默认是Object
Type[] getUpperBounds();
//获取通配符的下边界对象列表
//下边界是指使用super关键字所作的限定,若是没有,则为Null
Type[] getLowerBounds();

复制代码
3.1.4.1 通配符的使用范围

再次重复一次有关通配符的知识,具体见[夯实泛型]

  • 通配符只是泛型变量的填充类型的一种,不能作为泛型变量使用
  • 通配符只能用来在生成泛型实例时使用,如Box<?> box;中,其它位置都是不对的.
3.1.4.2 通用类型转换函数
private void parseClass(Class<?> c){
    parseTypeParameters(c.getGenericInterfaces());
}

private void parseTypeParameters(Type[] types){
    for(Type type:types){
        parseTypeParameter(type);
    }
}

private void parseTypeParameter(Type type){
    if(type instanceof Class){
        Class<?> c = (Class<?>) type;
        Log.d(TAG, c.getSimpleName());
    } else if(type instanceof TypeVariable){
        TypeVariable<?> tv = (TypeVariable<?>)type;
        Log.d(TAG, tv.getName());
        parseTypeParameters(tv.getBounds());
    } else if(type instanceof WildcardType){
        WildcardType wt = (WildcardType)type;
        Log.d(TAG, "?");
        parseTypeParameters(wt.getUpperBounds());
        parseTypeParameters(wt.getLowerBounds());
    } else if(type instanceof ParameterizedType){
        ParameterizedType pt = (ParameterizedType)type;
        Type t = pt.getOwnerType();
        if(t != null) {
            parseTypeParameter(t);
        }
        parseTypeParameter(pt.getRawType());
        parseTypeParameters(pt.getActualTypeArguments());
    } else if (type instanceof GenericArrayType){
        GenericArrayType arrayType = (GenericArrayType)type;
        Type t = arrayType.getGenericComponentType();
        parseTypeParameter(t);
    }
复制代码



四. 类内部信息获取

4.1 获取构造函数Constructor相关API

void setAccessible(boolean flag),它表明的含义是,是否将任何函数或字段设置为可访问的。若是设置为true,就无论这个函数或者字段是声明为private仍是public,都是能够访问的,默认状况下是false,即只有public类型是可访问的

/**
* 1. 获取构造函数Constructor
*/
//获取public类型的构造函数
Constructor<?>[] getConstructors();
Constructor<T> getConstructor(Class<?>... parameterTypes);//根据参数类型,获取指定的构造的构造函数,属于精确匹配,参数声明顺序、类型及个数要彻底匹配.
//获取全部类型的构造函数
Constructor<?>[] getDeclaredConstructors();
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)//同上
 
/*
* 2. Constructor之获取对应类的实例
× @params args 传入的参数类型、顺序及个数都必须与当前的Constructor对象一一对应
*/
public T newInstance(Object... args);
 
/**
* 3. Constructor之获取参数类型
*/
//用于解析通常函数
Class<?>[] getParameterTypes();
//用于解析泛型对象
Type[] getGenericParameterTypes();
 
 
/***公有的***/ 
// Constructor之获取访问修饰符
int getModifiers()
//获取声明Constructor的类Class对象;
Class<T> getDeclaringClass()
复制代码
4.2 获取成员变量Field相关API
/**
* 1. 获取Field对象
*/
//获取public类型的成员变量
Field[] getFields();
Field getField(String name);//根据变量名,获取对应的Field对象
//获取全部类型的成员变量
Field[] getDeclaredFields();
Field getDeclaredField(String name)//同上
 
/**
* 2. get,set方法系列
* 当获取或设置指定类对象中某变量的值
*/
//object:要设置的类对象(类实例),value:是此Field对象所对应的值
void set(Object object, Object value)
//object:要获取值的类的对象,返回值Object为:在此类的实例中,对应成员变量的值
Object get(Object object)

/**
 × 3. 针对基本数据类型
 ×/
//设置与获取int类型的值
void setInt(Object object, int value)
int getInt(Object object)
//设置与获取double类型的值
void setDouble(Object object, double value)
double getDouble(Object object)
//设置与获取float类型的值
void setFloat(Object object, float value)
float getFloat(Object object)
//设置与获取bool类型的值
void setBoolean(Object object, boolean value)
boolean getBoolean(Object object)
//设置与获取short类型的值
void setShort(Object object, short value)
short getShort(Object object)
//设置与获取long类型的值
void setLong(Object object, long value)
long getLong(Object object)
//设置与获取byte类型的值
void setByte(Object object, byte value)
byte getByte(Object object)
//设置与获取char类型的值
void setChar(Object object, char value)
char getChar(Object object)
 
/**
* 4. 判断当前field是否为枚举常量;
*/
boolean isEnumConstant()

/***公有的***/
//获取访问修饰符
int getModifiers()
//获取声明该Field的类class对象
Class<?> getDeclaringClass()
复制代码
4.3 获取成员方法相关API
/*
* 1. 获取指定类中的成员函数Method对象
*/
//获取public的成员函数
Method[] getMethods()
Method getMethod(String name, Class<?>... parameterTypes)//name为方法名,parameterTypes为参数类型,精确匹配
//获取全部类型成员函数
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, Class<?>... parameterTypes)//同上

/*
* 2. 执行某个方法
× @params receicer: 指要执行该函数的类对象(类实例),好比咱们的Person类的某一实例
* @params args: 用于传入该函数声明中的参数所对应的值的列表
* @return Object: 将函数的结果返回,Object对象就是执行此函数后返回的结果
*/
Object invoke(Object receiver, Object... args)
 
/**
* 3. 获取参数类型
*/
Class<?>[] getParameterTypes()
Type[] getGenericParameterTypes()
 
/**
* 4. 获取返回值类型
*/
Class<?> getReturnType()
Type getGenericReturnType()

复制代码

因为本人技术有限,若有错误的地方,麻烦你们给我提出来,本人不胜感激,你们一块儿学习进步.

为方便往后查找,本文只记载了重难点知识API使用,如需详细了解学习.敬请参考,这里感谢原做者启舰的博客对本人的帮助.

相关文章
相关标签/搜索