初始化对于类与接口的异同点深入解析
在上一次【http://www.cnblogs.com/webor2006/p/8905978.html】中学习了类加载器理论的一些内容,其中回顾一下关于类的初始化时机的这段文字:
而截图中也说明了这个结论在之前篇幅中也已经详细说明过了,那再拧出来有何意义呢?因为以前举的例子并不能很好的说明上面的结论,为什么,先来回顾一下当时的代码:
其中当时是这么论证“当一个接口在初始化时,并不要求其父接口都完成了初始化”的,先运行程序:
然后将运行生成的MyParent5的字节码文件删除掉,再运行,其结果也正常可以打印,如下:
然后此时将程序修改一下再用相同的方法来运行:
然后再将生成的MyParent5的字节码文件删掉再运行:
此时就抛异常了,由此实验就得出了“当一个接口在初始化时,并不要求其父接口都完成了初始化”的结论了,但是!!删字节码的实验当时是为了说明编译期常量与运行期常量的一个区别的,回顾一下:
因为对于编译期常量在编译之后会将常量放到调用常量所在类MyTest3的常量池中,所以之后的运行就跟MyParent3这个类就木有关系啦,而对于运行期常量,如上面截图的就是属于运行期常量的情况。
其实这个实例只能说明“在对MyChild5类的主动使用时JVM会尝试着加载MyParent5这个接口,但是由于MyParent5已经被人为删除了所以就报类找不到了”,这里为了说明此问题还是在JVM中增加用来查看类加载的一个参数再来运行观察,如下:
重新编译运行:
而在上面的实验中因为将MyParent5的字节码文件删掉了,那当然就抛出类找不到的异常啦,好接下来将MyChild5还是改回来接口:
编译运行:
那此时跟MyParent5和MyChild5完全木有关系,那下面将这两个的class文件删掉,然后再运行:
是不是惊呆了,这也跟我们打印的加载类的结果是相符合的,只是加载了MyTest5这个类,这也是接口跟类的不同,如果MyChild5是类的话那就会加载,好!下面将编译期的变量改为运行期的变量,如下:
再来编译运行:
这个在之前就已经讲过了,不过这里再总结一下关于接口和类的初始化:
其根本是否是常量来决定加载的情况,好,那回到咱们想要重新来论证的主题上来:
重新论证1:“在初始化一个类时,并不会先初始化它所实现的接口”
对于接口咱们知道是没法跟类一样在静态代码块中加一些日志来看出是否它被初始化了,其实还是有办法的,这里先来了解一个java的基础语法,因为在咱们实验代码中是需要用到这个特性的,如下:
请问它的输出是什么?运行看一下:
也就是static块只会在类加载初始化阶段调用一次,好,接下来修改一下再来看:
再来看结果:
也就是说不加static块是在类被构造的时候才去初始化的,了解了这个语法之后,下面来将咱们的实验代码进行修改:
也就是在接口中可以定义一个变量,然后在初始化变量里面加一个初始化块,如果MyParent5初始化了,那它里面的thread变量肯定也需要被初始化,而只要一初始化那“MyParent5 invoked”就会从初始化块中打印出来,注意:类的初始化和类的准备是两个不同的阶段,千万不要搞混啦,那下面来运行看一下:
而主动去调用MyChild5.b很显示会导致MyChild5子类的初始化,那“在初始化一个类时,并不会先初始化它所实现的接口。”,这样就精确论证了这一点,好,那如果将接口改为class呢?
当然会呀,因为目前是父子关系了,如下:
那如果再变化:
这个前面多次提到了,肯定是不会的,因为它是编译器的常量会被放到MyTest5的常量池了,如下:
接下来继续修改代码:
编译运行:
这个结论如预想,那如果改成类呢?
重新论证2:“在初始化一个接口时,并不会先初始化它的父接口。”:
修改实验代码:
编译运行:
很显然在初始化MyParent5这个子接口时,其MyGrandpa并未进行初始化。
转载于:https://www.cnblogs.com/webor2006/p/8922287.html
初始化对于类与接口的异同点深入解析相关推荐
- java 接口初始化_Java类和接口的初始化
类的初始化由执行类中静态代码块的初始化和类中声明的静态域的初始化两部分组成 接口的初始化由接口中声明的域(常量)的初始化组成 初始化的时机 类或接口T在以下任意情况发生之前会立即进行初始化:T是一个类 ...
- abstract类_走进C# abstract,了解抽象类与接口的异同
思维导航: 前言 abstract修饰符 抽象类与接口的异同 抽象类和接口的使用 总结 参考资料 文章正文: ?回到顶部 前言: 最近在研究.NET Core的一些类库源码的时候发现在底层类库中使用了 ...
- 【Java4】实例初始化,类初始化,/接口,多态,final/static,权限修饰符/native
文章目录 1.实例初始化过程:有几个构造器,就会有几个实例初始化方法 2.实例初始化和类初始化结合:先类(静态)后实 3.接口:只有abstract可省 3.1 鸟类案例:Flyable相当于父类的一 ...
- java 接口初始化_Java类的初始化 | 学步园
类的初始化时机1.创建类的实例 2.访问类或接口的静态变量(static final常量除外,static final变量可以)3.调用类的静态方法 4.反射(Class.forName(packag ...
- java基础-类-抽象类-接口(自学笔记)
一.类 class 定义:具有相同属性(特性)和方法(行为)的一类事物 的抽象的总称 例如:人类,动物,车,屌丝类.是一种类别,世界上所有的事物都可以分类,在计算机中java都能进行对应和体现 类的三 ...
- 学习Kotlin(三)类和接口
推荐阅读: 学习Kotlin(一)为什么使用Kotlin 学习Kotlin(二)基本语法 学习Kotlin(三)类和接口 学习Kotlin(四)对象与泛型 学习Kotlin(五)函数与Lambda表达 ...
- 类与接口(三)java中的接口与嵌套接口
###一.接口 ##1. 接口简介 接口: 是java的一种抽象类型,是抽象方法的集合.接口比抽象类更加抽象的抽象类型. 接口语法: [修饰符] [abstract] interface 接口名 [e ...
- Servlet入门篇(GenericServlet 类 - HttpServlet 类 -ServletConfig 接口 - HttpServletRequest 接口……)
1.Servlet 简介 Servlet 对请求的处理和响应过程可分为以下几个步骤: (1)客户端发送请求至服务器端: (2)服务器将请求信息发送至 Servlet : (3)Servlet 生成响应 ...
- 切记!构造函数里面别一定不要初始化其他类,踩过坑的都知道
点击上方蓝色关注我们! 先来看看什么是构造函数(方法):是一种特殊的方法,特殊之处就在于它没有返回类型,void也不可以有.且方法名与类名完全相同.主要是用来创建对象时初始化对象,也就是为对象成员变量 ...
最新文章
- react-native 安卓支持 gif动态图
- GCC安装UBUNTU
- 手动制作linux live,Linux下Live USB如何制作
- php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式
- POJ 1664 苹果放盘子(递归)
- java cxf 不使用springmvc_使用cfx与springMVC集成发布与调用webservice
- vs winform常用函数_使用.net core3.0 正式版创建Winform程序
- HTML (3)---HTML编辑器
- 机器视觉LED光源的选择及其性能优势
- burpsuite_pro的使用
- python 栈_python:栈的理解与应用
- docker java 中文乱码_记一次ubuntu docker 镜像 java 中文乱码问题查找
- Happy New Year!PR升3啦!
- 使用IDM下载软件下载百度云网盘里的资源,以Chrome浏览器为例
- 一篇比较好的高数的学习规划分享
- 换一种姿势:利用 PdaNet+ 实现电脑共享手机的流量
- PDF能打印吗?教你两种快速打印方法
- 小语种语音情感语料库的建立——论文阅读1
- 【Django】admin的save_modle方法重写-20220803
- 王者服务器维护8月四日,王者荣耀体验服弈星重做上线 8月4日停机更新
热门文章
- esp分区创建 linux_Elementary OS - 号称最漂亮的 Linux 发行版
- winform中通过FileStream实现将文件上传
- 使用Jenkins打包和部署Maven工程步骤详解
- html5整个桌面背景图片,HTML5 body设置全屏背景图片 如何让body的背景图片自适应整个屏----实战经验...
- 微信小程序轮播中的current_开源 | 微信接龙小程序 wechatsolita 开源
- docker使用_Docker的基本使用
- 思科三层交换机开启ipv6路由功能_三层交换机实现路由功能配置示例与详解 (Cisco Packer Tracer 模拟器)...
- Android studio错误:module not specified
- 服务器的配置文档在哪里找,服务器端的数据库配置怎么找
- java timer指定线程池_Java 定时器(Timer)及线程池里使用定时器实例代码