java [反射] [类加载器]

来源:互联网 发布:淘宝网零钱包儿童卡通 编辑:程序博客网 时间:2024/05/22 13:29

         

                                         


  1. 反射机制
  2. 反射中的成分描述
  3. AccessibleObject 
  4. Member 接口 
  5. Package--包类
  6. Constructor-- 构造方法类
  7. Method--方法类
  8. Field--域类
  9. Modifier --修饰符编码解码器 
  10. Array--动态数组类
  11. Class 类  
  12. 类加载器

  • 反射机制


java 反射是从JDK1.2开始出现

java 的反射机制是在运行状态下,对于任意一个类都能够获取这个类的属性和方法

        对于任意一个对象都能够调用它的任意一个方法访问任意属性,这种动态获取类成分信息 ,

动态创建类实例以及动态访问属性动态调用类方法的功能叫做java的反射机制

java程序可以在加载一个运行时才得知名称的class,获知其包,属性,方法,并能进一步进行访问设置创建调用各种类的成分java反射机制提供了在运行时获取一个对象所属的类对象,在运行时创建任意一个类的对象,在运行时获取任意一个类所具有的方法和属性,在运行时调用任意一个对

像的方法访问任意一个属性,生成动态代理


  • 反射中的成分描述


       描述类或接口包含的成分封装为类:
包类--Package
类类--Class
属性字段类--Field 
构造方法类-- Constructor
方法类--Method
修饰符类--Modifier
其中 Field Constructor Method Modifier 都为于java.lang.reflect包中
总体描述类或接口或基本类型当java的数据类型的类是Class,是java.lang包下的类




Field、Method 和 Constructor 
都继承了 java.lang.reflect包中的AccessibleObject 类
都实现了 java.lang.reflect包中的Member 接口

  • AccessibleObject 


AccessibleObject 类
该类用于在反射对象中设置 accessible 标志 , 允许具有足够特权的复杂应用程序
以某种通常禁止使用的方式来操作对象 , 提供了取消JAVA访问权限的限制。 
对于public 或 默认或protected 或private成员,在分别使用 Field、Method 
或 Constructor 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,
会执行访问检查

其构造方法供JVM使用


提供注解有关的获取和判断
getAnnotation(Class<T> annotationClass)返回该元素的指定类型的注释 ,若不存在则返回null。
getAnnotations()此元素上存在的(包括继承的注释)所有注释构成的数组,若无, 返回数组长度为0
getDeclaredAnnotations() 返回直接存在(忽略继承的注释)于此元素上的所有注释构成的数组
isAnnotationPresent(annotationClass) 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false


提供accessible标志的设置和获取

setAccessible(AccessibleObject[] array, boolean flag) 静态方法

使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志。 

setAccessible(boolean flag) 设置此对象的accessible 标志值 , 值为 true 则指示反射的对象在使用时应

该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
在flag值为true时 ,如果请求被拒绝 会抛出SecurityException。 
isAccessible()获取此对象的 accessible 标志的值(boolean值)。




  • Member 接口 


