美文网首页
Java笔记之动态特性

Java笔记之动态特性

作者: 码匠 | 来源:发表于2019-01-20 18:13 被阅读0次

    本笔记来自 计算机程序的思维逻辑 系列文章

    反射

    Class

    Class是一个泛型类,有一个类型参数

    • 所有类的根父类Object有一个 Class<?> getClass()方法,可以获取对象的Class对象
    • 如果类名已知,可以使用<类名>.class获取Class对象
    • 可以根据类名直接加载Class,获取Class对象:Class.forName(xxx)

    名称信息

    • String getName() 返回Java内部使用的真正的名字,带包信息
    • String getSimpleName() 返回不带包的名字
    • String getCanonicalName() 返回标准名字
    • Package getPackage() 返回包信息
    数组元素类型对应表
    元素类型 字符表示
    类或接口 L
    byte B
    boolean Z
    char C
    int I
    float F
    long J
    double D
    short S

    字段信息

    类中定义的静态变量和实例变量都被称为 字段 ,用类Field表示

    获取字段信息的方法
    • Field[] getFields() 返回所有的公共字段,包括其父类的
    • Field[] getDeclaredFields() 返回本类声明的所有字段,包括非公共的,但不包括父类的
    • Field getField(String name) 返回本类或父类中指定名称的公共字段
    • Field getDeclaredField(String name) 返回本类中声明的指定名称的字段
    Field
    • String getName() 返回字段名称
    • boolean isAccessible() 判断当前程序是否有该字段的访问权限
    • void setAccessible(boolean flag) 修改访问权限,忽略Java的访问检查机制,以允许读写非公共的字段
    • Object get(Object obj) 获取指定对象中该字段的值
    • void set(Object obj, Object value) 设置指定对象中该字段的值
    • int getModifiers() 返回字段的修饰符
    • Class<?> getType() 返回字段的类型
    • <T extends Annotation> T getAnnotation(Class<T> annotationClass) 返回字段指定类型的注解信息
    • Annotation[] getDeclaredAnnotations() 获取字段的注解信息

    方法信息

    类中定义的静态方法和实例方法都称为 方法 ,用类Method表示

    获取方法信息的方法
    • Method[] getMethods() 返回所有的公共方法,包括其父类的
    • Method[] getDeclaredMethods() 返回本类声明的所有方法,包括非公共的,但不包括父类的
    • Method getMethod(String name, Class<?>... parameterTypes) 返回本类或父类中指定名称和参数类型的公共方法
    • Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回本类中声明的指定名称和参数类型的方法
    Method
    • String getName() 返回方法名称

    • boolean isAccessible() 判断当前程序是否有该方法的访问权限

    • void setAccessible(boolean flag) 修改访问权限,忽略Java的访问检查机制,以允许调用非公共的方法

    • Object invoke(Object obj, Object... args) 调用指定对象中该方法

      如果是静态方法,obj 被忽略,可以为 nullargs 可以为 null ,也可以为空数组

    • int getModifiers() 返回方法的修饰符

    • Class<?>[] getParameterTypes() 返回方法的参数类型

    • Class<?> getReturnType() 返回方法的返回值类型

    • Class<?>[] getExceptionTypes() 返回方法声明抛出的异常类型

    • Annotation[] getDeclaredAnnotations() 获取方法的注解信息

    • <T extends Annotation> T getAnnotation(Class<T> annotationClass) 获取方法指定类型的注解信息

    • Annotation[][] getParameterAnnotations() 获取方法参数的注解信息

    创建对象

    使用ClassT newInstance()方法创建对象

    该方法会调用类的默认构造方法(即无参公共构造方法),如果类没有该构造方法,会抛异常

    获取构造方法的方法
    • Constructor<?>[] getConstructors() 返回所有公共的构造方法
    • Constructor<?>[] getDeclaredConstructors() 返回所有构造方法,包括非公共的
    • Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定参数类型的公共构造方法
    • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回指定参数类型的构造方法,包括非公共的
    Constructor
    • T newInstance(Object ... initargs) 创建对象
    • Class<?>[] getParameterTypes() 返回参数类型
    • int getModifiers() 返回修饰符
    • Annotation[][] getParameterAnnotations() 返回参数的注解信息

    类型检查和转换

    • boolean isInstance(Object obj) 判断类型
    • T cast(Object obj) 转换类型
    • boolean isAssignableFrom(Class<?> cls) 检查参数类型能否赋给当前对象

    类型信息

    • boolean isPrimitive() 是否基本类型
    • boolean isArray() 是否数组
    • boolean isInterface() 是否接口
    • boolean isEnum() 是否枚举
    • boolean isAnnotation() 是否注解
    • boolean isAnonymousClass() 是否匿名内部类
    • boolean isLocalClass() 是否本地类,即定义在方法内的类
    • boolean isMemberClass() 是否成员类

    声明信息

    • int getModifiers() 返回类的修饰符
    • Class<? super T> getSuperclass() 返回父类
    • Class<?>[] getInterfaces() 返回类所声明实现的所有接口,或接口所直接扩展的接口

    内部类

    • Class<?>[] getClasses() 返回所有公共的内部类和接口,包括从父类继承的
    • Class<?>[] getDeclaredClasses() 返回本类声明的所有内部类和接口
    • Class<?> getDeclaringClass() 如果当前类为内部类,返回声明该类的最外部的类
    • Class<?> getEnclosingClass() 如果当前类为内部类,返回直接包含该类的类
    • Method getEnclosingMethod() 如果当前类为本地类或匿名内部类,返回包含它的方法

    数组

    Class<?> getComponentType() 获取数组元素类型

    Array
    • Object newInstance(Class<?> componentType, int length) 创建指定元素类型,指定长度的数组
    • Object newInstance(Class<?> componentType, int... dimensions) 创建多维数组
    • int getLength(Object array) 返回数组长度
    • Object get(Object array, int index) 返回指定数组指定索引位置的值
    • void set(Object array, int index, Object value) 设置指定数组指定索引位置的值

    数组使用Object而非Object[]表示,是为了方便处理多种类型的数组

    枚举

    T[] getEnumConstants() 返回枚举常量

    泛型

    Class

    TypeVariable<Class<T>>[] getTypeParameters() 返回类的泛型信息

    Field

    Type getGenericType() 返回字段的泛型信息

    Method
    • Type getGenericReturnType() 返回方法返回值的泛型信息
    • Type[] getGenericParameterTypes() 返回方法参数的泛型信息
    • Type[] getGenericExceptionTypes() 返回方法声明异常的泛型信息
    Constructor

    Type[] getGenericParameterTypes() 返回构造方法参数的泛型信息

    Type

    接口

    子接口有

    • TypeVariable

      类型参数,可以有上界

    • ParameterizedType

      参数化的类型

      • Type getRawType() 返回原始类型
      • Type[] getActualTypeArguments() 返回具体的类型参数
    • WildcardType

      通配符类型

    注解

    创建

    @interface

    定义注解

    @Target

    元注解,表示注解的目标;目标可以有多个,用 {} 表示

    类型为ElementType,可选值有:

    • TYPE 表示类、接口(包括注解),或者枚举声明
    • FIELD 字段,包括枚举常量
    • METHOD 方法
    • PARAMETER 方法中的参数
    • CONSTRUCTOR 构造方法
    • LOCAL_VARIABLE 本地变量
    • ANNOTATION_TYPE 注解类型
    • PACKAGE
    @Retention

    表示注解信息保留到什么时候,取值只能有一个

    类型为RetentionPolicy,可选值有:

    • SOURCE 只在源代码保留,编译器将代码编译为字节码文件后就会丢失
    • CLASS 保留到字节码文件中,但Java虚拟机将 class 文件加载到内存时不一定会在内存中保留
    • RUNTIME 一直保留到运行时
    参数

    定义的方式是在注解内定义一些方法

    参数定义时可以使用 default 指定一个默认值

    参数的值不能为 null

    当只有一个参数,且名称为 value 时,提供参数值时可以省略 value=

    注解内合法的参数类型有

    • 基本类型
    • 字符串
    • 枚举
    • 注解
    • 以上类型的数组
    @Inherited

    注解不能继承

    在注解上声明该元注解,当父类声明了该注解,子类自动拥有该注解

    查看注解信息

    • Annotation[] getAnnotations() 返回所有注解
    • Annotation[] getDeclaredAnnotations() 返回本元素所有声明的注解
    • <T extends Annotation> T getAnnotation(Class<T> annotationClass) 返回特定类型的注解,没有返回 null
    • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断是否有指定类型的注解

    Annotation

    注解本身是一个接口

    所有的注解类型,内部实现都是扩展Annotation

    动态代理

    Java SDK动态代理

    使用ProxynewProxyInstance方法创建代理对象

    Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

    • loader 类加载器

    • interfaces 代理类要实现的接口列表,数组

      元素类型只能是接口,不能是普通的类

    • h 接口,对代理接口所有方法的调用都会转发给其invoke方法

    InvocationHandler

    处理代理类和被代理对象之间的关系和调用实现

    Object invoke(Object proxy, Method method, Object[] args)

    • proxy 代理对象本身,用处不大
    • method 被调用的方法
    • args 方法参数
    基本原理

    动态生成代理类,继承Proxy,动态创建每个接口的实现代码,即转发给InvocationHandler处理

    查看动态生成的代理类文件
    java -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true <包含main方法的完整类名>
    

    cglib动态代理

    基本原理

    动态生成一个类,继承被代理的类,代理类重写了父类的所有 publicfinal 的方法

    对比

    Java SDK动态代理面向的是一组 接口 ,只能为接口创建代理,返回的代理对象也只能转换到某个接口类型,无法代理一个没有接口的类,也无法代理非接口中定义的方法;而cglib则是面向一个具体的 ,动态创建新类,继承被代理类,重写其方法

    类加载机制

    类加载的基本机制和过程

    Java运行时,会根据类的完全限定名寻找并加载类,寻找的方式基本就是在系统类和指定的类路径中寻找

    • 如果是 class 文件的根目录,则直接查看是否有对应的子目录及文件
    • 如果是 jar 文件,则首先在内存中解压文件,然后再查看是否有对应的类
    类加载器

    负责加载类的类,输入完全限定的类名,输出Class对象

    一般程序运行时,都会有三个

    • Bootstrap ClassLoader 启动类加载器

      这个加载器是Java虚拟机实现的一部分,不是Java语言实现的,一般是C++实现,它负责加载Java的基础类,主要是 <JAVA_HOME>/lib/rt.jar

    • Extension ClassLoader 扩展类加载器

      这个加载器的实现类是sun.misc.Launcher$ExtClassLoader,它负责加载Java的一些扩展类,一般是 <JAVA_HOME>/lib/ext 目录中的jar包

    • Application ClassLoader 应用程序类加载器

      这个加载器的实现类是sun.misc.Launcher$AppClassLoader,它负责加载应用程序的类,包括自己写的和引入的第三方类库,即所有在类路径中指定的类

    基本过程

    这三个类加载器有父子委派关系,子加载器有一个变量 parent 指向父加载器,在子加载器加载时,一般会首先通过父加载器加载

    加载一个类时,基本过程:

    • 判断是否已经加载过了,加载过了,直接返回Class对象,一个类只会被一个ClassLoader加载一次
    • 如果没有被加载,先让父加载器去加载,如果加载成功,返回得到的Class对象
    • 在父加载器没有加载成功的前提下,自己尝试加载类

    这个过程一般被称为 双亲委派 模型,即优先让父加载器去加载

    一个程序运行时,会创建一个Application ClassLoader,在程序中用到ClassLoader的地方,如果没有指定,一般用的都是它,所以,它也被称为 系统类加载器

    ClassLoader

    方法
    • Class
      • ClassLoader getClassLoader() 返回实际加载它的加载器
    • ClassLoader
      • ClassLoader getParent() 返回它的父加载器
      • ClassLoader getSystemClassLoader() 返回默认的系统类加载器
      • Class<?> loadClass(String name) 用于加载类
    对比

    使用ClassLoaderloadClass方法和ClassforName方法都可以加载类,但ClassLoaderloadClass方法不会执行类的初始化代码

    应用

    • 实现隔离
    • 实现热部署

    相关文章

      网友评论

          本文标题:Java笔记之动态特性

          本文链接:https://www.haomeiwen.com/subject/gqxfjqtx.html