Java中的类加载

来源:互联网 发布:易赛软件 编辑:程序博客网 时间:2024/06/05 20:25

一、类的加载器(1)

当程序需要使用某个类时,如果这个类还没有加载到内存中,系统会通过加载,连接和初始化来完成类的初始化

1.1加载:

就是指将class文件文件读入内存,并为之创建一个Class(大写)对象(万物皆对象包括类),意思是任何类被使用时系统都会创建一个Class对象

1.2连接:

连接分成三步:校验、准备和解析。

1.2.1 校验:检查是否具有正确的内部结构,确保Java类型数据格式的正确性,适用于JVM。

1.2.2 准备:为静态成员变量分配内存,并设置默认初始化。

1.2.3 解析:解析过程就是在类型的常量池中寻找类,接口,字段,方法的符号引用,把这些符号引用替换成直接引用,

      这个阶段可以被推迟到初始化之后,当在程序运行过程中真正的使用这个符号的引用在去解析它。

1.3初始化:

1.3.1创建类的实例;

1.3.2访问类的静态变量,或者为静态变量赋初值;

1.3.3调用类的静态方法;

1.3.4.使用反射方式强制创建某个类或接口对应的Java.long.Class对象;

1.3.5初始化某个类的子类;

1.3.6 直接使用java.exe命令来直接运行主类。

二、类的加载器(2)

2.1含义:负责将class文件读入到内存中,并为之创建对应的Class对象。

2.2类的加载器的组成和作用:

BootStrap ClassLoader 根类加载器:也被称为引导类加载器,负责Java核心类的加载,比如:String,System等,在JDK的JRE中的lib目录下的rt.jar文件中

Extension ClassLoader 扩展类加载器:负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录

Sysetm ClassLoader 系统类加载器:负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。

类加载器加载class文件的步骤:

全盘负责:即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入
委托机制:先让parent(父)类加载器 (而不是super,它与parent classloader类不是继承关系)寻找,只有在parent找不到的时候才从自己的类路径中去寻找。
三、Java的反射(增加了程序的扩展性)
3.1反射机制:在Java程序运行状态中,对于任何一个类都能获取这个类的所用属性和方法,对于任意的一个对象都能调用它的任意一个方法和属性,这种动态的获取信息以及调用对象的方法的功能被称之为Java的反射机制。
   3.2反射技术:其实Java的反射机制就是动态的加载一个类,并获取这个类的内容,而且将字节码文件(包括内容)封装成对象,这样便于操作。
说白了,就是将一个类解剖
3.3反射的步骤:
1、获取Class对象,即获取指定名称的字节码文件对象
2、实例化对象,获取字节码文件的属性、方法和构造方法。
3、访问属性、调用方法、调用构造方法创建对象
3.4获取Class对象的三种方式:
1、每个类对象都有一个静态的属性class.
弊端:必须要明确类,如果明确的获得某个类的Class对象可以用此方式,主要用于传参。(Class c  = Person.class)
2、通过每个对象都具备getClass来获取:
    弊端:必须要创建该类对象,才可以调用getClass方法。如果拿到了对象,不知道是什么类型可以用此方式,用于获得对象的类型。 
Object obj = new Person(); 
Class clazz1 = obj.getClass()

 3、使用的Class类中的方法,静态的forName方法。

指定什么类名(完整的类名),就获取什么类字节码文件对象,这种方式的扩展性最强,只要将类名的字符串传入即可,用于类加载。 

String classname = “cn.itcast.reflect.Person”; 
Class clazz = Class.forName(classname);

//当类的字节码已经加载进了内存,就将该字节码返回;

如果jvm还没有该字节码,就用类加载器加载,再返回加载的字节码。 
前两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成。 


3.5九个预定的Class:

1、包括八种基本类型(byte、short、int、long、float、double、char、boolean)的字节码对象和一种返回值为void类型的void.class。

2、Integer.TYPE是Integer类的一个常量,它代表此包装类型包装的基本类型的字节码,所以和int.class是相等的。

基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示
3、只要是在源程序中出现的类型都有各自的Class实例对象,如int[].class。数组类型的Class实例对象,可以用Class.isArray()方法判断是否为数组类型的。
5、反射的使用:
5.1、Class类
1、类中的方法,不包括获取成员属性及方法对象
static Class forName(String className):返回与给定字符串名的类或接口的相关联的Class对象。
Class getClass():返回的是Object运行时的类,即返回Class对象即字节码对象       
String getName():以String形式返回此Class对象所表示的实体名称。       
String getSuperclass():返回此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class      
boolean isArray():判定此Class对象是否表示一个数组       
boolean isPrimitive():判断指定的Class对象是否是一个基本类型。       
2)通过Class对象获取类实例
如:
String className="包名.Person";
Class clazz=Class.forName(className);
 Object obj=clazz.newInstance();
   5.2、反射获取成员方法并使用:
获取所有方法:
Method[] getMehtods():返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。
Method[] getDeclareMethods():返回Method 对象的一个数组,这些对象反映此Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
获取单个方法:
Method getMethod(String name,Class<?>… parameterTypes):返回一个Method对象,它表示的是此Class对象所代表的类的指定公共成员方法。
Method getDeclaredMethod(String name,Class<?>… parameterTypes):返回一个Method 对象,该对象反映此Class 对象所表示的类或接口的指定已声明方法。name 参数是一个String,它指定所需方法的简称,parameterTypes 参数是Class 对象的一个数组,它按声明顺序标识该方法的形参类型。
使用方法:Method类方法
void setAccessible(boolean)方法:值为true时取消 Java 语言访问检查
Object invoke(Object obj ,参数);//调用对象的method方法

0 0