`成员是一种接口,反映有关单个成员(字段或方法)或构造方法的标识信息


提供的功能
getDeclaringClass() 
                       返回此Method或Field或Constructor所表示的方法或域或构造方法的声明类或接口的 Class 对象。
                       即定义的方法或字段或构造方法所在的类
int getModifiers() 
                      返回此Method或Field或Constructor所表示的方法或域或构造方法的 Java 语言修饰符的整数形式。 
                      如果同时被多个修饰符修饰那么返回的是各个修饰符常量的和, 修饰符的编码解码由Modifier 类描述
getName() 
                       返回此Method或Field或Constructor所表示的方法或域或构造方法的简单名称。 
isSynthetic() 
                    如果此成员是编译器引入的,则返回 true;否则,返回 false。 
                    复合方法或复合字段或复合构造方法调用该方法返回true,否则为false







  • Package--包类



  • Constructor-- 构造方法类


Constructor 描述单个构造方法及访问权限
除了继承AccessibleObject的getAnnotations, isAccessible, isAnnotationPresent, 

setAccessible方法外 , 

    • 提供的主要功能

(1) 判断

              equals(Object o) 如果此Constructor实例与o所指向Constructor的一个实例都是由同一个类型声明的
                              且参数列表相同则他们是同一个构造方法
isSynthetic() 如果此构造方法是一个复合构造方法,则返回 true;否则返回 false。
isVarArgs() 如果声明此构造方法可以带可变数量的参数,则返回 true;否则返回 false。

(2)获取构造方法的各成分


TypeVariable<Constructor<T>>[] getTypeParameters() 按照声明顺序返回一组 TypeVariable 对象,这些对象表示通过此 GenericDeclaration 
                                                           对象所表示的一般声明来声明的类型变量。 即返回声明的泛型的部分

getDeclaringClass() 返回定义构造方法的类的Class对象。

getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。

Class<?>[] getParameterTypes() 按照声明顺序返回此 Constructor 对象所表示构造方法的形参类型的 Class 对象构成的数组

Type[] getGenericParameterTypes() 按照声明顺序返回构造方法的形参类型的 Type 对象构成的数组


(3) 通过反射方式构造实例
T newInstance(Object... initargs) 
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,
并用指定的初始化参数初始化该实例。空参数的构造方法反射调用该方法的initargs为
null数组长度指定为0 ,
跟new一样每调用一次该方法就会产生一个实例,该方法可以反射调用一个类的任意
参数列表的构造方法,如果仅仅参数空参数的构造方法的一个对象可以直接调用
Class中的newInstance方法

反射方式调用类的构造方法创建实例,可以使得现在可以不需要预先知道未来要创建的
实例的类是什么类,而通过一个变量来存放待确定的未来的类的全限定名,将该变量'
传给Class的forName方法获得类对象,再通过Class的newInstance或Constructor的

newInstance方法来创建实例


(4) 描述的字符串表示

toGenericString()  返回描述此 Constructor 的字符串,其中包括类型参数。
toString() 返回描述此 Constructor 的字符串。
getName() 返回此构造方法的名称。

(5) 获取声明抛出的异常类型
Class<?>[] getExceptionTypes() 返回声明在构造方法上的抛出异常类型的Class对象构成的数组
Type[] getGenericExceptionTypes() 返回声明在构造方法上的抛出异常类型的Type 对象数组

          
(6) 复写父类有关操作该Constructor 表示的构造方法上的注解的方法
<T extends Annotation> T  getAnnotation(Class<T> annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 

Annotation[] getDeclaredAnnotations() 返回直接存在于此元素上的所有注释(不包括继承的)。 

Annotation[][] getParameterAnnotations() 按照声明顺序返回一组数组,这些数组表示通过此 Constructor 对象表示的方法的形参上的注释。 



  • Method--方法类


Method 用来描述某类或接口的单个方法的类
通过Class的getMethod(String name , Class<?> cla)方法可以返回一个Class对象表示的类指定方法
通过Method的invoke(Object obj, Object... args) 方法可以调用该Method实例表示的方法 , 
obj代表指向该方法的实例可以通过newInstance()动态创建Class对象表示的类的实例,如果该Method]
表示的方法是静态方法则第一个参数可以为null,因为静态不依赖于实例

    • 提供的主要功能

(1)判断
equals(Object obj)如果此Method实例与obj指向的Method实例是由相同的类声明,具有相同的名称、
                                  形参类型和返回类型,则两个 Method 相同。
                                   判断时依次获取各成分并比较都相等之后返回true
getDeclaringClass()
getName()
getReturnType()

getParameterTypes()


isVarArgs()判断此方法是否含有可变长度的参数,含有则返回true
isSynthetic()如果此方法为复合方法,则返回 true;否则,返回 false。
isBridge()如果此方法是 bridge 方法,则返回 true;否则,返回 false。


(2) 获取各成分

  • 获取修饰符   

getModifiers() 以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。

                 
  • 获取泛型方法的泛型声明类型
TypeVariable<Method>[] getTypeParameters()返回按声明顺序的 TypeVariable 对象(方法泛型声明
的占位符)的数组,该类型对象描述了由 GenericDeclaration 对象表示的按声明顺序
来声明的泛型类型变量 , 如果所表示的方法参数中没有类型变量,则返回长度为 0 的数组。


  • 获取Method表示的方法的返回类型
Class getReturnType() 返回此 Method 对象所表示的方法的正式返回类型的 Class 对象(不包括泛型限定部分:
<参数化类型的全限定名>如果有的话) 
Type getGenericReturnType()返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。 
如果返回类型是参数化类型 , 则返回的 Type 对象必须表示实际的参数类型
返回Type的字符串形式是 :  实际返回类型的全限定名+<参数化类型的全限定名>
因为Type包括参数化类型


  • 获取参数列表
Class<?>[] getParameterTypes()按照声明顺序返回此 Method 对象所表示的方法的形参类型的 
Class 对象的数组,如果底层返回是空参数则返回的是长度为0的Class数组
如果参数列表中有参数化类型泛型,则返回的数组中该Class类型不包括参数化的类型
Type[] getGenericParameterTypes()按照声明顺序返回此 Method 对象所表示的方法的形参类型
的 Type 对象的数组。如果底层方法不带参数,则返回长度为 0 的数组。 
如果参数列表中有参数化类型泛型,则返回的数组中包括参数化类型的部分


  • 获取方法上声明抛出的异常类
Class<?>[] getExceptionTypes() 
返回声明在此 Method 对象表示的底层方法抛出的异常类型 的Class 对象的数组
Type[] getGenericExceptionTypes() 
返回声明在此 Method 对象表示的方法抛出的异常类型的  Type 对象数组


  • 获取方法定义所在的类或接口类型
getDeclaringClass()返回此 Method 对象表示的方法的类或接口的声明类或接口的 Class 对象。 

  • 获取方法名称
getName()  以 String 形式返回此 Method 对象表示的方法名称

(3) 获取方法描述的字符串形式


toString() 返回描述此 Method 的字符串,包括修饰符(如果有),返回类型,声明类,方法名,参数列表.
不包括泛型声明部分,返回泛型类型的不包括参数化部分,参数列表中泛型类不包括参数化部分 
即返回格式为:
toGenericString()  返回描述此 Method 的字符串,与toString方法不同的是,多了泛型类型参数列表
(如果有)。 如果没有泛型类型参数列表则返回结果和toString一样该方法,返回格式如下:
                                       "修饰符"+"<泛型声明>"+"返回类型"+"<参数化类型全限定名>"+" "+"定义该方法所在的类的全限定名"
                                 +"."+"方法名"+"("+"方法的形式参数列表各类型全限定名(泛型类包括泛型限定,基本类型为本身)"+")"  
         

(4) 反射式调用Method表示的方法


invoke(Object obj , Object... args) 通过反射调用指定对象指定参数的此 Method 对象表示的底层方法。
其中指定的形参如果是基本形参,则调用过程会包含自动装箱拆箱,
如果调用的方法是空参数, 则invoke的第二个参数为null,
如果调用的方法是静态的,则第一个参数为null
调用该方法的返回值:
如果Method表示的方法返回类型为基本类型,则该该调用返回过程包括自动装箱过程
如果Method表示的方法返回类型为基本类型数组,则该调用直接返回该数组,
如果Method表示的方法访问类型为void,则该调用返回null

通过反射调用该方法, 不需要创建一个类的实例就能调用成员方法


(5)操作方法上注解的功能(覆盖了父类方法)


getAnnotation(Class<T> annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,
                                                否则返回 null。该方法覆盖了父类AccessibleObject 中的 getAnnotation
getDeclaredAnnotations()返回直接存在于此元素上的所有注释(不包括继承的) 如果没有注释直接存
               在于此元素上,则返回长度为零的一个数组. 该方法覆盖了父类对应的方法
Annotation[][] getParameterAnnotations()返回表示按照声明顺序对此 Method 对象所表示方法的
                                           形参进行注释的那个数组的数组。
Object getDefaultValue()  返回由此 Method 实例表示的注释成员的默认值。 
         
         

(6) 继承自父类的功能

                       getAnnotations, isAccessible, isAnnotationPresent, setAccessible










  • Field--域类


Field 用来描述类或接口中的字段常量,静态成员变量,非静态成员变量等

除了具有继承自AccessibleObject 的方法 
getAnnotations, isAccessible, isAnnotationPresent, setAccessible, setAccessible 

外 

    • 提供的主要方法

                 (1) 判断

equals(Object obj) 如果由相同的类声明并且具有相同的名称和类型,那么这两个 Field 对象是相同的。
class Ac{public static final String SS = "sss";}
class Ad{public static final String SS = "sss"

Ac a1 = new Ac();
Ac a2 = new Ac();
          Ac.class.getFields()[0].getDeclaringClass()==C.class.getFields()[0].getDeclaringClass();//false
          a1.getClass().getFields()[0].getDeclaringClass()==a2.getClass().getFields()[0].getDeclaringClass();//true

           
isEnumConstant() 如果此字段表示枚举类型的元素,则返回 true

                (2) 获取Filed成分(修饰符,声明类型,注解)

getModifiers()以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符 , 当同时被多个修饰时返回各个的和
                        可以通过Modifier类的toString方法将其转换成字符串的表现形式
getType()返回该 Field 对象表示的字段的声明类型Class对象
getGenericType()   返回此 Field 对象所表示字段的声明类型的Type对象.
                            Type类型包括原始类型、参数化类型、数组类型、类型变量和基本类型。 
getName()  返回此 Field 对象表示的字段的名称。
getAnnotation(注解类型) 返回该元素的指定类型注解
getDeclaredAnnotations() 返回所有该元素上的注解

 

                (3) Filed 的字符串表示

toString()将此Filed对象转化成字符串形式 格式如下
"修饰符"+" "+"字段类型"+" "+"定义该属性所在的类的全限定名"+"."+"字段名"
toGenericString()将此Filed对象(包括一般类型)转化成字符串形式 格式如下
"修饰符"+" "+"一般字段类型(包括泛型的<>部分 , 如果有的话)"+" "+"定义该属性所在的类的全限定名"
+"."+"字段名"


(4) 提供了对指定该Field所在的类的实例的get 和set操作
通用的get  操作 Object get(Object obj)   返回指定对象上此 Field 表示的字段的值 , 适用不同的声明类型
通用的set  操作  set(Object obj, Object value)    将指定对象上此 Field 对象表示的字段设置为指定的新值
适用于基本数据类型的获取操作: get对应包装名(Object obj) 可以获取静态或实例 基本类型的字段值
适用于基本数据类型的设置操作: set对应包装名(Object obj,  基本类型) 
      
如果获得的Field表示所表示的成员变量是私有的,则以上的set或get操作都不允许,调用会抛出异常
但可以通过Field的父类方法setAccessible(true)来解除这种禁止,使得可以强迫性设置或获取私有变量值


  • Modifier --修饰符编码解码器 


将类接口,成员方法,成员变量,构造方法的修饰符封装为 Modifier 类
Modifier 类提供了 static 方法和常量 对类和成员访问修饰符进行解码 , 将修饰符表示为整型数
公共常量字段
PUBLIC = 1;
PRIVATE = 2;                   
PROTECTED = 4;             
STATIC = 8;                     
FINAL = 16;                     
SYNCHRONIZED = 32;  
VOLATILE = 64;              
TRANSIENT = 128;         
NATIVE = 256;                
INTERFACE = 512;          
ABSTRACT = 1024;         
STRICT = 2048;                
分别描述
public,private,protected,static,final,synchronized,volatile,transient,native,interface,abstract,strictfp

                编码与解码

如果用flag表示一个getModifier()的返回结果
int flag 由12位的二进制数表示
根据编码表
0000 0000 00011--------public
0000 0000 00102--------private
0000 0000 01004--------protected
0000 0000 10008--------static
0000 0001 000016------final
0000 0010 000032------synchronized
0000 0100 000064------volatile
0000 1000 0000128----transient
0001 0000 0000256----native
0010 0000 0000512----interface
0100 0000 00001024--abstract
1000 0000 00002048--strictfp


二进制的每一位如果为1 则代表包含该位所代表的修饰符
假如 flag = 25 ;  其二进制表示 0000 0001 1001
根据标志位为1则含有该修饰符,解码结果为 public static final



Modifier中的非公共的字段描述,其中
复合 SYNTHETIC = 4096;
注解 ANNOTATION = 8192;
枚举 ENUM = 16384;


Modifier提供了通过修饰符对应的整数判断修饰符类型的功能及根据整数返回修饰符字符串形式的方法toString








  • Array--动态数组类

 Array也是java.lang.reflect包中的类 , 通过反射动态创建和访问 Java 数组

该类所有的方法都是静态的 , 提供主要操作有创建特定维数长度的数组 , 设置指定索引的值 ,
返回指定索引的值 , 获取数组长度


提供了设置和获取指定数组中指定索引的值的操作 , 可以指定设置或返回类型为基本类型或Object
通用设置 set(Object array,int index , Object value) 和 基本类型元素设置(Object value 改为基本类型)
通用获取 Object get(Object array,int index) 和基本类型元素获取返回基本类型元素值


getLength(Object array) 以 int 形式返回指定数组对象的长度。
newInstance(Class<?> componentType, int... dimensions) 
创建一个具有指定的元素类型和维度的新数组。 如果 componentType 表示一个非数组类或接口,
则新数组具有dimensions.length 维度 , 如果 componentType 表示一个数组类,则新数组的维
数等于 dimensions.length 和 componentType 的维数的总和
newInstance(Class<?> componentType, int length) 
创建一个具有指定的元素类型和长度为length的新数组,该数组的维数等于componentType的维数+1
调用此方法等效于创建如下数组:  int[] x = {length}; Array.newInstance(componentType, x);




















  • Class 类  


Class 描述所有java数据类型的类

字节码对象 , 所有的java类型 包括TYPE(类,接口,枚举,注解类型),都是 Class 的一个实例
我们不能通过Class的构造方法来获得每种类型的Class类实例,因为Class的构造方法是私有的
Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自
动构造的 , 所以若类型的字节码已经存在则可以直接获取,若果不存在 , 获取字节码对象的
操作将导致不存在的类被类加载器加载初始化后才能获取,每一种类对象在内存中只存在一份
对于void 或基本类型他们的类对象可以通过其名称.class的形式获得
对于接口则可以通过接口名.class或Class.forName("接口全限定名")获得
而对于类类型,因为ava所有类都继承自Object类,而Object类提供了getClass()方法可以使
得所有的java类实例除了可以使用上面两种方式还可以通过getClass()方法来获得类类型的
字节码对象,当然不是所有类都可以,而是要求该类能创建对象,能被实例化


  • 获取字节码对象的方式


得到一个类的字节码对象的主要三种办法
1,数据类型名.class数据类型可以是任意java的数据类型 包括TYPE(类,接口,枚举,注解类型),
八种基本数据类型,void,数组
void.class返回void的Class对象
int.class 返回int的Class对象
char.class 返回char的Class对象
Iterator.class返回Iterator的Class对象
String.class 返回String的Class对象
int[].class 返回int[]的Class对象
int[][].class 返回int[][]的Class对象
同一种元素类型和同维数的数组具有同一数组Class对象
int[].class!=int[][].class

char[]!=int[].class


2,对象调用getClass方法只有对象可以调用该方法,即对象被创建之后才能调用,void和基本类型

及接口,抽象类,构造函数私有化的类因为不是类或不能创建对象, 不能用该方法获得他们的Class对象


3,调用Class的静态方法forName

      Class.forName(String className);

       className是包括完整包名的类名或接口名即全限定名,

通过全限定名的字符串形式返回Class对象 ,void 或基本类型不能通过该方法获得字节码对象
通过此方式获取类型的字节码对象,可以在内存中还没有加载字节码的前提下,将类的字节码加载到
内存中去,可以不需要创建对象再获取 ,假如调用该方法时对应的字节码对象已经存在于内存中,则
该方法直接去获取内存中的字节码对象并返回,而不是加载同一个分字节码


特殊获取方式

1) Class 的getSuperclass() 及 getDeclaringClass()可以通过子类或者被声明类的中的其他Class对象间接获得

2) 基本类型的包装类和Void类中都有一个字段常量,TYPE 该字段指向对应的基本类型及void的Class对象如
int.class ==Integer.TYPE
char.class==Character.TYPE
void.class==Void.TYPE
基本类型的Class对象不等于对应装箱类的Class 对象
int.class==Integer.class;//false
因为泛型仅仅是提供给编译器检查用的,所以一个泛型类参数化之后,经过编译,只要原始类型
相同那么就是同一Class对象,如:
ArrayList<String> al1 = new ArrayList<String>();
        ArrayList<Integer> al2 = new ArrayList<Integer>();
al1.getClass()==al2.getClass();//true


字节码对象(Class类实例)提供很多操作

获取Class对象
获取Class对象的加载器
获取Class对象表示的类或接口的成分(包/方法/构造器/字段/)
获取Class对象表示的类或接口的成分的字符串表现形式或只或只获取其中的成分名称
获取Class对象表示的类或接口的父类或实现接口
创建Class对象表示的类的对象
类型判断(接口/枚举/注解类/数组类/基本类型或void/)
可引用判断
相等或子类子接口判断



(1) 获取Class对象
forName(String name )将字符串形式的类或接口的全限定名返回对应的字节码对象,不能用该方法获得
void或基本类型字节码对象 ,此方法等效于: 
Class.forName(className, true, currentLoader)
forName(String name,boolean initialize, ClassLoader loader)
使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的 Class 对象
只有 initialize 参数为 true 且以前未被初始化时,才载入该类并初始化该类。 如果
是false时,调用forName方法只是在命令类加载器载入该类,而不初始化该类的静
态区块,只有当该类第一次实例化时,静态区块才被调用。当为true时,则载入时就
调用静态区块。 调用该方法不会产生类的实例,产生类实例可以通过newInstance方法


(2)创建Class对象表示的类的对象

newInstance() 获得此字节码对象所表示的类的新实例,这是通过new以外的另一种创建类
对象的方式,调用该方法要求字节码对象所表示的类是非抽象类的且可以创建对象
的类类型,抽象类、接口、数组类、基本类型或 void或者该类没有公共构造方法
不能调用该方法 , 否则抛异常,调用此方法时,如果该类尚未初始化,则初始化这个类。
但是调用该方法来获得实例只能通过调用空参数的构造方法来获得,此方法不能获取
非空参数的实例 , 如果Class说表示的类没有空参数的构造方法,则调用该方法会抛出
异常 ,如果想通过反射调用带参数的构造方法参数实例,可以先获取Constructor实例

再通过Constructor中的newInstance方法来指定调用的含参构造方法

(3) 判断


  • 可引用判断 , 相等或子类子接口判断

isInstance(Object obj)判断此Class对象的所表示的引用类型能否指向obj指定实例,它的作用跟
instanceof运算符等效,如
String s = "abc";
System.out.println(Object.class.isInstance(s));//true
System.out.println(s instanceof Object);//true
isAssignableFrom(Class<?> cls)  判断此类字节码对象是否与要检查的类字节码对象相等或是
其子类或子接口void 或基本类型只有相同时返回true , 类和接口在相同时或是该类或接口
的子类子接口时返回true
  • 类型判断(接口/枚举/注解类/数组类/基本类型或void/)
isInterface() 判断此类对象是否表示一个接口类型 ,注释类型也是接口
isArray() 判断此类对象是否表示一个数组类
isAnnotation()如判断此 Class 对象是否表示一个注释类型 ,
isPrimitive()判断此类对象是否表示一个基本类型或void,是则返回true ,有九种预定义的 Class 对象
                     基本类型或void的Class对象Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE,
                     Integer.TYPE,Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE 分别就是基本类型或
                       void的字节码对象 , 故他们调用此方法返回结果也是true
isEnum() 判断是否为枚举类 , 被声明enum的枚举类才会返回true ,Enum 的Class调用此方法返回false

isSynthetic()判断此类是否是复合类          

(4) 获取描述的字符串表示

getName()以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
类或接口返回全限定名字符串形式,基本类型和void返回自己的字符串形式
基本类型的数组的返回: "维数个["+"基本类型名的首字母的大写(boolean 和long分别是Z和J)"
类类型或接口的数组类返回 : "(维数个)["+"L"+"元素类型全限定名"
String.class.getName()//返回"java.lang.String"
int.class.getName()//返回"int"
new String[1][2][3].getClass().getName()//"返回[[[Ljava.lang.String"
(new byte[3][4][5][6][7][8][9]).getClass().getName()//返回"[[[[[[[B"
boolean[][].class.getName();//返回"[[Z"


toString 重写了Object的方法,对于类(包括枚举)和接口(包括注解类)数组类返回形式是

"类型(class/interface )" + "数组维数个[ " + "全限定名"跟getName()方法相比对于类或接口或数组
类该方法仅仅是多了类型声明(class/interface ) ,对于基本类型或void则返回结果相同
注意 Object的toString等效于:
getClass().getName() + '@' + Integer.toHexString(hashCode())

(5) 获取Class对象的加载器

getClassLoader() 获得该类的类加载器,若返回null说明该类型的Class实例由引导类加载器加载的


(6) 获取Class对象表示的类或接口的成分(包/方法/构造器/字段/)

getComponentType() 如果当前类不是一个数组,则返回 null,如果是一维数组则返回元素类型对

应的Class对象 , 如果是N维数组则返回N-1维该类数组类的Class对象


getFiled(String S)获得该类或接口的名为S的公共成员字段 , 搜索顺序是:
从该类表示的类搜索带指定名的公共字段 , 若找不到--->从该类的直接父接口按声明顺序搜索
一直到顶层父接口, 若找不到--->从该类对象表示的类的直接父类搜索 ,若搜不到继续搜上一个

            父类,如果到顶层父类都没找到,则抛出NoSuchFieldException异常


getFileds( )获取该Class对象表示的类或接口的所有公共字段返回所有公共字段构成是数组,先搜索本类
或接口中的公共字段按声明顺序再获取 , 再搜索其父接口及其所有父接口然后搜索父类直到
顶层父类 , 如果都没搜到任何公共字段或该Class对象表示的是void 或基本类型则返回长度为

0的Field数组.


getDeclaredField(String name) 返回此Class对象所表示的类或接口的名为name所表示的字段(任意权限)

若不存在或该Class对象表示的是void 或基本类型则抛出异常


getDeclaredFields() 返回此 Class 对象所表示的类或接口所声明的所有字段,包括所有权限修饰的
字段(包括公共、保护、默认(包)访问和私有字段)构成的数组 , 如果该Class对象表示的类

             或接口没有声明任何字段或该Class对象表示的是void或基本类型则返回长度为0的Filed数组


getConstructor(Class[]) 返回此 Class 对象表示的类的指定的公共构造方法对象。 Class[]表示指定的

                            构造方法的形参的类对象构成的数组


getConstructors() 返回此Class 对象表示的类的所以公共的构造方法构造的数组 , 如果该类没有公共构造

                           方法或该类是数组类或该Class表示的是接口或基本类型或void则返回长度为0的数组


getDeclaredConstructor(Class<?>... parameterTypes) 根据此 Class 对象所表示的类或接口的指定

                           构造方法的形参的类对象构成的数组返回此构造方法。 


getDeclaredConstructors()  返回此 Class 对象表示的类声明的所有构造方法。包括公共、保护、默认(
包)访问和私有构造方法。返回数组中的元素没有任何特定的顺序。如果该类存在一个默认构造
方法,则它包含在返回的数组中。如果此 Class 对象表示接口、基本类型、数组类

             或 void,则此方法返回一个长度为 0 的数组。 


getMethod(String name, Class<?>... argsTypes) 返回一个此 Class 对象所表示的类或接口的
指定公共成员方法。 参数name用来指定方法名称,argsTypes用来指定方法的参数类型它是一个
Class 对象数组 ,如果argsTypes为null则表示空参数 , 查找指定方法的顺序是:
-->从本类开始查找,若没有匹配的-->从其父类中查找,如果没有再往顶层去找,如果都没有则-->

            从该类父接口查找,一直到顶层接口,如果都没找到则抛出异常


getMethods() 返回此Class对象表示的类或接口(包括父类超父类父接口超父接口)的公共成员方法构成的
数组 . 数组类返回Object类继承来的所有公共方法. 返回的数组元素没有特定顺序,如果此Class对象
表示的类及其父类接口都没有公共成员方法或表示基本类型或void则返回长度为0的数组


getDeclaredMethod(String name, Class<?>... argsTypes)
返回此Class对象表示的类或接口的任意权

                        限修饰的指定方法对象
getDeclaredMethods() 返回此Class对象表示的类或接口(不包括继承的类或接口)任意权限修饰的Method
对象,返回的数组元素没有特定顺序 , 如果此类或接口没有任何方法或Class对象表示的是基本类型或
数组或void则返回长度为0的Method数组

 

getInterfaces() 返回此Class对象所表示的类所实现或接口所继承的接口,返回的数组元素顺序与声明的接口

顺序一致 ,如果该Class对象表示的类没有实现任何接口或表示的接口没有继承任何接口,或表示的是
基本类型或void 则返回长度为0 的Class数组
getSuperclass()返回此Class对象所表示的实体(类、接口、基本类型或 void)的超类的 Class。
如果该Class表示 Object 类、一个接口、一个基本类型或 void,则返回 null

            注意该方法中class的c是小写的 !


getPackage()  获取此类所在的包。


getDeclaringClass()返回此类的声明类 , 内部类的声明类就是它所在的外部类,内部类实例调用getClass()返回

内部类的Class对象,再调用getDeclaringClass()返回外部类Class对象

getModifiers()返回此Class对象表示的类或接口的修饰符的整数形式,若被多个修饰则返回他们的和




  • 类加载器



类的使用包括三个过程,在java源文件被编译器编译成class文件后,通过类加载器将class中的二进制
文件装入JVM中的方法区,并在堆区中创建一个该class的Class对象,没一种class只会被创建一个Class
对象,当需要创建一个该Class对象所表示的类实例的时候会在堆中开辟存放该类实例所需空间,并进行
初始化


类加载器(class loader),用来加载 Java 类到 Java 虚拟机中
Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。
类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个Class的实例
表示一个 Java 类型。如果该类对象所表示的类是可以实例化的即可以创建对象那么可以通过此实
例的 newInstance()方法创建出该类的一个对象。数组类的Class对象不是由类加载器创建的,而是
java运行是JVM根据需要自动创建.数组类的类加载器由Class 的getClassLoader()返回,该加载器与元素
类型的加载器相同,基本类型的数组没有加载器,调用该方法返回的是null

      

        java类加载器分系统提供的类加载器和java自定义的类加载器
系统提供的加载器有三种:


(1)引导类加载器(Bootstrap ClassLoader) 
----用来加载java的核心类库 , 引导类加载器是本地的和环境有关,而且它不是用java写
   成的,用C++实现,是所有类加载器的最终父加载器 , 这个引导类加载器的主要功
能是加载java的核心类库(JRE/lib/rt.jar) , 如java.lang包的类 , 包含了运行java程序必不可少的系
统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系
统缺省加载这个包 , 因为引导类加载器脱离于java体系,故被通过引导加载器加载
的Class 对象调用getClassLoader()返回的都是null,java.lang.ClassLoader 的
getParent()方法返回的也是null , 而扩展类加载器的Parent设为null

(2)扩展类加载器(Extension ClassLoader) 
----用来加载java的扩展类库jre\lib\ext\*.jar 或者java.ext.dirs系统属性指定的目录中jar文件
  此类加载器是java类,由sun.misc.Launcher (启动器)的内部类ExtClassLoader实现 ,
由其父加载器 Bootstrap ClassLoader引导加载

(3)系统类加载器(System ClassLoader) 
----用来加载一般java应用的类 ,加载classpath指定的类 , 是我们编写的java类
的默认类加载器 ,整个应用中不做任何特殊设置, 我们编写的所有java类都会
由它来装载

 此类加载器是java类,由sun.misc.Launcher的内部类AppClassLoader实现 
也是由Bootstrap ClassLoader加载的,且加载该类加载器之前需要先加载完
ExtClassLoader ,AppClassLoader的Parent被设置为ExtClassLoader
此类加载器实例可以通过java.lang.ClassLoader 的getSystemClassLoader
方法来获取 ,


java开发者通过继承java.lang.ClassLoader 来自定义类加载器





类加载器对应的层次关系:


自定义类加载器的父加载器是系统类加载器
系统类加载器的父加载器是扩展类加载器 
扩展类加载器的父加载器是引导类加载器
扩展类加载器和系统类加载器都由其最终的父加载器即引导类加载器加载到JVM中




加载器的继承关系(注意不是加载器父子关系)

java.lang.ClassLoader 

                               |-- java.security.SecureClassLoader 

                                                                     |-- java.net.URLClassLoader  

                                                                                                     |-- sun.misc.Launcher.ExtClassLoader  

                                                                                                     |-- sun.misc.Launcher.AppClassLoader  

注意Launcher是启动器而ExtClassLoader和AppClassLoader是其内部类,是内部类继承了

URLClassLoader 。







每一种java 类的字节码对象最多只能在JVM中存在一份,需要使用某java类型时,如果当前虚拟机中

没有时会通过类加载器加载一份进去 , 如果检测到已经存在一份时就不再加载同一种类的字节码对

象 , 而是共享存在的那一份.同一类的不同对象共享一份其对应的Class对象,不同类对应不同Class

实例,不同Class实例可以被同一个ClassLoader实例加载


怎么判断是否是同一个Class 实例呢?


java通过两个标识来判断,一个是类或接口的全限定名(完整包名和类名或接口) , 另一个是被同一

个类加载器实例加载 

每一个java类都是由特定的类加载器实例加载到JVM中 , 每一个Class实例都对应着一个类加载器

实例,类加载器一般通过Class的getClassLoader()方法获得,对于调用该方法返回null的Class实例

是由引导类加载器加载的



java.lang.ClassLoader 是用来操作类加载器的类

getParent 返回该类加载器的父加载器



类加载器的委托机制


1)当前线程的类加载器首先加载该线程中的第一个类
在一个类中引用了另外一个类,则先加载前一个类再加载后加载另一个类
2)使用ClassLoader.loaderClass()方法


         每个子加载器加载类时,先委托给父加载器,依次类推
先由最顶层的加载器加载,如果加载不了,再由下一层,依次类推,一直到发起的子加载器


发起的子加载器也加载不了时会抛出ClassNotFoundExcept 

0 0
原创粉丝点击