一个IDE的提示,引发了对《Java编程思想》的质疑?

前言

最近在读slf4j的源码,同时在B站录一套读源码的课程(av:BV1KD4y197Jf),其中一个简单的IDE编码规范的提示,因为多问了几个为什么导致一系列Java基础知识的追踪和验证,最近竟然发现《Java编程思想》书中的内容竟然也有不严谨或者说不一定对的地方。

这个追踪问题的答案的过程非常有意思,整合了不少工具、书籍以及Java基础知识。下面我们就来看看到底是什么问题。

IDE的提示信息

在slf4j的LoggerFactory类中有几个静态方法,方法的修饰为private final static。而IDE会提示,private的方法不用final修饰。

这个提示看起来很合理,既然方法为private的了,也就说是私有的,不可被继承,当然不可改变了,也就不需要再用final进行修饰了。

image

此刻问了自己一个为什么?虽然看起来是这么回事,但底层是如何实现的呢?是不是意味着private修饰的成员方法默认就是final的?

关于private方法不能被重写我们就不举例说明了,很显然的事。下面就来求证一下“private修饰的成员方法是不是默认就是final的”。

Java编程思想对final的定义

《Java编程思想》第4版,第267页中有描述“final和private关键字”的一段内容:

“类中所有的private方法都隐式的指定为是final的……可对private方法添加final修饰词,但这并不能给该方法增加任何额外的意义。”

从本质上来讲private是用来表示可见性的,而final是用来表示禁止覆盖的。JVM真的会对private隐式的指定为final吗?下面我们就写一段代码,并利用工具来进行证明一下。

证明过程

首先我们定义一个类,在类中定义两个方法,一个private修饰,一个private final修饰:

public class FinalMethod {

	private void test1(){
	}

	private final void test2(){
	}
}

然后,我们对类进行编译,看看编译之后的字节码中到底是如何实现的。

在class文件中,有专门描述方法的方法表,方法表第一项就是访问标志access_flags。这个标志用于识别一些类或接口层次的访问信息。具体标志位以及标志的含义如下:

image

关于access_flags可以参考《深入Java虚拟机》介绍类文件结构的章节。补充了基础知识之后,我们就通过工具来看看上面的类编译之后是什么样子。

这里用到一款开源的字节码浏览器工具:jclasslib bytecode viewer。下载链接:https://github.com/ingokegel/jclasslib/releases 。

通过该工具打开FinalMethod的class文件,先看test1方法:

image

可以看到该方法的access_flags访问标准为0x0002[private],对照上表的名称也就是ACC_PRIVATE。

那再看test2方法的access_flags的值:

image

可以看到对应的值为0x0012,对照上表并没有发行有这么一个值,它是怎么来的呢?其实access_flags如果有多个修饰的话,是会进行或(|)运算的,也就是0x0002 | 0x0010,结果不就是0x0012。对应的Flag名称就是ACC_PRIVATE和ACC_FINAL。

结论分析

通过上面的分析,如果说被private修饰的方法都隐式的指定为final的了,那么,编译的字节码应该是一致的才对。但通过上面的分析,很显然两者是有区别的。

也就是说,虽然我们知道private修饰的方法不用再使用final进行修饰了,但本质上它与private final修饰的方法还是有所区别的,不能一概而论。

小结

其实单从使用层面来讲,本篇文章的分析并没有太多的意义,使用时通过private修饰了,就不用再使用final了。只是说明slf4j源码在这个层面上是需要进行一定的优化的。

但如果你留意这个分析过程所牵涉的知识和工具,你是不是发现会收获很多?比如class文件的结构、访问标志、算法,以及字节码浏览器等等。

平时工作或学习中,多问一个为什么可能就会串联出一连串的知识点、工具和方法论,这也是学习和实践的一部分。

原文链接:《一个IDE的提示,引发了对《Java编程思想》的质疑?


程序新视界

公众号“ 程序新视界”,一个让你软实力、硬技术同步提升的平台,提供海量资料

微信公众号:程序新视界

程序新视界 CSDN认证博客专家 Spring 架构 Java
个人公众号【程序新视界】,一个硬技术,软实力同步提升的平台。《Spring Boo技术内幕:架构设计与实现原理》作者,《深入以太坊智能合约开发》联合作者之一。主要从事于三方支付行业。
已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值