Java语法进阶15-反射

反射

类加载

类在内存中的生命周期:加载-->使用-->卸载java

当程序主动使用某个类时,若是该类还未被加载到内存中,系统会经过加载、链接、初始化三个步骤来对该类进行初始化程序员

类的加载又分为三个阶段:数组

(1)加载:loadui

就是指将类型的class字节码数据读入内存编码

(2)链接:linkspa

  ①验证:校验合法性等code

  ②准备:准备对应的内存(方法区),建立Class对象,为类变量赋默认值,为静态常量赋初始值。component

  ③解析:把字节码中的符号引用替换为对应的直接地址引用对象

(3)初始化:initialize(类初始化)即执行<clinit>类初始化方法,大多数状况下,类的加载就完成了类的初始化,有些状况下,会延迟类的初始化。blog

类初始化

一、哪些操做会致使类的初始化?

(1)运行主方法所在的类,要先完成类初始化,再执行main方法

(2)第一次使用某个类型就是在new它的对象,此时这个类没有初始化的话,先完成类初始化再作实例初始化

(3)调用某个类的静态成员(类变量和类方法),此时这个类没有初始化的话,先完成类初始化

(4)子类初始化时,发现它的父类尚未初始化的话,那么先初始化父类

(5)经过反射操做某个类时,若是这个类没有初始化,也会致使该类先初始化

二、哪些使用类的操做,可是不会致使类的初始化?

(1)使用某个类的静态的常量(static final)

(2)经过子类调用父类的静态变量,静态方法,只会致使父类初始化,不会致使子类初始化。

(3)用某个类型声明数组并建立数组对象时,不会致使这个类初始化

类加载器

(1)引导类加载器(Bootstrap Classloader)又称为根类加载器

   它负责加载jre/rt.jar核心库,它自己不是Java代码实现的,也不是ClassLoader的子类,获取它的对象时每每返回null

(2)扩展类加载器(Extension ClassLoader)

  它负责加载jre/lib/ext扩展库,它是ClassLoader的子类

(3)应用程序类加载器(Application Classloader)

    它负责加载项目的classpath路径下的类,它是ClassLoader的子类

(4)自定义类加载器

  当你的程序须要加载“特定”目录下的类,能够自定义类加载器;

加载器的双亲委托模式

 下一级的类加载器,若是接到任务时,会先搜索是否加载过,若是没有,会先把任务往上传,若是都没有加载过,一直到根加载器,若是根加载器在它负责的路径下没有找到,会往回传,若是一路回传到最后一级都没有找到,那么会报ClassNotFoundException或NoClassDefError

 类加载器之间不是继承关系,是组合的方式实现的。

Class

 Java反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;

简单理解为JVM运行时会在方法区记录全部class文件中全部类的信息(类名,属性,方法),并将全部类又作为Class类的对象。当调用某个类时就会将其先加载到内存中,

也就是将这个类做为Class类的对象被建立出来。在Class类中定义了许多供操做(此类)的方法(建立对象,调用属性和方法),从而能够动态的修改程序结构

Class对象是反射的根源,全部Java类型均可以获取它的类型对象。

Class 类的对象是在加载类时由 Java 虚拟机以及经过调用类加载器中的 defineClass方法自动构造,在方法区建立的,不是由程序员建立的,Class 没有公共构造方法。

获取Class对象的四种方式

(1)类型名.class

要求编译期间已知类型

(2)对象.getClass()

获取对象的运行时类型

(3)Class.forName(类型全名称)

能够获取编译期间未知的类型

(4)ClassLoader的类加载器对象.loadClass(类型全名称)

能够用系统类加载对象或自定义加载器对象加载指定路径下的类型

获取类型的详细信息

能够获取:包、修饰符、类型名、父类(包括泛型父类)、父接口(包括泛型父接口)、成员(属性、构造器、方法)、注解(类上的、方法上的、属性上的)

