Java基础-类加载机制与自定义类Java类加载器(ClassLoader)
Java基础-类加载机制与自定义类Java类加载器(ClassLoader)
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
关于类加载器的概念和分类我就不再废话了,因为我在之前的笔记已经提到过了,详细能看到这篇文章的这些概念应该都烂熟于胸啦!如果你是一名小白的话可以参考我以前的笔记:https://www.cnblogs.com/yinzhengjie/p/9272289.html。本篇博客的重点侧重三点,第一,测试静态代码块;第二,编写自定义类加载器;第三,验证四级类加载机制。
一.测试静态代码块
1>.静态代码块的作用
答:静态代码块的作用说白了跟构造方法的功能类似,他们都可以给类的成员变量进行赋值操作,我们可以简单的理解为静态代码块是为了给类初始化,构造方法是为了给对象初始化。
2>.静态代码块在加载类的必须会被执行吗?
答:答案是否定的,我们在加载类的时候,可以不指定加载静态代码块。但是,只要你新建一个实例或者是通过反射的方式创建一个实例,依然还是会触发静态代码块的执行。我们在加载类是指定不加载静态代码块说白了只是延时它的加载,因为在实例化的过程中依然会加载!
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.jvm; public class Person {
public String name;
private int age;
public String sex; static {
System.out.println("I'm yinzhengjie !!!");
} public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
} public Person() { } public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} @Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}';
}
}
Person.java 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.jvm; import org.junit.Test; import java.lang.reflect.Field; public class TestJVM { @Test
public void testClassLoader() throws Exception {
//通过ClassLoader.getSystemClassLoader()获取系统加载类,将类的初始化操作设置为false.
Class c1 = Class.forName("cn.org.yinzhengjie.jvm.Person",false,ClassLoader.getSystemClassLoader());
Field name = c1.getDeclaredField("name");
System.out.println(name);
}
} /*
以上代码输出结果如下:
public java.lang.String cn.org.yinzhengjie.jvm.Person.name
*/
TestJVM.java 文件内容(不指定加载静态代码块)
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.jvm; import org.junit.Test; import java.lang.reflect.Field; public class TestJVM { @Test
public void testClassLoader() throws Exception {
//通过ClassLoader.getSystemClassLoader()获取系统加载类,将类的初始化操作设置为false.
Class c1 = Class.forName("cn.org.yinzhengjie.jvm.Person",false,ClassLoader.getSystemClassLoader());
Field field = c1.getDeclaredField("name");
System.out.println(field);
//虽然上面的代码再加载类的过程中设置禁用静态代码块的加载,通过反射获取到的时候依然会触发静态代码块的执行!
Object obj = c1.newInstance();
field.set(obj,"尹正杰");
System.out.println(obj);
}
} /*
以上代码输出结果如下:
public java.lang.String cn.org.yinzhengjie.jvm.Person.name
I'm yinzhengjie !!!
Person{name='尹正杰', age=0, sex='null'}
*/
TestJVM.java 文件内容(反射触发静态代码块的执行)
二.编写自定义类加载器
1>.编写自定义类加载器
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.jvm; import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; /**
* 自定义ClassLoader
*/
public class MyClassLoader extends ClassLoader {
protected Class<?> findClass(String name) {
try {
String path = "D:\\BigData\\JavaSE\\yinzhengjieData\\" + name + ".class" ;
FileInputStream in = new FileInputStream(path) ;
ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
byte[] buf = new byte[1024] ;
int len = -1 ;
while((len = in.read(buf)) != -1){
baos.write(buf , 0 , len);
}
in.close();
byte[] classBytes = baos.toByteArray();
return defineClass(classBytes , 0 , classBytes.length) ;
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}
2>.调用自定义类加载器
在“D:\BigData\JavaSE\yinzhengjieData”目录下编写测试代码如下:
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ public class Yinzhengjie {
private String name;
private int age;
static {
System.out.println("I'm yinzhengjie !");
} public Yinzhengjie(String name, int age) {
this.name = name;
this.age = age;
} public Yinzhengjie() {
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Yinzhengjie{" + "Name = " + name + ", Age = " + age + '}';
}
}
Yinzhengjie.java 文件内容
使用javac命令编译Java代码。
调用咱们自定义的类加载器,测试代码如下:
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.jvm; import java.lang.reflect.Constructor; public class MyClassLoaderApp {
public static void main(String[] args) {
//创建自定义类加载器实例
ClassLoader cl = new MyClassLoader() ;
cl.getParent();
try {
Class clz = cl.loadClass("Yinzhengjie") ;
Constructor constructor = clz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("尹正杰", 18);
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
} /*
以上代码执行结果如下:
I'm yinzhengjie !
Yinzhengjie{Name = 尹正杰, Age = 18}
*/
三.验证四级类加载机制
1>.根类加载器是得不到的
2>.得到扩展类加载器
3>.得到系统类加载器
4>.得到自定义加载器
Java基础-类加载机制与自定义类Java类加载器(ClassLoader)的更多相关文章
- java基础知识回顾之javaIO类--java序列化和反序列化
/** * * 一:理解序列化反序列化及其应用 * 序列化:把堆内存的对象转化成字节流的过程. * 反序列化:把字节流序列恢复重构成对象的过程. * 对象的序列化的用途:1.把对象的字节序列持久化, ...
- Java类加载机制及自定义加载器
转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...
- Java基础-DBCP连接池(BasicDataSource类)详解
Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 ...
- 零基础怎么学Java?Java的运行机制是什么?Java入门基础!
Java语言是当前流行的一种程序设计语言,因其安全性.平台无关性.性能优异等特点,受到广大编程爱好者的喜爱. 想学习Java语言的同学对于Java的运行机制是必须要了解的!! 计算机高级语言的类型主要 ...
- Java基础系列1:深入理解Java数据类型
Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个 ...
- java基础思维导图,让java不再难懂
java基础思维导图,让java不再难懂 原文链接 https://my.oschina.net/u/3080373/blog/873056 最近看了一些文章的思维导图,发现思维导图真是个强大的工具 ...
- Java基础加强-(注解,动态代理,类加载器,servlet3.0新特性)
1. Annotation注解 1.1. Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annota ...
- Java基础学习总结(75)——Java反射机制及应用场景
什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...
- 夯实Java基础系列12:深入理解Java中的反射机制
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
随机推荐
- R语言学习 第五篇:字符串操作
文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符. 一,字符串中的字符数量 函数nchar()用于获得字符串中的字符数量: > s ...
- Join 和 Apply 用法全解
在关系型数据库系统中,为了满足第三范式(3NF),需要将满足“传递依赖”的表分离成单独的表,通过Join 子句将相关表进行连接,Join子句共有三种类型:外连接,内连接,交叉连接:外连接分为:left ...
- Harbor私有镜像仓库无坑搭建
转载:https://k8s.abcdocker.com/kubernetes_harbor.html 一.介绍 Docker容器应用的开发和运行路不开可靠的镜像管理,虽然Docker官方也提供了公共 ...
- Python中 list, numpy.array, torch.Tensor 格式相互转化
1.1 list 转 numpy ndarray = np.array(list) 1.2 numpy 转 list list = ndarray.tolist() 2.1 list 转 torch. ...
- python类属性在继承中的修改的影响
class A(object): x = 1 class B(A): pass class C(A): pass # 通过父类修改类属性,子类继承的类属性也改变 A.x = 3 print(A.x, ...
- Mac 绑定Gitlab或者GitHub帐号,从新生成公钥
1.SSH(Secure Shell)是一种安全协议,在你的电脑与GitLab服务器进行通信时,我们使用SSH密钥(SSH Keys)认证的方式来保证通信安全. 2.创建 SSH密钥,并将密钥中的公钥 ...
- Beta 冲刺 四
团队成员 051601135 岳冠宇 031602629 刘意晗 031602248 郑智文 031602330 苏芳锃 031602234 王淇 照片 项目进展 岳冠宇 昨天的困难 数据交换比较复杂 ...
- 使用maven的插件进行maven项目的打包
1 maven项目打包的插件有3种 maven-jar-plugin maven-assembly-plugin maven-shade-plugin 2 maven-jar-plugin 现在要新增 ...
- Win2019 preview 版本的安装过程
1. 加入 windows insider 协议 登录自己的账号 同意 insder 协议. 然后 https://www.microsoft.com/en-us/software-download/ ...
- DevExpress15.2+VS2015 破解、汉化
破解 下载有效的激活工具DEV15.X在VS2015 (亲测),地址 http://download.csdn.net/download/u011149525/9581176 解压后的注册说明: 感谢 ...