day15-类加载器&反射&模块化

1. 类加载器
1.1 类加载【理解】
类加载的描述
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始
化这三个步骤来对类进行初始化。如果不出现意外情况, JVM 将会连续完成这三个步骤,所以有时也把
这三个步骤统称为类加载或者类初始化
类的加载
就是指将 class 文件读入内存,并为之创建一个 java.lang.Class 对象
任何类被使用时,系统都会为之建立一个 java.lang.Class 对象
类的连接
验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
准备阶段:负责为类的类变量分配内存,并设置默认初始化值
解析阶段:将类的二进制数据中的符号引用替换为直接引用
类的初始化
在该阶段,主要就是对类变量进行初始化
类的初始化步骤
假如类还未被加载和连接,则程序先加载并连接该类
假如该类的直接父类还未被初始化,则先初始化其直接父类
假如类中有初始化语句,则系统依次执行这些初始化语句
注意:在执行第 2 个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤 1-3
类的初始化时机
创建类的实例
调用类的类方法
访问类或者接口的类变量,或者为该类变量赋值
使用反射方式来强制创建某个类或接口对应的 java.lang.Class 对象
初始化某个类的子类
直接使用 java.exe 命令来运行某个主类
1.2 类加载器【理解】
1.2.1 类加载器的作用
负责将 .class 文件加载到内存中,并为之生成对应的 java.lang.Class 对象。虽然我们不用过分关心类加载机
制,但是了解这个机制我们就能更好的理解程序的运行!
1.2.2JVM 的类加载机制
全盘负责:就是当一个类加载器负责加载某个 Class 时,该 Class 所依赖的和引用的其他 Class 也将由该类加载
器负责载入,除非显示使用另外一个类加载器来载入
父类委托:就是当一个类加载器负责加载某个 Class 时,先让父类加载器试图加载该 Class ,只有在父类加载器
无法加载该类时才尝试从自己的类路径中加载该类
缓存机制:保证所有加载过的 Class 都会被缓存,当程序需要使用某个 Class 对象时,类加载器先从缓存区中搜
索该 Class ,只有当缓存区中不存在该 Class 对象时,系统才会读取该类对应的二进制数据,并将其转换成 Class 对象,存储到缓存区
1.2.3Java 中的内置类加载器
Bootstrap class loader :它是虚拟机的内置类加载器,通常表示为 null ,并且没有父 null
Platform class loader :平台类加载器可以看到所有平台类 ,平台类包括由平台类加载器或其祖先定义的 Java
SE 平台 API ,其实现类和 JDK 特定的运行时类
System class loader :它也被称为应用程序类加载器 ,与平台类加载器不同。 系统类加载器通常用于定义应
用程序类路径,模块路径和 JDK 特定工具上的类
类加载器的继承关系: System 的父加载器为 Platform ,而 Platform 的父加载器为 Bootstrap
1.2.4ClassLoader 中的两个方法
方法名
说明
static ClassLoader getSystemClassLoader()
返回用于委派的系统类加载器
ClassLoader getParent()
返回父类加载器进行委派
方法分类
示例代码
2. 反射
2.1 反射的概述【理解】
是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。
由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展
2.2 获取 Class 类对象的三种方式【应用】
2.2.1 三种方式分类
类名 .class 属性
对象名 .getClass() 方法
public class ClassLoaderDemo {
public static void main ( String [] args ) {
//static ClassLoader getSystemClassLoader() :返回用于委派的系统类加载器
ClassLoader c = ClassLoader . getSystemClassLoader ();
System . out . println ( c ); //AppClassLoader
//ClassLoader getParent() :返回父类加载器进行委派
ClassLoader c2 = c . getParent ();
System . out . println ( c2 ); //PlatformClassLoader
ClassLoader c3 = c2 . getParent ();
System . out . println ( c3 ); //null
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14 Class.forName( 全类名 ) 方法
2.2.2 示例代码
2.3 反射获取构造方法并使用【应用】
2.3.1Class 类获取构造方法对象的方法
方法名
说明
Constructor<?>[] getConstructors()
返回所有公共构造方法对象的数
Constructor<?>[] getDeclaredConstructors()
返回所有构造方法对象的数组
Constructor getConstructor(Class<?>... parameterTypes)
返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>...
parameterTypes)
返回单个构造方法对象
方法分类
示例代码
public class ReflectDemo {
public static void main ( String [] args ) throws ClassNotFoundException {
// 使用类的 class 属性来获取该类对应的 Class 对象
Class < Student > c1 = Student . class ;
System . out . println ( c1 );
Class < Student > c2 = Student . class ;
System . out . println ( c1 == c2 );
System . out . println ( "--------" );
// 调用对象的 getClass() 方法,返回该对象所属类对应的 Class 对象
Student s = new Student ();
Class <? extends Student > c3 = s . getClass ();
System . out . println ( c1 == c3 );
System . out . println ( "--------" );
// 使用 Class 类中的静态方法 forName(String className)
Class <?> c4 = Class . forName ( "com.itheima_02.Student" );
System . out . println ( c1 == c4 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ReflectDemo01 {
public static void main ( String [] args ) throws ClassNotFoundException ,
NoSuchMethodException , IllegalAccessException , InvocationTargetException ,
InstantiationException {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
1
2
3
4 方法名
说明
T newInstance(Object...initargs)
根据指定的构造方法创建对象
2.3.2Constructor 类用于创建对象的方法
2.4 反射获取构造方法并使用练习 1 【应用】
案例需求
通过反射获取公共的构造方法并创建对象
代码实现
学生类
//Constructor<?>[] getConstructors() 返回一个包含 Constructor 对象的数组,
Constructor 对象反映了由该 Class 对象表示的类的所有公共构造函数
// Constructor<?>[] cons = c.getConstructors();
//Constructor<?>[] getDeclaredConstructors() 返回反映由该 Class 对象表示的类
声明的所有构造函数的 Constructor 对象的数组
Constructor <?> [] cons = c . getDeclaredConstructors ();
for ( Constructor con : cons ) {
System . out . println ( con );
}
System . out . println ( "--------" );
//Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个
Constructor 对象,该对象反映由该 Class 对象表示的类的指定公共构造函数
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回
一个 Constructor 对象,该对象反映由此 Class 对象表示的类或接口的指定构造函数
// 参数:你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象
Constructor <?> con = c . getConstructor ();
//Constructor 提供了一个类的单个构造函数的信息和访问权限
//T newInstance(Object... initargs) 使用由此 Constructor 对象表示的构造函数,
使用指定的初始化参数来创建和初始化构造函数的声明类的新实例
Object obj = con . newInstance ();
System . out . println ( obj );
// Student s = new Student();
// System.out.println(s);
}
}
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Student {
// 成员变量:一个私有,一个默认,一个公共
private String name ;
int age ;
public String address ;
// 构造方法:一个私有,一个默认,两个公共
1
2
3
4
5
6
7 测试类
public Student () {
}
private Student ( String name ) {
this . name = name ;
}
Student ( String name , int age ) {
this . name = name ;
this . age = age ;
}
public Student ( String name , int age , String address ) {
this . name = name ;
this . age = age ;
this . address = address ;
}
// 成员方法:一个私有,四个公共
private void function () {
System . out . println ( "function" );
}
public void method1 () {
System . out . println ( "method" );
}
public void method2 ( String s ) {
System . out . println ( "method:" + s );
}
public String method3 ( String s , int i ) {
return s + "," + i ;
}
@Override
public String toString () {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}' ;
}
}
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class ReflectDemo02 {
public static void main ( String [] args ) throws ClassNotFoundException ,
NoSuchMethodException , IllegalAccessException , InvocationTargetException ,
InstantiationException {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
1
2
3
4 2.5 反射获取构造方法并使用练习 2 【应用】
案例需求
通过反射获取私有构造方法并创建对象
代码实现
学生类:参见上方学生类
测试类
2.6 反射获取成员变量并使用【应用】
2.6.1Class 类获取成员变量对象的方法
方法分类
//public Student(String name, int age, String address)
//Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor <?> con = c . getConstructor ( String . class , int . class ,
String . class );
// 基本数据类型也可以通过 .class 得到对应的 Class 类型
//T newInstance(Object... initargs)
Object obj = con . newInstance ( " 林青霞 " , 30 , " 西安 " );
System . out . println ( obj );
}
}
5
6
7
8
9
10
11
12
13
14
15
public class ReflectDemo03 {
public static void main ( String [] args ) throws ClassNotFoundException ,
NoSuchMethodException , IllegalAccessException , InvocationTargetException ,
InstantiationException {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
//private Student(String name)
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor <?> con = c . getDeclaredConstructor ( String . class );
// 暴力反射
//public void setAccessible(boolean flag): 值为 true ,取消访问检查
con . setAccessible ( true );
Object obj = con . newInstance ( " 林青霞 " );
System . out . println ( obj );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 方法名
说明
Field[] getFields()
返回所有公共成员变量对象的数组
Field[] getDeclaredFields()
返回所有成员变量对象的数组
Field getField(String name)
返回单个公共成员变量对象
Field getDeclaredField(String name)
返回单个成员变量对象
示例代码
public class ReflectDemo01 {
public static void main ( String [] args ) throws ClassNotFoundException ,
NoSuchFieldException , NoSuchMethodException , IllegalAccessException ,
InvocationTargetException , InstantiationException {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
//Field[] getFields() 返回一个包含 Field 对象的数组, Field 对象反映由该 Class
象表示的类或接口的所有可访问的公共字段
//Field[] getDeclaredFields() 返回一个 Field 对象的数组,反映了由该 Class 对象
表示的类或接口声明的所有字段
// Field[] fields = c.getFields();
Field [] fields = c . getDeclaredFields ();
for ( Field field : fields ) {
System . out . println ( field );
}
System . out . println ( "--------" );
//Field getField(String name) 返回一个 Field 对象,该对象反映由该 Class 对象表
示的类或接口的指定公共成员字段
//Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映由该
Class 对象表示的类或接口的指定声明字段
Field addressField = c . getField ( "address" );
// 获取无参构造方法创建对象
Constructor <?> con = c . getConstructor ();
Object obj = con . newInstance ();
// obj.addressField = " 西安 ";
//Field 提供有关类或接口的单个字段的信息和动态访问
//void set(Object obj, Object value) 将指定的对象参数中由此 Field 对象表示的字
段设置为指定的新值
addressField . set ( obj , " 西安 " ); // obj 的成员变量 addressField 赋值为西安
System . out . println ( obj );
// Student s = new Student();
// s.address = " 西安 ";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 方法名
说明
voidset(Object obj,Object value)
obj 对象的成员变量赋值为 value
2.6.2Field 类用于给成员变量赋值的方法
2.7 反射获取成员变量并使用练习【应用】
案例需求
通过反射获取成员变量并赋值
代码实现
学生类:参见上方学生类
测试类
// System.out.println(s);
}
}
35
36
37
public class ReflectDemo02 {
public static void main ( String [] args ) throws Exception {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
//Student s = new Student();
Constructor <?> con = c . getConstructor ();
Object obj = con . newInstance ();
System . out . println ( obj );
//s.name = " 林青霞 ";
// Field nameField = c.getField("name"); //NoSuchFieldException:
name
Field nameField = c . getDeclaredField ( "name" );
nameField . setAccessible ( true );
nameField . set ( obj , " 林青霞 " );
System . out . println ( obj );
//s.age = 30;
Field ageField = c . getDeclaredField ( "age" );
ageField . setAccessible ( true );
ageField . set ( obj , 30 );
System . out . println ( obj );
//s.address = " 西安 ";
Field addressField = c . getDeclaredField ( "address" );
addressField . setAccessible ( true );
addressField . set ( obj , " 西安 " );
System . out . println ( obj );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 2.8 反射获取成员方法并使用【应用】
2.8.1Class 类获取成员方法对象的方法
方法名
说明
Method[] getMethods()
返回所有公共成员方法对象的数组,包
括继承的
Method[] getDeclaredMethods()
返回所有成员方法对象的数组,不包括
继承的
Method getMethod(String name, Class<?>...
parameterTypes)
返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>...
parameterTypes)
返回单个成员方法对象
方法分类
示例代码
public class ReflectDemo01 {
public static void main ( String [] args ) throws Exception {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
//Method[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映由该 Class
象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超级接口继承的类
//Method[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映由
Class 对象表示的类或接口的所有声明方法,包括 public protected default package )访问和私
有方法,但不包括继承方法
// Method[] methods = c.getMethods();
Method [] methods = c . getDeclaredMethods ();
for ( Method method : methods ) {
System . out . println ( method );
}
System . out . println ( "--------" );
//Method getMethod(String name, Class<?>... parameterTypes) 返回一个 方法
对象,该对象反映由该 Class 对象表示的类或接口的指定公共成员方法
//Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回
一个 方法对象,它反映此表示的类或接口的指定声明的方法 Class 对象
//public void method1()
Method m = c . getMethod ( "method1" );
// 获取无参构造方法创建对象
Constructor <?> con = c . getConstructor ();
Object obj = con . newInstance ();
// obj.m();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 方法名
说明
Objectinvoke(Object obj,Object... args)
调用 obj 对象的成员方法,参数是 args, 返回值是 Object 类型
2.8.2Method 类用于执行方法的方法
2.9 反射获取成员方法并使用练习【应用】
案例需求
通过反射获取成员方法并调用
代码实现
学生类:参见上方学生类
测试类
// 在类或接口上提供有关单一方法的信息和访问权限
//Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此
方法对象表示的基础方法
//Object :返回值类型
//obj :调用方法的对象
//args :方法需要的参数
m . invoke ( obj );
// Student s = new Student();
// s.method1();
}
}
26
27
28
29
30
31
32
33
34
35
36
public class ReflectDemo02 {
public static void main ( String [] args ) throws Exception {
// 获取 Class 对象
Class <?> c = Class . forName ( "com.itheima_02.Student" );
//Student s = new Student();
Constructor <?> con = c . getConstructor ();
Object obj = con . newInstance ();
//s.method1();
Method m1 = c . getMethod ( "method1" );
m1 . invoke ( obj );
//s.method2(" 林青霞 ");
Method m2 = c . getMethod ( "method2" , String . class );
m2 . invoke ( obj , " 林青霞 " );
// String ss = s.method3(" 林青霞 ",30);
// System.out.println(ss);
Method m3 = c . getMethod ( "method3" , String . class , int . class );
Object o = m3 . invoke ( obj , " 林青霞 " , 30 );
System . out . println ( o );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 2.10 反射的案例【应用】
2.10.1 反射练习之越过泛型检查
案例需求
通过反射技术,向一个泛型为 Integer 的集合中添加一些字符串数据
代码实现
2.10.2 运行配置文件中指定类的指定方法
案例需求
通过反射运行配置文件中指定类的指定方法
代码实现
//s.function();
// Method m4 = c.getMethod("function"); //NoSuchMethodException:
com.itheima_02.Student.function()
Method m4 = c . getDeclaredMethod ( "function" );
m4 . setAccessible ( true );
m4 . invoke ( obj );
}
}
24
25
26
27
28
29
30
public class ReflectTest01 {
public static void main ( String [] args ) throws Exception {
// 创建集合
ArrayList < Integer > array = new ArrayList < Integer > ();
// array.add(10);
// array.add(20);
// array.add("hello");
Class <? extends ArrayList > c = array . getClass ();
Method m = c . getMethod ( "add" , Object . class );
m . invoke ( array , "hello" );
m . invoke ( array , "world" );
m . invoke ( array , "java" );
System . out . println ( array );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ReflectTest02 {
public static void main ( String [] args ) throws Exception {
// 加载数据
Properties prop = new Properties ();
FileReader fr = new FileReader ( "myReflect\\class.txt" );
prop . load ( fr );
fr . close ();
1
2
3
4
5
6
7
8 3. 模块化
3.1 模块化概述【理解】
Java 语言随着这些年的发展已经成为了一门影响深远的编程语言,无数平台,系统都采用 Java 语言编写。但是,伴
随着发展, Java 也越来越庞大,逐渐发展成为一门 臃肿 的语言。而且,无论是运行一个大型的软件系统,还是运
行一个小的程序,即使程序只需要使用 Java 的部分核心功能, JVM 也要加载整个 JRE 环境。 为了给 Java“ 瘦身 ,让
Java 实现轻量化, Java 9 正式的推出了模块化系统。 Java 被拆分为 N 多个模块,并允许 Java 程序可以根据需要选择加
载程序必须的 Java 模块,这样就可以让 Java 以轻量化的方式来运行
其实, Java 7 的时候已经提出了模块化的概念,但由于其过于复杂, Java 7 Java 8 都一直未能真正推出,直到 Java
9 才真正成熟起来。对于 Java 语言来说,模块化系统是一次真正的自我革新,这种革新使得 古老而庞大 Java 语言
重新焕发年轻的活力
3.2 模块的基本使用【应用】
1. 在项目中创建两个模块。一个是 myOne, 一个是 myTwo
2. myOne 模块中创建以下包和以下类,并在类中添加方法
/*
className=com.itheima_06.Student
methodName=study
*/
String className = prop . getProperty ( "className" );
String methodName = prop . getProperty ( "methodName" );
// 通过反射来使用
Class <?> c = Class . forName ( className ); //com.itheima_06.Student
Constructor <?> con = c . getConstructor ();
Object obj = con . newInstance ();
Method m = c . getMethod ( methodName ); //study
m . invoke ( obj );
}
}
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 3. myTwo 模块中创建以下包和以下类,并在类中创建对象并使用
4. myOne 模块中 src 目录下,创建 module-info.java ,并写入以下内容
5. myTwo 模块中 src 目录下,创建 module-info.java ,并写入以下内容 3.3 模块服务的基本使用【应用】
1. myOne 模块中新建一个包,提供一个接口和两个实现类
2. myOne 模块中修改 module-info.java 文件,添加以下内容 3. myTwo 模块中新建一个测试类
4. myTwo 模块中修改 module-info.java 文件,添加以下内容
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值