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. 由于未能创建 Microsoft Visual C# 2008 编译器,因此未能打开项目 "..."的解决方法

    如果遇到这种问题,我们通常只要在 Visual Studio 2017 的命令提示符工具里执行下列命令即可: devenv /resetskippkgs 如果还是不行的话,可以先把 Visual St ...

  2. eclipse中怎么找项目部署的路径和找编译后的class路径

    1.快捷键 ctrl+shift+R,会默认显示你的源文件.java的路径,如果没有.class的话,点击右上角的三角,选中  Show Derived Resource; 2.打开出现下图 3.按下 ...

  3. WebService技术,服务端发布到Tomcat(使用Servlet发布),客户端使用axis2实现(二)

    还是在WebService技术,服务端and客户端JDK-wsimport工具(一)的基础上实现.新建一个包:com.aixs2client.目录结构如下: 一.服务端: 1.还是使用com.webs ...

  4. webpack 支持的模块方法

    在webpack中支持的模块语法风格有:ES6,commonJS和AMD ES6风格(推荐) 在webpack2中,webpack支持ES6模块语法.这意味着在没有babel等工具处理的情况下你就可以 ...

  5. 11慕课网《进击Node.js基础(一)》Buffer和Stream

    Buffer 用来保存原始数据 (logo.png) 以下代码读取logo.png为buffer类型 然后将buffer转化为string,新建png 可以将字符串配置: data:image/png ...

  6. opencv2 用imwrite 抽取并保存视频图像帧

    最近在写一个车辆检测程序,程序中需要获取图像帧,并保存为图片,且放到指定目录中去,我在网上查了很多发现都是opencv1的有关操作,没有opencv2的操作,我参考网上的例子,结合着用opencv2新 ...

  7. 求二维数组联通子数组和的最大值 (联通涂色) beta!

    算法十分臃肿,效率捉鸡,不知用了多少循环,还有bug...任重道远,编程之美. 思想:按行遍历,找出每行的最大子数组.若行间都联通,行最大子数组相加后,再加上独立的正数.若行间不连通,找出较大子路径, ...

  8. Daily Scrum - 12/0809

    Meeting Minutes (08的Scrum报告放在word里,publish没有成功,所以这是08-09的报告,抱歉…): 卡片翻转的效果确认完成: 按钮蓄力的效果确认完成: 按钮上移的效果确 ...

  9. 各组Beta版本发布点评

    1.  新蜂:俄罗斯方块 俄罗斯方块已经基本完成了所有功能,运行流畅,也加入了之前用户期待的即将降落的方块和游戏积分的功能,用户还能随时暂停和继续游戏. 2. 天天向上: 连连看游戏 连连看游戏在核心 ...

  10. k8s 实验过程中遇到的两个小问题 端口 和 批量删除Error的pods

    1. 自己kubeadm搭建的一套k8s系统 然后进行做实验 发现了几个问题 jenkins 创建 salves的时候总是有问题.  提示注册不上 然后 我修改了下yaml文件 暴露端口 50000 ...