Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。
对于 Java 虚拟机来说,如果两个类不同,试图对这两个类的对象进行相互赋值,会抛出运行时异常 ClassCastException
。
//文件Sample.java
package com.luke;
public class Sample
{
private Sample instance;
public void setSample(Object instance) {
this.instance = (Sample) instance;
}
public void out(String msg)
{
System.out.println(msg);
}
}
//文件Test.java
package com.luke;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class MyClassLoader extends ClassLoader
{
public Class loadClassMy(String path, String name, boolean resolve) throws ClassNotFoundException
{
Class klass = null;
try
{
klass = findLoadedClass(name); //检查该类是否已经被装载。
if (klass != null)
{
System.out.println("该类已经加载了");
return klass;
}
byte[] bs = getClassBytes(path, name);//从一个特定的信息源寻找并读取该类的字节。
if (bs != null && bs.length > 0)
{
klass = defineClass(name, bs, 0, bs.length);
}
if (klass == null)
{ //如果读取字节失败,则试图从JDK的系统API中寻找该类。
klass = findSystemClass(name);
}
if (resolve && klass != null)
{
resolveClass(klass);
}
}
catch (IOException e)
{
throw new ClassNotFoundException(e.toString());
}
System.out.println("klass == " + klass);
return klass;
}
private byte[] getClassBytes(String path, String className) throws IOException
{
//String path = System.getProperty("java.class.path") + File.separator;
path += className.replace('.', File.separatorChar) + ".class";
System.out.println(path);
FileInputStream fis = null;
try
{
fis = new FileInputStream(path);
}
catch (FileNotFoundException e)
{
System.out.println(e);
return null; //如果查找失败,则放弃查找。捕捉这个异常主要是为了过滤JDK的系统API。
}
byte[] bs = new byte[fis.available()];
fis.read(bs);
return bs;
}
}
public class Test
{
/**
* @description
* @param
* @return void
* @author luke
* @date 2013-5-23
* @version
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
//System.out.println(System.getProperty("java.class.path") + File.separatorChar);
try
{
MyClassLoader loader = new MyClassLoader();
MyClassLoader loader1 = new MyClassLoader();
//--------------测试1
/**
* 1.sun.misc.Launcher$AppClassLoader@190d11################sun.misc.Launcher$AppClassLoader@190d11
* sun.misc.Launcher$AppClassLoader@190d11****************sun.misc.Launcher$AppClassLoader@190d11
*/
Class c = loader.loadClass("com.luke.Sample");
Class c1 = loader1.loadClass("com.luke.Sample");
/*Class c = Sample.class;
Class c1 = Class.forName("com.luke.Sample");*/
System.out.println(c.getClassLoader() + "################" + c1.getClassLoader());
/**
*Test.class与Sample.class都在classpath路径下;
* 因为Test的加载器是系统加载器即sun.misc.Launcher$AppClassLoader@190d11,
* 根据加载器代理委托机制,c和c1的加载器也是sun.misc.Launcher$AppClassLoader@190d11,
* 类的全名又相同, 所以类相同, 可以强制转换,Test类也能看见Sample类.
*/
Sample o = (Sample)c.newInstance();
Sample o1 = (Sample)c1.newInstance();
System.out.println(o.getClass().getClassLoader() + "****************" + o1.getClass().getClassLoader());
o.out("hello world!");
Method setSampleMethod = c.getMethod("setSample", java.lang.Object.class);
setSampleMethod.invoke(o, o1);
Method m = c.getMethod("out", java.lang.String.class);
m.invoke(o, "你好");
//--------------测试1
//----------------------------测试2
/**
* 2.com.luke.MyClassLoader@10b30a7################com.luke.MyClassLoader@10b30a7
* com.luke.MyClassLoader@10b30a7****************com.luke.MyClassLoader@10b30a7
*/
Class c = loader.loadClassMy("D:\\workspace\\SSHDemo\\Web\\WEB-INF\\classes\\", "com.luke.Sample", false);
Class c1 = loader.loadClassMy("D:\\workspace\\SSHDemo\\Web\\WEB-INF\\classes\\", "com.luke.Sample", false);
System.out.println(c.getClassLoader() + "################" + c1.getClassLoader());
/**
*Test.class在classpath路径下,但Sample.class在D:\workspace\SSHDemo\Web\WEB-INF\classes\com\luke\下;
* 因为Test的加载器是系统加载器即sun.misc.Launcher$AppClassLoader@190d11,
* 根据加载器代理委托机制,c和c1的加载器都是自定义加载器com.luke.MyClassLoader@10b30a7,
* 虽然类的全名相同,Test与右边的c与c1的加载器不同, c与c1的加载器的父加载器是系统加载器,父加载器加载的类不能看见子加载器加载的类, 下面的实例不可以转换, 会报异常ClassCastException.
*/
/*Sample o = (Sample)c.newInstance();
Sample o1 = (Sample)c1.newInstance();
((Sample)o).out("hello world!");*/
Object o = c.newInstance();
Object o1 = c1.newInstance();
System.out.println(o.getClass().getClassLoader() + "****************" + o1.getClass().getClassLoader());
/**
* c和c1的加载器都是自定义加载器即com.luke.MyClassLoader@10b30a7,
* 类的全名又相同, 所以类相同, o与o1类型相同, 可以赋值.
*/
Method setSampleMethod = c.getMethod("setSample", java.lang.Object.class);
setSampleMethod.invoke(o, o1);
Method m = c.getMethod("out", java.lang.String.class);
m.invoke(o, "你好");
//----------------------------测试2
//----------------------------测试3
/**
* 2.com.luke.MyClassLoader@10b30a7################com.luke.MyClassLoader@1b67f74
* com.luke.MyClassLoader@10b30a7****************com.luke.MyClassLoader@1b67f74
*/
/* Class c = loader.loadClassMy("D:\\workspace\\Demo\\bin\\", "com.luke.Sample", false);
Class c1 = loader1.loadClassMy("D:\\workspace\\SSHDemo\\Web\\WEB-INF\\classes\\", "com.luke.Sample", false); */
Class c = loader.loadClassMy("D:\\workspace\\SSHDemo\\Web\\WEB-INF\\classes\\", "com.luke.Sample", false);
Class c1 = loader1.loadClassMy("D:\\workspace\\SSHDemo\\Web\\WEB-INF\\classes\\", "com.luke.Sample", false);
System.out.println(c.getClassLoader() + "################" + c1.getClassLoader());
/**
* 因为Test的加载器是系统加载器即sun.misc.Launcher$AppClassLoader@190d11,
* 根据加载器代理委托机制,c的加载器是com.luke.MyClassLoader@10b30a7,
* c1的加载器是com.luke.MyClassLoader@1b67f74,
* 虽然类的全名相同, c与c1的加载器的父加载器是系统加载器,父加载器加载的类不能看见子加载器加载的类, 下面的实例不可以转换, 会报异常ClassCastException.
*/
/*Sample o = (Sample)c.newInstance();
Sample o1 = (Sample)c1.newInstance();
((Sample)o).out("hello world!");*/
Object o = c.newInstance();
Object o1 = c1.newInstance();
System.out.println(o.getClass().getClassLoader() + "****************" + o1.getClass().getClassLoader());
/**
* c的加载器是com.luke.MyClassLoader@10b30a7,
* c1的加载器是com.luke.MyClassLoader@1b67f74,
* 虽然类的全名相同, 但是c和c1的加载器不同,所以类不相同, o与o1类型不同, 不可以赋值, 会报异常ClassCastException.
*/
/*Method setSampleMethod = c.getMethod("setSample", java.lang.Object.class);
setSampleMethod.invoke(o, o1); */
Method m = c.getMethod("out", java.lang.String.class);
m.invoke(o, "你好");
//----------------------------测试3
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InstantiationException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
分享到:
相关推荐
微信视频号大风口项目,多赛道选择,可矩阵,玩法简单轻松上手.mp4
电子科技大学图书馆微信小程序_中国电子科技大学
2023-04-06-项目笔记-第三百七十二阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.370局变量的作用域_370- 2025-01-08
期末课设-Python和Django实现音乐推荐系统(含源码+课设报告+答辩PPT).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载
FlexiFed实验初学者学生复制品_ FlexiFed留级生.zip
sTM32 ADC采集滤波算法,卡尔曼 中位值 同步对比输出源程序,芯片采用STM32f103c8t6.算法采用卡尔曼滤波算法中位值滤波算法, 波形输出正常采集的卡尔曼 中位值三个波形输出,程序注释详细。
详细介绍及样例数据:https://blog.csdn.net/T0620514/article/details/145019667
三相两电平逆变器模型预测控制(MPC)simulink仿真,内有坐标变和MPC代码,可修改电流参考值,~~可用作电力电子方向入门学习
25混合A星算法路径规划Hybrid-Astar 以车辆的运动学模型为节点,以当前点到终点的Astar距离和RS距离两者最大的距离作为H(n)函数的估计代价,使用matlab实现(2016a以上版本)
考虑阶梯式碳交易机制与电制氢的综合能源系统热电优化 关键词:碳交易 电制氢 阶梯式碳交易 综合能源系统 热电优化 参考文档:《考虑阶梯式碳交易机制与电制氢的综合能源系统热电优化》基本复现 仿真平台:MATLAB+CPLEX 主要内容:代码主要做的是一个考虑阶梯式碳交易机制的电热综合能源系统优化调度研究,考虑综合能源系统参与碳交易市场,引入引入阶梯式碳交易机制引导IES控制碳排放,接着细化电转气(P2G)的两阶段运行过程,引入电解槽、甲烷反应器、氢燃料电池(HFC)替传统的P2G,研究氢能的多方面效益;最后提出热电比可调的热电联产、HFC运行策略,进一步提高IES的低碳性与经济性。 目标函数为以购能成本、碳排放成本、弃风成本最小,将原问题转化为混合整数线性问题,运用CPLEX商业求解器进行求解。
并离网逆变器仿真模型 逆变器PQ控制,Vf控制,无功能量发生器SVG,有源电力滤波器APF仿真模型
springboot176基于Spring Boot的装饰工程管理系统,含有完整的源码和报告文档
一、项目简介 本项目是一套基于SSM框架实现的生活缴费系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值 二、技术实现 jdk版本:1.8 及以上 ide工具:IDEA或者eclipse 数据库: mysql5.5及以上 后端:spring+springmvc+mybatis+maven+mysql 前端:vue,css,js 三、系统功能 系统角色主要包括:管理员、用户 系统主要功能包括: 用户登录 用户注册 首页 个人中心 修改密码 个人信息 用户管理 电表管理 电表缴费管理:查看缴费详情,缴费 ETC管理 ETC缴费管理 供暖管理 供暖缴费管理 固话管理 固话缴费管理 宽带管理 宽带缴费管理 燃气表管理 燃气表缴费管理 油卡管理 油卡缴费管理 水表管理 水表缴费管理 帮助中心类型管理 油卡所属公司管理 客服管理 轮播图管理等功能
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
多智能体、一致性、时滞 含通信时滞和输入时滞的多智能体一致性仿真 简单的多智能体一致性性仿真图,包含状态轨迹图和控制输入图。 适用于初学者。
内容概要:本文介绍了一种新的智能对比度增强技术——动态直方图均衡化(DHE)。该方法通过对输入图像的直方图进行分割并分别进行直方图均衡化来克服传统全局直方图均衡化(GHE)和其他方法存在的局限性,从而实现更好的图像细节保护及显著的整体对比度增强效果。具体来说,DHE基于局部极小值将图像直方图划分为子直方图,并重新调整各分区以避免高灰度频率部分对低频区域的影响。同时,在进行均衡时限制每种子直方图的灰度级范围,防止过度拉伸导致细节丢失等问题。 适用人群:从事计算机视觉和图像处理研究的专业人员,特别是关注对比度增强算法及其实际应用的研究学者和技术开发者。 使用场景及目标:可用于医疗影像处理、指纹识别等多个领域的前期预处理步骤;主要目的是改善低对比度图像的质量,提升后续图像识别或其他处理任务的效果。 其他说明:相比于现有技术如全球均值变换、局部直方图均衡以及特定直方图规格化等方式,本提出的DHE能有效避免因增强处理而引起的严重副作用如棋盘效应等,提供更加平滑自然的视觉体验。此外文中还展示了多个实验结果以验证新方法的有效性和优越性能表现。
我的超迷你机械臂机器人项目。_Dummy-Robot
实体单元椭圆主体扭转分析,着重分析扭矩的施加方式
OKR计划表 自我管理
用于微信小程序的ProtoBuffer库