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 喜欢的话麻烦点下 ...
随机推荐
- 解决Git在添加ignore文件之前就提交了项目无法再过滤问题
由于未添加ignore文件造成提交的项目很大(包含生成的二进制文件).所以我们可以将编译生成的文件进行过滤,避免添加到版本库中了. 首先为避免冲突需要先同步下远程仓库 $ git pull 在本地项目 ...
- TMS320VC5509片内ADC采集
1. ADC采集比较简单,内部的10位的ADC,AIN0-AIN3的输入,主要是用的CSL的库函数#include <csl_adc.h> ; Uint16 samplestoraage[ ...
- numpy 初识(三)
基本运算 exp: e sqrt:开放 floor:向下取整 ravel:矩阵拉成一个向 T:转置(行和列变换) 改变形状: resize: 更改其形状(返回值为None)a.resize(6,2) ...
- Jmeter(十九)_ForEach控制器实现网页爬虫
一直以来,爬虫似乎都是写代码去实现的,今天像大家介绍一下Jmeter如何实现一个网页爬虫! 龙渊阁测试开发家园 317765580 Jmeter的爬虫原理其实很简单,就是对网页提交一个请求,然后把返回 ...
- Loadrunner 面试常见问题
三大组件: 脚本生成器,录制和调试脚本 . 控制台,设置运行和资源场景 结果分析器,将测试结果数据以不同的图表呈现,便于性能分析 工作原理: 录制:根据不同协议,记录下客户端和服务器二者之间的对话,生 ...
- C++基础知识(1)
C语言是结构化编程语言(for循环.while循环.do while循环和if else语句),将低级语言的效率.硬件访问能力和高级语言的通用性.可移植性融合在一起. UNIX编译和链接 UNIX用C ...
- Google Kickstart Round.B C. Diverse Subarray
这题又是万恶的线段树 maxx[j]存储的是 l = xxx, r = j的时候的答案 我们会让 l 从 1到n 的遍历中,查询线段树的[l, n]中最大的答案 因为query的下界是n,所以单次查询 ...
- 强化学习算法DQN
1 DQN的引入 由于q_learning算法是一直更新一张q_table,在场景复杂的情况下,q_table就会大到内存处理的极限,而且在当时深度学习的火热,有人就会想到能不能将从深度学习中借鉴方法 ...
- centos上部署mysql
本文记录整个安装的过程和跳进的坑,大家预祝我能从坑里爬出来吧 当前系统版本 开始我们的安装: 在安装之前查阅了部分资料,大体安装流程 yum -y install mysql yum -y insta ...
- PAT-1045. Favorite Color Stripe (30)-LIS
将Eva喜欢的颜色按顺序编个优先级, 2 3 1 5 6-> 1 2 3 4 5 然后读取stripe,将Eva不喜欢的先剔除掉,剩下的颜色替换为相应的优先级 2 2 4(去掉) 1 5 5 6 ...