public ClassLoader getClassLoader() 【返回该类的类加载器】
public String toString() 【将对象转换为字符串】
public Package getPackage() 【获取此类的包】
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException 【返回此 Class 对象表示的类声明的全部构造方法】
public native int getModifiers();

【 返回此类或接口以整数编码的 Java 语言修饰符,用二进制的某一位1,来表明一种修饰符】

public String getName()

【以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称】

public native Class<? super T> getSuperclass();

【返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class】

public Type getGenericSuperclass()

【返回此 Class 所表示的实体(类、接口、基本类型或 void)

直接超类的 Type】

public Class<?>[] getInterfaces() 【肯定此对象所表示的类或接口实现的接口】
public Field getField(String name) 【返回此 Class 对象所表示的类或接口的指定公共成员字段】
public Field[] getFields() throws SecurityException 【返回此 Class 对象所表示的类或接口的全部可访问公共字段】
public Field getDeclaredField(String name) 【返回此 Class 对象所表示的类或接口的指定已声明字段】
public Field[] getDeclaredFields() throws SecurityException 【返回此 Class 对象所表示的类或接口所声明的全部字段】
public Method getMethod(String name, Class<?>... parameterTypes) 【返回此 Class 对象所表示的类或接口的指定公共成员方法】
public Method[] getMethods() throws SecurityException

【返回此 Class 对象所表示的类或接口(包括那些由该类或接口

声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法】

public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 【返回此 Class 对象所表示的类或接口的指定已声明方法】
public Method[] getDeclaredMethods() throws SecurityException

【此 Class 对象表示的类或接口声明的全部方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法】

public T newInstance() 【建立此 Class 对象所表示的类的一个新实例】
public Annotation[] getAnnotations() 【返回此元素上存在的全部注释】
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) 【若是存在该元素的指定类型的注释,则返回这些注释,不然返回 null】
public T[] getEnumConstants() 【若是此 Class 对象不表示枚举类型,则返回枚举类的元素或 null】
public boolean isMemberClass() 【当且仅当底层类是成员类时返回 true】
public native boolean isInterface(); 【断定指定的 Class 对象是否表示一个接口类型】

建立任意引用类型的对象

一、直接经过Class对象来实例化(要求必须有无参构造)

  • (1)获取该类型的Class对象(2)建立对象 newInstance()

二、经过获取构造器对象来进行实例化

  • (1)获取该类型的Class对象(2)获取构造器对象(3)建立对象 newInstance(Object... initargs)

若是构造器的权限修饰符修饰的范围不可见,也能够调用setAccessible(true)

操做任意类型的属性

(1)获取该类型的Class对象

Class clazz = Class.forName("com.guigu.bean.User");

(2)获取属性对象

Field field = clazz.getDeclaredField("username");

(3)设置属性可访问

field.setAccessible(true);

(4)建立实例对象:若是操做的是非静态属性,须要建立实例对象

Object obj = clazz.newInstance();

(4)设置属性值

field.set(obj,"chai");

(5)获取属性值 Object value = field.get(obj);

若是操做静态属性变量,那么实例对象能够省略,用null表示

调用任意类型的方法

(1)获取该类型的Class对象

Class clazz = Class.forName("com.atguigu.service.UserService");

(2)获取方法对象

Method method = clazz.getDeclaredMethod("login",String.class,String.class);

(3)建立实例对象

Object obj = clazz.newInstance();

(4)调用方法

