java中类的加载_Java中的类和类加载机制

主要介绍以下几方面内容(理解 Class 类、理解 Java 的类加载机制、学会使用 ClassLoader 进行类加载)

1.理解Class类

每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。

Class 对象只能由系统建立对象

一个类在 JVM 中只会有一个Class实例

每个类的实例都会记得自己是由哪个 Class 实例所生成

1:Class是什么?

Class是一个类:(/小写class表示是一个类类型,大写Class表示这个类的名称)

public classReflectionTest {

@Test

public voidtestClass() {

Class clazz = null;

}

}

//Class的定义

public final

class Class implementsjava.io.Serializable,

java.lang.reflect.GenericDeclaration,

java.lang.reflect.Type,

java.lang.reflect.AnnotatedElement {....}

2:Class这个类封装了什么信息?

Class是一个类,封装了当前对象所对应的类的信息

1、 一个类中有属性,方法,构造器等,比如说有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类

2、Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等

3.对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。

4.Class 对象只能由系统建立对象,一个类(而不是一个对象)在 JVM 中只会有一个Class实例

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagereflect;public classPerson {

String name;private intage;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}public Person(String name, intage) {super();this.name =name;this.age =age;

}publicPerson() {super();

}

}

定义了一个Person类型

通过Class类获取类对象

public classReflectionTest {

@Testpublic voidtestClass() {

Class clazz= null;//1.得到Class对象

clazz = Person.class;

System.out.println();//插入断点

}

}

在断点处就可以看到Class对像包含的信息

832e4beac8bcb875d0469f6c36101647.png

同样,这些属性值是可以获取的

public classReflectionTest {

@Testpublic voidtestClass() {

Class clazz= null;//1.得到Class对象

clazz = Person.class;//2.返回字段的数组

Field[] fields =clazz.getDeclaredFields();

System.out.println();//插入断点

}

}

查看fields的内容

7c988478740e5b9c3319d52b0ad3dc6c.png

对象为什么需要照镜子呢?

1. 有可能这个对象是别人传过来的

2. 有可能没有对象,只有一个全类名

通过反射,可以得到这个类里面的信息

获取Class对象的三种方式

1.通过类名获取      类名.class

2.通过对象获取      对象名.getClass()

3.通过全类名获取    Class.forName(全类名)

public classReflectionTest {

@Testpublic void testClass() throwsClassNotFoundException{

Class clazz=null;//1、通过类名获取对象 类名.class

clazz=Person.class;

Field[] filed=clazz.getDeclaredFields();

Field[] fields=clazz.getFields();

System.out.println(Arrays.deepToString(filed));

System.out.println(Arrays.deepToString(fields));//2、通过对象名//这种方式是用在传进来一个对象,却不知道对象的类型时候用

Person person=newPerson();

clazz=person.getClass();

Object obj=newPerson();

clazz=obj.getClass();//3、通过全类名(会抛出异常)

String classname="reflect.Person";

clazz=Class.forName(classname);//字符串的例子

clazz=String.class;

clazz="javaTest".getClass();

clazz=Class.forName("java.lang.String");

System.out.println();

}

Class类的常用方法

方法名

功能说明

static Class forName(String name)

返回指定类名 name 的 Class 对象

Object newInstance()

调用缺省构造函数,返回该Class对象的一个实例

Object newInstance(Object []args)

调用当前格式构造函数,返回该Class对象的一个实例

getName()

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

Class getSuperClass()

返回当前Class对象的父类的Class对象

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Class getSuperclass()

返回表示此Class所表示的实体的超类的Class

Class类的newInstance()方法

@Testpublic void testNewInstance() throwsClassNotFoundException, InstantiationException, IllegalAccessException{//1、获取Class对象

String className="reflect.Person";

Class clazz=Class.forName(className);//利用class对象的newInstance方法创建一个类的实例

Object obj=clazz.newInstance();

System.out.println(obj);

}

可以看出确实是创建了一个Person实例

但是Person类有两个构造方法,到底是调用的哪一个构造方法呢

实际调用的是类的无参数的构造器。所以在我们在定义一个类的时候,定义一个有参数的构造器,作用是对属性进行初始化,还要写一个无参数的构造器,作用就是反射时候用。

一般地、一个类若声明一个带参的构造器,同时要声明一个无参数的构造器

2.ClassLoader

类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示

4aafea3bacf81decf0aacc8b35631593.png

@Testpublic void testClassLoader() throwsClassNotFoundException{//1、获取一个系统的类加载器(可以获取,当前这个类ReflecTest就是它加载的)

ClassLoader classLoader=ClassLoader.getSystemClassLoader();

System.out.println(classLoader);//2、获取系统加载器的父类加载器(扩展器加载器,可以获取)

classLoader=classLoader.getParent();

System.out.println(classLoader);//3、获取扩展类加载器的父类加载器(引导加载器,不可以获取)

classLoader=classLoader.getParent();

System.out.println(classLoader);//4、测试当前类用哪个类加载器进行加载(系统类加载器)

classLoader=Class.forName("reflect.ReflectionTest").getClassLoader();

System.out.println(classLoader);//5、测试JDK提供的Object类由哪个类加载器负责加载(引导类)

classLoader=Class.forName("java.lang.Object").getClassLoader();

System.out.println(classLoader);

}

使用类加载器获取当前类目录下的文件

e1f621e8feca878caf008d650d9db561.png

首先,系统类加载器可以加载当前项目src目录下面的所有类,如果文件也放在src下面,也可以用类加载器来加载

调用 getResourceAsStream 获取类路径下的文件对应的输入流.

b8a4653a5e472ca7481b48efd23c39d1.png

@Testpublic void testClassLoader() throwsClassNotFoundException{/*//1、获取一个系统的类加载器(可以获取,当前这个类ReflecTest就是它加载的)

ClassLoader classLoader=ClassLoader.getSystemClassLoader();

System.out.println(classLoader);

//2、获取系统加载器的父类加载器(扩展器加载器,可以获取)

classLoader=classLoader.getParent();

System.out.println(classLoader);

//3、获取扩展类加载器的父类加载器(引导加载器,不可以获取)

classLoader=classLoader.getParent();

System.out.println(classLoader);

//4、测试当前类用哪个类加载器进行加载(系统类加载器)

classLoader=Class.forName("reflect.ReflectionTest").getClassLoader();

System.out.println(classLoader);

//5、测试JDK提供的Object类由哪个类加载器负责加载(引导类)

classLoader=Class.forName("java.lang.Object").getClassLoader();

System.out.println(classLoader);*/

//src目录下直接加载

InputStream in1=null;

in1=this.getClass().getResourceAsStream("text1.txt");//放在内部文件夹,要写全路径

InputStream in2=this.getClass().getResourceAsStream("reflect/text2.txt");

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值