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)的更多相关文章

  1. java基础知识回顾之javaIO类--java序列化和反序列化

    /** *  * 一:理解序列化反序列化及其应用 * 序列化:把堆内存的对象转化成字节流的过程. * 反序列化:把字节流序列恢复重构成对象的过程. * 对象的序列化的用途:1.把对象的字节序列持久化, ...

  2. Java类加载机制及自定义加载器

    转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...

  3. Java基础-DBCP连接池(BasicDataSource类)详解

    Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 ...

  4. 零基础怎么学Java?Java的运行机制是什么?Java入门基础!

    Java语言是当前流行的一种程序设计语言,因其安全性.平台无关性.性能优异等特点,受到广大编程爱好者的喜爱. 想学习Java语言的同学对于Java的运行机制是必须要了解的!! 计算机高级语言的类型主要 ...

  5. Java基础系列1:深入理解Java数据类型

    Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个 ...

  6. java基础思维导图,让java不再难懂

    java基础思维导图,让java不再难懂 原文链接  https://my.oschina.net/u/3080373/blog/873056 最近看了一些文章的思维导图,发现思维导图真是个强大的工具 ...

  7. Java基础加强-(注解,动态代理,类加载器,servlet3.0新特性)

    1.   Annotation注解 1.1.  Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annota ...

  8. Java基础学习总结(75)——Java反射机制及应用场景

    什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...

  9. 夯实Java基础系列12:深入理解Java中的反射机制

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

随机推荐

  1. CF 55 D. Beautiful numbers

    D. Beautiful numbers 链接 题意: 求[L,R]中多少个数字可以整除它们的每一位上的数字. 分析: 要求模一些数字等于0等价于模它们的lcm等于0,所以可以记录当前出现的数字的lc ...

  2. 【第六课】Nginx常用配置下详解

    目录 Nginx常用配置下详解 1.Nginx虚拟主机 2.部署wordpress开源博客 3.部署discuz开源论坛 4.域名重定向 5.Nginx用户认证 6.Nginx访问日志配置 7.Ngi ...

  3. vue-cli 3.0 图片路径问题(何时使用 public 文件夹)

    1. 图片放入public文件夹下时 参考:https://cli.vuejs.org/zh/guide/html-and-static-assets.html#public-%E6%96%87%E4 ...

  4. 详解C#7.0新特性

    1. out 变量(out variables) 以前我们使用out变量必须在使用前进行声明,C# 7.0 给我们提供了一种更简洁的语法 “使用时进行内联声明” .如下所示: 1 var input ...

  5. 写个发邮件的功能php的(全代码)

    ---恢复内容开始--- 正好做了个项目,需要在线留言,一般在线留言发邮件是很常见的方式,一开始从网上搜了很久都没有很全的,也有全一点的,但是也不能用,运行不成功,下面给大家分享一下运行成功了的全部代 ...

  6. UE4添加植被Foliage Type

    在UE4中的地形渲染上不可避免的需要添加植被,而如果采取手动添加StaticMesh植被的方式则会浪费大量的时间精力. UE4提供了一种批量添加地面植被类型的方式Foliage Type.在编辑器内容 ...

  7. Ubuntu 18.04下Couldn't connect to Docker daemon at http+docker://localunixsocket解决办法

    一台服务器系统为:Ubuntu 18.04 LTS,上面建了git裸仓库,用于开发吧代码push到这里.同时WEB测试环境通过docker也部署在这台.通过git钩子post-receive,当有新代 ...

  8. oozie 编译与安装

    oozie:4.3.1  hadoop 2.7.6 hive编译使用2.0.0参与编译不通过,但是可以指定为1.2.0,编译可以通过,后期不使用hive的action即可(也可以使用,但是可能会出现异 ...

  9. PAT甲题题解-1122. Hamiltonian Cycle (25)-判断路径是否是哈密顿回路

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789799.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  10. Linux内核分析 一二章读书笔记

    第一章 Linux内核简介 1.Unix (1)Unix系统很简洁 (2)在Unix中,所以东西都被当作文件对待,通过一套相同的系统调用接口来进行:open(),read(),write(),lsee ...