- 浏览: 118297 次
- 性别:
- 来自: 北京
最新评论
-
supertangcugu:
senninha 写道然鹅。。jdk1.8已经把这货移到了he ...
小例子:如何说明String常量池的位置 -
senninha:
然鹅。。jdk1.8已经把这货移到了heap区?只有把-Xmx ...
小例子:如何说明String常量池的位置 -
onada1108:
还有你是基于jdk那个版本
小例子:如何说明String常量池的位置 -
onada1108:
我想问下,你这个方法跑啦多长时间
小例子:如何说明String常量池的位置 -
hu_xuefeng:
hsbljyy 写道看来真的有很多谬误啊!当变量在-128~1 ...
从“关于Java堆与栈的思考”一帖看错误信息的传播
首先声明,本文无任何实际价值,只是讨论一些无聊的说法。
有一个著名的帖子《Java关键字final、static使用总结》,里面有这样一句话:
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
这句话的确值得注意,搞不明白一个表示可见性的关键字private和一个表示禁止覆盖的关键字final怎么扯上关系了。
我说这句话是在java语义的角度看是错误的。有人说《Java编程思想》里这么说的,应该可信。如果你认为是错误的,如何证明?
其实从语义角度很容易说明它们是不相关的了,证明也不难。我们知道,在class文件中,方法在常量池中有专门的项进行描述。
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
其中access_flags描述方法的访问标志和属性,具体信息有:
Declared private; accessible only within the defining class. |
||
Declared synchronized; invocation is wrapped in a monitor lock. |
||
如果说“private类型的方法默认是final类型的”是正确的,那么自然,如果一个方法是private的,它的access_flags中应该存在
ACC_PRIVATE和ACC_FINAL,如果不存在ACC_FINAL则自然证明了该说法的错误。
怎么看呢?找工具吧。
http://www.ej-technologies.com/products/jclasslib/overview.html
jclasslib是不错的工具。
我们写一个简单的测试类:
public class Main {
private void test(){}
private final void test2(){}
}
编译,使用jclasslib打开Main.class文件。容易辨别。
test():
test2():
如果语言角度有“自动是……”这个语义的话,应该会自己添加相应的描述信息的。比如,我们说一个接口中的方法自动是public abstract 的,即使你不写,编译器也会自动添加的。比如下面例子:
public interface Main { void test(); }
test()方法的描述符是:
补充说明:在回复信息中,有一种说法是“private自动是final的”是为了内联优化。我们知道,final的方法可以内联(inline)优化,private的和static的也可以进行同样的优化。
这里要注意逻辑关系,private和static的可以进行内联优化,并不能说它们就是final的。其实final不过是语言级别的一个概念而已,它是内联的充分不必要条件。如果说,可以内联优化就是final的话,那么static的呢?可惜从语言角度我们无法说明private和final无关。只能从侧面说明一下:
上面代码编译错误,因为final的存在。 这起码能够说明,不要从内联角度来说“private方法自动为final的”。class Base {
public static final void test() {
}
}
class Derived extends Base {
public static void test() {
}
}
我感觉《Thinking In Java》上很多地方是值得推敲的。
比如《Everything is an Object》一节,作者将存储区分为寄存器、栈、堆、常量区和非内存存储等5个部分,
当然,这是没有问题的。但是放到一个讲java的地方就有些奇怪了,毕竟java里提到的堆、栈一般来讲指的是面向
jvm的逻辑意义上的堆和栈,而且在这个层次上,内存的划分是由jvm规范定义的,包括pc寄存器、虚拟机栈、堆、
方法区、常量池、本地方法栈等。好像书里还提到过静态存储区的概念,这个jvm里也是不存在的。
书里还指出“构造方法是static的”:
Even though it doesn’t explicitly use the static keyword, the constructor is actually a
static method. So the first time an object of type Dog is created, or the first time a
static method or static field of class Dog is accessed, the Java interpreter must
locate Dog.class, which it does by searching through the classpath.
实在搞不清楚作者为什么要说constructor是静态的,如果是的话,构造方法里还能用this吗?
此外还有一段争论“pass by value”了,作者在注释里有一段说明,我总感觉他有狡辩的意思。不好直接说作者的说法是错误的,不过感觉没有必要老在一些说法上标新立异。
关于创建派生类对象,书里有这样的说法:When you create an object of the derived class, it contains within it a subobject of the base class.
This subobject is the same as if you had created an object of the base class by itself. It’s just that from the outside, the subobject of the base
class is wrapped within the derived-class object.
好像别的资料里都没有“subobject”这样的说法。作者的这种想法估计是从C++来的。但我想java的设计者们并没有这么考虑。
首先,我们看在父类的构造函数中调用被子类覆盖的方法时的表现。在java中,我们不提什么“父类subobject”之类的说法,
创建的就是一个完整的对象,那就是派生类的对象,很自然的,在父类构造方法中调用的覆盖方法会是当前对象对应的重写过的方法,
因此此时就出现了多态现象。而不会根据“父类subobject”的类型去找方法。但是C++中确实是根据“父类subobject”的类型去找
方法的,因此不会出现多态现象。其次,在java中,实际的对象都需要包含一些标志信息,比如垃圾回收标志、线程锁标志等。
显然所谓的“父类subobject”是不会有这种信息的,从这个角度看,也没有必要非要制造“父类subobject”这样一个概念。
文字比较拗口,示例代码如下 :
public class Test {
public static void main(String[] args) {
new Derived();
}
}
class Super {
public Super() {
test();
}
public void test() {
System.out.println("Super");
}
}
class Derived extends Super {
public Derived() {
}
public void test() {
System.out.println("Derived");
}
}
当然,学语言没有必要务求表达精确。这是个“度”的问题了。
评论
static方法也可以内联优化,显然static的无法添加final限定,因为添加了就改变了程序的语义。所以从内联角度无法说明这个问题。可以参考上面原文的修改。
findbox是不是findbug的笔误?
你看错了吧,我说的是物理。当时c盛行。况且我也没有贬低他的意思,我只是实话实说罢了。。
至于后面的,晦涩,没看懂,不发表意见
接口的方法是有ACC_PUBLIC和ACC_ABSTRACT标记的。所以这个比较类比不能成立。
如果从“语义”的角度将,认为private的方法有类似final的功能,这个我是赞同的。如果从语言角度这么提,我认为是毫无道理的。从方法绑定的角度看,invokespecial调用private方法时,可以根据引用的类型绑定方法。所谓的“final“语义,似乎就是指这一点了。
在SUN的jvm里,所谓的“静态数据区”应该是对应PermGen的,或者是PermGen的一部分。这跟翻译无关,只是我不喜欢书里的表达而已。
findbox我没看过,谢谢提示。
至于后面的,晦涩,没看懂,不发表意见
很多读物理然后去搞计算机的,特别猛。Bruce Eckel应该是C++标准委员会的成员。
发表评论
-
接口类型引用为何能调用Object类的方法
2009-09-20 19:15 3449首先看这段代码 ... -
无聊:详解java的构造方法
2009-09-20 00:47 5651关于java的构造方法有几个简单的问题: 1. ... -
小例子:如何说明String常量池的位置
2009-09-20 00:44 14436以前批过《关于Java堆与栈的思考》这个帖子,具体内容 ... -
无聊:为啥可以使用空引用调用static方法或者访问static field
2009-09-10 00:52 2015先看代码: public class ... -
从“关于Java堆与栈的思考”一帖看错误信息的传播
2009-08-05 05:03 10038我对转贴的信息一直有敌意,原因如下:首先,除了 ... -
谜题解析
2009-07-30 12:35 2844题目接http://zangxt.iteye.com/blog ... -
几个谜题,深入的了解java
2009-07-29 18:10 6022在2009年的JavaOne大会上,Joshua Bloch和 ... -
java中匿名内部类的构造方法调用
2008-07-28 19:14 12060与人讨论匿名内部类的构造方法问题,自己 ... -
static方法与覆盖
2008-08-01 17:50 1334The Java Programming Langu ... -
局部内部类 与 final变量
2008-09-12 23:39 1267局部内部类可以访问定义该类的作用字段中的所有变量,包 ... -
java 1.6 表达式计算方法
2008-10-11 12:42 1117import javax.script.Script ... -
看一下enum的原理
2008-10-29 13:22 2513java5增加了enum,其实对enum的处理很简 ... -
一个静态初始化的问题
2008-10-31 21:59 1178问题代码: public class Test1{ ... -
读Java Puzzlers笔记: 表达式问题
2008-11-02 11:27 1164一.奇数性判断一个数是否为奇数,方法: publ ... -
i++ ,++i,i=i++的问题
2008-11-05 20:16 1237很经典的无聊问题之一。 int i=0;i=i+ ... -
instanceof的使用
2008-11-06 20:47 1408总结:Java Puzzlers一书中的谜题50 看 ... -
Java的好书
2008-11-14 21:59 2276学Java也算有一段时间了,记录一下看过或者还需要 ... -
HashMap小测试
2008-11-25 18:48 1144测试HashMap代码: ... -
jvm对boolean类型的处理
2008-11-25 19:16 2062JVM对boolean类型的支持比较有意思,java虚拟 ... -
一.准备工作
2008-12-03 12:48 1129首先下载openjdk的源文件包,地址http: ...
相关推荐
### Java编程思想(完整版) #### 第1章 对象入门 **1.1 抽象的进步** 抽象在软件工程中扮演着极其重要的角色。通过抽象,开发者能够关注于概念的本质特征,而忽略掉不必要的细节。这有助于降低系统的复杂度,使得...
### Java编程思想读书笔记 #### 一、Java与C++的区别及内存管理 在学习Java的过程中,我们常常会拿它与C++进行比较。这两门语言虽然有着相似之处,但也有许多不同点。 1. **内存管理:** - C++提供了更为底层的...
根据提供的文件信息,我们可以深入探讨《Java编程思想》这一主题中的关键知识点,这些知识点主要集中在类、对象、封装性、继承、多态等核心概念上。 ### Java编程思想概述 《Java编程思想》这本书深入浅出地介绍了...
《Java编程思想》是 Bruce Eckel 的经典著作,这本书深入浅出地介绍了Java语言的核心概念和技术,被广大Java程序员视为学习Java的必备参考书。这个压缩包包含了书中的实例代码和习题答案,对于读者理解和掌握Java...
1. **动态绑定**:在Java中,除了`static`方法和`final`方法(包括`private`方法,因为它们不能被子类覆盖)之外,其他所有方法都是动态绑定。这意味着在运行时,系统会根据对象的实际类型来决定调用哪个方法。这种...
### JAVA面向对象编程思想 #### 一、面向对象的基本概念 面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它通过模拟现实世界中的对象及其交互方式来构建软件系统。Java作为一种典型的面向...
在Java编程中,final关键字扮演着至关重要的角色,它用于声明不可变的变量、方法以及类,以确保代码的稳定性和安全性。以下是关于final关键字的深入解析: 1. **final类**: 当一个类被声明为final时,这意味着这...
《Java编程思想》是 Bruce Eckel 的经典著作,这本书深入浅出地讲解了Java语言的各个方面,对于初学者和有经验的程序员来说都是极好的学习资源。提供的"java编程思想 答案+源代码.rar"压缩包包含了本书的解答和源...
《Java编程思想》是 Bruce Eckel 的经典之作,它深入浅出地介绍了Java这门强大的编程语言。这本书的章节练习答案则是对书中理论知识的实践检验,帮助读者巩固理解并提升编程技能。以下是对这份"Java编程思想练习答案...
《Java编程思想第五章练习与习题》章节涵盖了Java编程中的关键概念,这些概念对于深入理解和熟练运用Java语言至关重要。本章的练习旨在巩固和拓展读者在类、对象、继承、多态等核心主题上的理解。以下是根据描述和...
4. 用 private 修饰的 static 成员变量和成员方法,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用),但是不能在其他类中通过类名来直接引用,这一点很...
《Java编程思想》是 Bruce Eckel 的经典著作,这本书深入浅出地讲解了Java语言的核心概念和编程技术,是Java程序员的重要参考书籍。中文版的出现使得更多的中国开发者能够无障碍地学习这本巨著,无需面对语言障碍。...
而"Java编程思想_第4版—习题答案"这个压缩包则为读者提供了书中的习题解答,是学习过程中不可或缺的辅助资料。 1. 面向对象编程:Java是一种面向对象的语言,它强调将数据和操作数据的方法封装在一起,形成对象。...
《Java编程思想》是 Bruce Eckel 的经典著作,它深入浅出地介绍了Java语言的核心概念和技术,对于初学者和有经验的程序员来说都是极好的学习资源。这本书从对象的概念出发,逐步引导读者深入理解Java的世界。 1. **...
"Java编程思想答案"是针对这些练习题的解答,能够帮助读者检验自己的学习效果,解决学习过程中遇到的问题。 在学习Java编程时,掌握以下几个核心知识点至关重要: 1. **基础语法**:Java是一种静态类型的、面向...
### Java编程思想:为何面向对象编程在软件开发领域有如此深远的影响 #### 一、面向对象编程(OOP)的概念及重要性 面向对象编程(Object-Oriented Programming,简称OOP)是一种软件开发方法,它将数据和处理数据...
《Java编程思想全面的答案》这份资源集合了众多Java编程思想的学习习题解答,旨在帮助学习者深入理解并掌握Java编程的核心概念。以下是对这个主题的详细解析: Java编程思想是学习Java编程的基础,它涵盖了面向对象...
Java编程思想是每个Java开发者必备的知识体系,涵盖了Java语言的核心概念和高级特性。这篇笔记将聚焦于Java中的多态性,这是面向对象编程的关键概念,同时也涉及到构造函数、静态方法和final关键字的理解。 1. **...
在探讨“Java编程思想面向对象逻辑思维方法”这一主题时,我们深入剖析了面向对象编程(Object-Oriented Programming,OOP)的核心理念及其在Java中的应用方式。面向对象编程是一种编程范式,它将数据和操作数据的...