Object result = method.invoke(obj,"chai","123);

若是方法的权限修饰符修饰的范围不可见,也能够调用setAccessible(true)

若是方法是静态方法,实例对象也能够省略,用null代替

获取泛型父类

一、获取子类的Class对象

二、调用getGenericSuperClass()获取泛型父类

三、强转为ParameterizedType类型

四、调用getActualTypeArguments()获取实际类型参数

读取注解信息

获取上的注解:

一、获取Class对象

二、调用getAnnotation()方法获得注解对象

三、调用注解对象的配置参数的方法获取配置参数值

获取属性上的注解:

一、获取Class对象

二、获取某个属性Field对象

三、调用getAnnot ation()方法获得注解对象

四、调用注解对象的配置参数的方法获取配置参数值

获取方法上的注解:

一、获取Class对象

二、获取某个方法method对象

三、调用getAnnot ation()方法获得注解对象

四、调用注解对象的配置参数的方法获取配置参数值

获取内部类或外部类信息

public Class<?>[] getClasses():  

【返回全部公共内部类和内部接口。包括从超类继承的公共类和接口成员以及该类声明的公共类和接口成员。】

public Class<?>[] getDeclaredClasses():

【返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的全部类和接口。包括该类所声明的公共、保护、默认(包)访问及私有类和接口,但不包括继承的类和接口】 

public Class<?> getDeclaringClass(): 

【若是此 Class 对象所表示的类或接口是一个内部类或内部接口,则返回它的外部类或外部接口,不然返回null。】 

动态建立和操做任意类型的数组

java.lang.reflect包下还提供了一个Array类,Array对象能够表明全部的数组。程序能够经过使用Array类来动态的建立数组,操做数组元素等。

Array类提供了以下几个方法:

public static Object newInstance(Class<?> componentType, int... dimensions):

【建立一个具备指定的组件类型和维度的新数组。】

public static void setXxx(Object array,int index,xxx value):

【将array数组中[index]元素的值修改成value。此处的Xxx对应8种基本数据类型,若是该属性的类型是引用数据类型,则直接使用set(Object array,int index, Object value)方法。】

public static xxx getXxx(Object array,int index,xxx value):

【将array数组中[index]元素的值返回。此处的Xxx对应8种基本数据类型,若是该属性的类型是引用数据类型,则直接使用get(Object array,int index)方法。】

Field

String getName() 返回此 Field 对象表示的字段的名称
Object get(Object obj) 返回指定对象上此 Field 表示的字段的值
int getModifiers() 以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符
boolean equals(Object obj) 将此 Field 与指定对象比较
Type getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型
boolean getBoolean(Object obj) 获取一个静态或实例 boolean 字段的值
int getInt(Object obj) 获取 int 类型或另外一个经过扩辗转换能够转换为 int 类型的基本类型的静态或实例字段的值
void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值
void setShort(Object obj, short s) 将字段的值设置为指定对象上的一个 short 值
void setInt(Object obj, int i) 将字段的值设置为指定对象上的一个 int 值

Method

boolean equals(Object obj) 将此 Method 与指定对象进行比较
String getName() 以 String 形式返回此 Method 对象表示的方法名称
Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法
Class<?> getReturnType() 返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型
Class<?>[] getParameterTypes() 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型
int getModifiers() 以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符
Type getGenericReturnType() 返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象
Type[] getGenericParameterTypes() 返回一个 Type对象的数组, Type以声明顺序表示由该对象表示的可执行文件的形式参数类型
Type[] getGenericExceptionTypes() 返回一个 Type对象的数组, Type此可执行对象声明抛出的异常
Class<?>[] getExceptionTypes() 返回 Class 对象的数组,这些对象描述了声明将此 Method 对象表示的底层方法抛出的异常类型
Class<?> getDeclaringClass() 返回表示声明由此 Method 对象表示的方法的类或接口的 Class 对象
Annotation[] getDeclaredAnnotations() 返回直接存在于此元素上的全部注释

Constructor

boolean equals(Object obj) 将此 Constructor 对象与指定的对象进行比较
String getName() 以字符串形式返回此构造方法的名称
Class<T> getDeclaringClass() 返回 Class 对象,该对象表示声明由此 Constructor 对象表示的构造方法的类
int getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符
T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来建立该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型
Type[] getGenericParameterTypes() 按照声明顺序返回一组 Type 对象,这些对象表示此 Constructor 对象所表示的方法的形参类型
相关文章
相关标签/搜索