疯狂-反射
2017-08-14 22:34:43 59 举报
AI智能生成
疯狂java讲义,反射这一章内容,看开源框架,反射肯定有,需要系统的学习
作者其他创作
大纲/内容
类的加载、连接和初始化
JVM和类
当系统出现以下情况JVM将终止:
1,程序运行到最后正常结束
2,System.exit()或Runtime.getRuntime().exit()
3,程序执行中,遇到未捕获的异常或错误
4,程序所在平台强制结束JVM进程
1,程序运行到最后正常结束
2,System.exit()或Runtime.getRuntime().exit()
3,程序执行中,遇到未捕获的异常或错误
4,程序所在平台强制结束JVM进程
类的加载
系统会通过加载、连接、初始化三个步骤对类进行初始化。
类加载: 将类的class文件读入内存,并创建一个java.lang.Class对象。
类加载: 将类的class文件读入内存,并创建一个java.lang.Class对象。
类的加载是由类加载器完成的,JVM提供的这些类加载器被叫做类加载器。开发者也可以继承ClassLoader基类来创建自己的类加载器。
可以从以下来源加载类的二进制数据:
1,从本地文件系统加载class文件。
2,从JAR包加载class文件
3,通过网络加载class文件
4,将java源文件动态编译,并执行加载
java虚拟机规范允许系统与现在加某些类,而并不一定等到“首次使用”时才加载
可以从以下来源加载类的二进制数据:
1,从本地文件系统加载class文件。
2,从JAR包加载class文件
3,通过网络加载class文件
4,将java源文件动态编译,并执行加载
java虚拟机规范允许系统与现在加某些类,而并不一定等到“首次使用”时才加载
类的连接
当加载完类后,系统生成一个对应的Class文件,接着进入连接阶段,负责把类的二进制数据合并到JRE中。类连接分为如下三个阶段:
1,验证:校验加载的类是否有正确的结构,并和其他类协调一致
2,准备:负责为类的类变量分配内存,并设置默认初始值
3,解析:将类的二进制数据中的符号应用替换成直接引用
1,验证:校验加载的类是否有正确的结构,并和其他类协调一致
2,准备:负责为类的类变量分配内存,并设置默认初始值
3,解析:将类的二进制数据中的符号应用替换成直接引用
类的初始化
虚拟机负责对类进行初始化,主要就是对类变量进行初始化。在java类中对类变量指定初始值有两种方式:
1,申明类变量时指定初始值
2,使用静态初始化块为类变量指定初始化值
1,申明类变量时指定初始值
2,使用静态初始化块为类变量指定初始化值
JVM初始化一个类包含如下几个步骤
1,如果还没加载该类,则程序先加载并连接该类
2,如果该类的直接父类还没有被初始化,则先初始化其直接父类
3,如果该类中有初始化语句,则系统依次执行这些初始化语句
1,如果还没加载该类,则程序先加载并连接该类
2,如果该类的直接父类还没有被初始化,则先初始化其直接父类
3,如果该类中有初始化语句,则系统依次执行这些初始化语句
类初始化的时机
当首次通过下面的方式来使用某个类或接口时,系统就会初始化该类或接口
1,创建实例:new类、通过反射来创建、反序列化创建。
2,调用某个类的类方法(静态方法)
3,访问某个类或接口的类变量,或为该类变量赋值。
4,通过反射方式创建类或接口的java.lang.Class对象。
5,初始化某个类的子类
6,用java.exe命令运行某个主类
1,创建实例:new类、通过反射来创建、反序列化创建。
2,调用某个类的类方法(静态方法)
3,访问某个类或接口的类变量,或为该类变量赋值。
4,通过反射方式创建类或接口的java.lang.Class对象。
5,初始化某个类的子类
6,用java.exe命令运行某个主类
ClassLoader#loadClass()只是加载某个类,并不会初始化该类
Class#forName()会初始化该类。
Class#forName()会初始化该类。
类加载器
类加载器简介
在JVM中,用类的全包名作为唯一标识
在JVM启动时,会有三个类加载器:
1,Bootstrap ClassLoader : 根类加载器
2,Extension ClassLoader : 扩展类加载器
3,System ClassLoader : 系统类加载器
1,Bootstrap ClassLoader : 根类加载器
2,Extension ClassLoader : 扩展类加载器
3,System ClassLoader : 系统类加载器
Extension Classloader 被称为扩展类加载器,会加载扩展目录
(%JAVA_HOME%/jre/lib/ext 或由 java.ext.dirs系统属性指定的目录)
System Classloader系统类加载器,加载 java命令的 -classpath选项、
java.class.path系统属性或CLASSPATH环境变量所指定的JAR包和类路径
(%JAVA_HOME%/jre/lib/ext 或由 java.ext.dirs系统属性指定的目录)
System Classloader系统类加载器,加载 java命令的 -classpath选项、
java.class.path系统属性或CLASSPATH环境变量所指定的JAR包和类路径
类加载机制
1,全盘负责:当加载某个class时,该class所依赖的和引用的其他class也将由该类加载器负责载入,除非显示指定另外一个类加载器来载入。
2,父类委托:先让parent类加载器试图加载该class,只有父加载器无法加载该类时,才尝试从自己的类路径中加载该类。
3,缓存机制:加载过的class都会被缓存,当需要使用某个class时,先从缓存中搜寻该class,只有当缓存不命中时,才会读取二进制数据。
2,父类委托:先让parent类加载器试图加载该class,只有父加载器无法加载该类时,才尝试从自己的类路径中加载该类。
3,缓存机制:加载过的class都会被缓存,当需要使用某个class时,先从缓存中搜寻该class,只有当缓存不命中时,才会读取二进制数据。
类加载器加载class8个步骤:
1,检测该类是否加载过
2,
3,
4,
5,
6,
7,
8,
1,检测该类是否加载过
2,
3,
4,
5,
6,
7,
8,
创建并使用自定义的类加载器
ClassLoader包含两个关键方法:
loadClass(String name, boolean resolve):根据指定名称加载类
findClass(String name):根据指定名称来查找类
loadClass(String name, boolean resolve):根据指定名称加载类
findClass(String name):根据指定名称来查找类
loadClass执行步骤:
1,用findLoadedClass()检查是否已经加载类,如果已经加载则直接返回
2,调用父加载器的loadClass()方法,如果父类加载器为null,则直接用bootStarp加载器加载
3,调用findClass()方法
1,用findLoadedClass()检查是否已经加载类,如果已经加载则直接返回
2,调用父加载器的loadClass()方法,如果父类加载器为null,则直接用bootStarp加载器加载
3,调用findClass()方法
Class defineClass(String name, byte[] b, int off, int len) :
该方法负责将指定的class文件读入到字节数组byte[] b内,并转换成class对象。该字节码可以是网络文件,本地文件。
该方法负责将指定的class文件读入到字节数组byte[] b内,并转换成class对象。该字节码可以是网络文件,本地文件。
findSystemClass(String name):从本地文件系统装入文件,如果存在,就使用defineClass()
方法转换成Class对象。
static getSystemClassLoader(): 返回系统类加载器
getParent():获取该类加载的父类加载器
resolveClass(Class<?> c):链接指定的类
findLoadedClass(String name):返回已经加载的类
方法转换成Class对象。
static getSystemClassLoader(): 返回系统类加载器
getParent():获取该类加载的父类加载器
resolveClass(Class<?> c):链接指定的类
findLoadedClass(String name):返回已经加载的类
URLClassLoader类
URLClassLoader(URL[] urls) : 使用默认的父类加载器创建一个ClassLoader对象
URLClassLoader(URL[] urls, ClassLoader parent) : 使用指定的父类加载器创建一个
ClassLoader对象
URLClassLoader(URL[] urls, ClassLoader parent) : 使用指定的父类加载器创建一个
ClassLoader对象
loadClass执行步骤:
1,用findLoadedClass()检查是否已经加载类,如果已经加载则直接返回
2,调用父加载器的loadClass()方法,如果父类加载器为null,则直接用bootStarp加载器加载
3,调用findClass()方法
1,用findLoadedClass()检查是否已经加载类,如果已经加载则直接返回
2,调用父加载器的loadClass()方法,如果父类加载器为null,则直接用bootStarp加载器加载
3,调用findClass()方法
Class defineClass(String name, byte[] b, int off, int len) :
该方法负责将指定的class文件读入到字节数组byte[] b内,并转换成class对象。该字节码可以是网络文件,本地文件。
该方法负责将指定的class文件读入到字节数组byte[] b内,并转换成class对象。该字节码可以是网络文件,本地文件。
通过反射查看类信息
java许多对象都有两种类型:编译时类型和运行时类型
例如:
Person p = new Student();
p的编译时类型是Person,运行时类型是Student
程序需要运行时发现对象和类的真实信息。一般有一下两种做法:
1,如果在编译和运行时都知道类型的具体信息,可以先使用instanceof判断下,在强转
2,编译时不知道该对象和类可能属于哪些类,只能依靠运行时信息来发现该对象和类的真实信息,这就需要反射
例如:
Person p = new Student();
p的编译时类型是Person,运行时类型是Student
程序需要运行时发现对象和类的真实信息。一般有一下两种做法:
1,如果在编译和运行时都知道类型的具体信息,可以先使用instanceof判断下,在强转
2,编译时不知道该对象和类可能属于哪些类,只能依靠运行时信息来发现该对象和类的真实信息,这就需要反射
获得Class对象
获得Class对象的三种方法:
1,Class.forName( String clazzName) (必须是完整的包名)
2,类.class
3,对象.getClass()
1,Class.forName( String clazzName) (必须是完整的包名)
2,类.class
3,对象.getClass()
从Class中获取信息
获取构造函数:
Constructor<T> getConstructor(Class<?>...parameterTypes):
返回参数对应的public构造函数
Constructor<?>[] getConstructors():获得所有的public构造器
Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):
返回参数对应的构造函数
Constructor<?>getDeclaredConstructors():返回所有的构造函数
Constructor<T> getConstructor(Class<?>...parameterTypes):
返回参数对应的public构造函数
Constructor<?>[] getConstructors():获得所有的public构造器
Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):
返回参数对应的构造函数
Constructor<?>getDeclaredConstructors():返回所有的构造函数
获取函数:
Method getMethod(String name, Class<?>...parameterTypes):返回指定参数的public方法
Method[] getMethods(): 返回所有的public方法
Method getDeclaredMethod(String name, Class<?>...parameterTypes) : 获取指定参数的方法
Method[] getDeclaredMethods():获取所有的方法
Method getMethod(String name, Class<?>...parameterTypes):返回指定参数的public方法
Method[] getMethods(): 返回所有的public方法
Method getDeclaredMethod(String name, Class<?>...parameterTypes) : 获取指定参数的方法
Method[] getDeclaredMethods():获取所有的方法
获取成员变量:
Field getField(String name) : 获取指定名称的public字段
Field[] getFields(): 返回所有的public字段
Field getDeclaredField(String name) : 返回指定名称字段
Field[] getDeclaredFields() : 返回所有的字段
Field getField(String name) : 获取指定名称的public字段
Field[] getFields(): 返回所有的public字段
Field getDeclaredField(String name) : 返回指定名称字段
Field[] getDeclaredFields() : 返回所有的字段
获取注解:
<A extends Annotation> A getAnnotation(Class<A> annotationClass) :
获取指定的Annotation; 如果不存在,则返回null
<A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) :
获取指定的类Annotation
Annotation[] getAnnotations() : 返回修饰该Class对象对应类上存在的所有Annotations
Annotation[] getDeclaredAnnotations() : 返回所有的类Annotation
<A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) :
获取指定的类Annotation
<A extends Annotation> A[] getDeclaredAnnotationByType(Class<A> annotationClass) :
获取指定类型的多个类Annotation
<A extends Annotation> A getAnnotation(Class<A> annotationClass) :
获取指定的Annotation; 如果不存在,则返回null
<A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) :
获取指定的类Annotation
Annotation[] getAnnotations() : 返回修饰该Class对象对应类上存在的所有Annotations
Annotation[] getDeclaredAnnotations() : 返回所有的类Annotation
<A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) :
获取指定的类Annotation
<A extends Annotation> A[] getDeclaredAnnotationByType(Class<A> annotationClass) :
获取指定类型的多个类Annotation
获取内部类:
Class<?>[] getDeclaredClasses() : 返回包含的额全部内部类
获取外部类:
Class<?> getDeclaringClass() : 返回外部类
Class<?>[] getDeclaredClasses() : 返回包含的额全部内部类
获取外部类:
Class<?> getDeclaringClass() : 返回外部类
获取类实现的接口:
Class<?>[] getInterfaces() : 返回该类实现的所有接口
获取类所继承的父类
Class<? super T> getSuperclass() : 返回父类的Class对象
Class<?>[] getInterfaces() : 返回该类实现的所有接口
获取类所继承的父类
Class<? super T> getSuperclass() : 返回父类的Class对象
获取类的修饰符、所在包、类名等基本信息
int getModifiers():返回修饰符
Package getPackage() : 获取此类的包名
String getName() : 返回class的类名
String getSimpleName() : 返回class简称的类名
boolean isAnnotation():该class对象是否是注解(@interface)
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):该class对象是否使用了Annotation修饰
boolean isAnonymousClass():该class对象是否是一个匿名类
boolean isArray():该class对象是否表示一个数组类
boolean isEnum(): 该class对象是否表示一个枚举类
boolean isInterface():该class对象是否表示一个接口
boolean isInstance(Object obj): 判断obj是否是此Class对象的实例
int getModifiers():返回修饰符
Package getPackage() : 获取此类的包名
String getName() : 返回class的类名
String getSimpleName() : 返回class简称的类名
boolean isAnnotation():该class对象是否是注解(@interface)
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):该class对象是否使用了Annotation修饰
boolean isAnonymousClass():该class对象是否是一个匿名类
boolean isArray():该class对象是否表示一个数组类
boolean isEnum(): 该class对象是否表示一个枚举类
boolean isInterface():该class对象是否表示一个接口
boolean isInstance(Object obj): 判断obj是否是此Class对象的实例
8新增的方法参数反射
Executable 派生了 Constructor、method方法
int getParameterCount() : 获取构造器或方法的形参个数
Parameter[] getParameters() : 获取构造器或方法的所有形参
int getParameterCount() : 获取构造器或方法的形参个数
Parameter[] getParameters() : 获取构造器或方法的所有形参
Parameter是8新增的,代表方法或构造器的一个参数
getModifiers() : 获取修饰符
String getName() : 获取形参名
Type getParameterizedType() : 获取带泛型的形参类型
Class<?> getType() : 获取形参类型
boolean isNamePresent() : class文件是否包含了方法的形参名信息
boolean isVarArgs() : 返回该参数是否是个数可变的形参
ps : 使用javac命令编译的java源文件,生成的Class文件不包含方法的形参名信息,
javac -parameters 源文件名 : 生成的Class文件则包含方法的形参信息
getModifiers() : 获取修饰符
String getName() : 获取形参名
Type getParameterizedType() : 获取带泛型的形参类型
Class<?> getType() : 获取形参类型
boolean isNamePresent() : class文件是否包含了方法的形参名信息
boolean isVarArgs() : 返回该参数是否是个数可变的形参
ps : 使用javac命令编译的java源文件,生成的Class文件不包含方法的形参名信息,
javac -parameters 源文件名 : 生成的Class文件则包含方法的形参信息
使用反射生成并操作对象
创建对象
通过反射创建对象的两种方法:
1, Class.newInstance()
2, 获取Constructor对象,constructor.newInstance();
1, Class.newInstance()
2, 获取Constructor对象,constructor.newInstance();
调用方法
Object invoke(Object obj, Object... args) : obj形参是执行该方法的主调,args是执行该方法时传入该方法的实参
访问成员变量值
getXxx(Object obj) : 获取obj对象的该成员变量的值。Xxx对应8种基本类型,如果该成员变量的类型是引用类型,则不需要Xxx。
setXxx(Object obj, Xxx val) : 将obj对象的该成员变量设置为val的值。Xxx对应8种基本类型,如果该成员变量的类型是引用类型,则不需要Xxx。
访问private的成员变量需要设置field.setAccessible(true);
setXxx(Object obj, Xxx val) : 将obj对象的该成员变量设置为val的值。Xxx对应8种基本类型,如果该成员变量的类型是引用类型,则不需要Xxx。
访问private的成员变量需要设置field.setAccessible(true);
操作数组
Array类提供了如下几个方法:
static Object newInstance(Class<?> componentType, int ... length) :
创建一个指定元素类型、指定维度的新数组
static xxx getXxx(Object array, int index):
返回array数组中的第index个元素,xxx为基本类型,如果数组元素是引用类型,则方法变为
get(Object array, int index)
static void setXxx(Object array, int index, xxx val):
设置array数组的第index个元素值为value
static Object newInstance(Class<?> componentType, int ... length) :
创建一个指定元素类型、指定维度的新数组
static xxx getXxx(Object array, int index):
返回array数组中的第index个元素,xxx为基本类型,如果数组元素是引用类型,则方法变为
get(Object array, int index)
static void setXxx(Object array, int index, xxx val):
设置array数组的第index个元素值为value
使用反射生成JDK动态代理
Proxy和InvocationHandler创建动态代理
Proxy提供两个方法:
static Class<?> getProxyClass(ClassLoader loader, Class<?>...interfaces) :
创建动态代理类所对应的Class对象,该类会实现interfaces的多个接口,第一个参数生成动态代理类的类加载器
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) : 创建动态代理对象,执行代理对象的每个方法,都是在实现InvocationHandler对象的invoke方法。
static Class<?> getProxyClass(ClassLoader loader, Class<?>...interfaces) :
创建动态代理类所对应的Class对象,该类会实现interfaces的多个接口,第一个参数生成动态代理类的类加载器
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) : 创建动态代理对象,执行代理对象的每个方法,都是在实现InvocationHandler对象的invoke方法。
动态代理和AOP
泛型和反射
泛型和Class类
public static <T> T getInstance(Class<T> cls)
使用反射来获取泛型信息
获取成员变量f的类型:
Class<?> a = f.getType();
获取成员变量f的泛型类型
Type gType = f.getGenericType();
ParameterizedType pType = (ParameterizedType) gType;
Type rType = pType.getRawType(); (原始类型)
Type[] tArgs = pType.getActualTypeArguments(); (泛型参数信息)
Class<?> a = f.getType();
获取成员变量f的泛型类型
Type gType = f.getGenericType();
ParameterizedType pType = (ParameterizedType) gType;
Type rType = pType.getRawType(); (原始类型)
Type[] tArgs = pType.getActualTypeArguments(); (泛型参数信息)
0 条评论
下一页