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. 修改 input[type="radio"] 和 input[type="checkbox"] 的默认样式

    表单中,经常会使用到单选按钮和复选框,但是,input[type="radio"] 和 input[type="checkbox"] 的默认样式在不同的浏览器或 ...

  2. c语言连接mysql数据库的实现方法

    C语言连接mysql数据库,需要相应的头文件和lib文件,如果你安装Mysql数据库,会在安装目录下找到这些库文件,如果没有安装,也可以在网上找到 我这里也有一份网上找到的:/201205/other ...

  3. Spring的单例模式底层实现学习笔记

    单例模式也属于创建型模式,所谓单例,顾名思义,所指的就是单个实例,也就是说要保证一个类仅有一个实例.单例模式有以下的特点:①单例类只能有一个实例②单例类必须自己创建自己的唯一实例③单例类必须给所有其他 ...

  4. TDD 与 CI 在 Python 中的实践

    社区化产品的长久生存之道可能莫过于对迭代周期的控制.还记得以前采用老土的阶段开发的年代,将软件生命周期分为各个阶段,当到达每个阶段的里程碑则集中所有的资源.人力作全面冲刺.每次到了里程碑的检查点冲过了 ...

  5. golang高性能端口扫描

    前言 最近有个小项目的需要,使用golang写了个端口扫描工具,不得不说golang的效率确实比python快的太多了.在使用一段时间golang之后,感觉有三个方面是优于python的: 一个方面是 ...

  6. 红黑树插入与删除完整代码(dart语言实现)

    之前分析了红黑树的删除,这里附上红黑树的完整版代码,包括查找.插入.删除等.删除后修复实现了两种算法,均比之前的更为简洁.一种是我自己的实现,代码非常简洁,行数更少:一种是Linux.Java等源码版 ...

  7. 读C#程序(第三周)

    阅读下面程序,请回答如下问题: 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出第一个结果?时间 ...

  8. 读C#程序

    阅读下面程序,请回答如下问题: 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出第一个结果?时间 ...

  9. 三步轻松搞定delphi中CXGRID手动添加复表头(多行表头,报表头)

    网上有代码动态生成cxgrid多行表头的源码,地址为:http://mycreature.blog.163.com/blog/static/556317200772524226400/ 如果要手动设计 ...

  10. node之文件的静态资源的托管

    /** * 文件的静态资源托管 */ let express = require('express'); let path =require('path'); let app = express(); ...