2019独角兽企业重金招聘Python工程师标准>>>
写在前面
从事Java开发快三年了,从SE程序写到EE程序,对Java语言的理解肯定与三年前不同。随着理解的加深,对Java也越来越敬畏。所以想忙里偷闲复习一遍《Java编程思想》这本书,当年入门时拜读,对一些东西一知半解,跳过了一些暂时用不到的内容,重翻此书温故并知新。
在这里把阅读过程中一些值得我记住的东西和自己的思考记下来,便于以后翻看,也便于与各位探讨。
2.1
作者在注解中写到“我曾经读到的一本书说:‘Java所支持的按址传递是完全错误的’,因为Java对象标识符实际上是对象的引用’,并且他接着说任何事物都是按值传递的。”
这句话有些拗口,推测是翻译的问题。我从前看过一个简洁的说法与之契合(出处忘记了,对原作者表示抱歉):Java传递的是引用的值。即传递时是将对象的引用复制了一份,对象还是那个对象,没有多,只是多了一个指向它的引用。我比较赞同这种观点。
2.2
本节与上一节给出了两种初始化字符串的形式:
- String s = "asdf";
- String s = new String("asdf");
两者的比较让我联想到Java常量池:第一种引用指向了一个字符串常量,它在Java常量池中;而第二种引用指向了一个字符串对象。所以用 == 比较两者结果是false。
相应的:
String s0 = "asdf";
String s1 = "asdf";
String s2 = "as" + "df";
s0 == s1结果为true, s1 == s2 结果为true。因为三个引用都指向了常量池中的同一个字符串常量。而
String s0 = "asdf";
String s1 = new String("asdf");
String s2 = "as" + new String("df");
s0 == s1结果为false,s1 == s2结果为false,s0 == s2结果为false。因为s1和s2无法再编译期间确定,所以它们是单独的字符串对象。
本节中可总结出这样的表述:Java的基本类型和引用存放在Java的堆栈中。
同时Java的对象都在Java堆内存中。
基本类型的相关总结:
- 基本类型的大小都是固定的,与os和硬件无关;
- 所有类型都是有符号的,Java中不存在无符号基本类型;
- char占两个字节(之前总忘记);
- boolean类型很特殊,作者说它所占存储空间的大小没有明确指定。在《JVM虚拟机规范》一书中提到,字节码中对boolean类型支持有限并且没有该类型,在字节码中将其转换为int,同时oracle的虚拟机实现将boolean数组转换成byte数组。这里就有个问题,反编译时如何确定是boolean类型呢?有待研究。
Java提供了两个用于高精度计算的类:BigInteger和BigDecimal。分别支持任意精度的整数的定点数。注意这里BigDecimal是定点数,关于定点数和浮点数的区别:
定点数小数点固定的位于实数中间的某个位置。
浮点数 用科学计数法表达实数,由尾数、基数和指数以及正负号组成。Java平台上的浮点数类型float和double采纳了IEEE 754标准中所定义的单精度32位浮点数和双精度64位浮点数的格式。第一个域占1位是符号域,0表示整数、1表示负数。第二个域是指数域,单精度为8位,双精度为11位。由于指数既要表示正数又要表示负数,所以在无符号表示法上加入偏差,单精度为127、双精度为1023,以单精度为例,8位可以表达0到255之间的数,减去偏差127得到指数的范围是-127~128。第三个域为尾数域,单精度23位、双精度52位。IEEE标准要求尾数小数点左侧必须为1(因为是二进制),所以保存尾数时省略这个1。基数不用保存因为是2。
BigDecimal的实现:BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。
这里为什么说BigDecimal是定点数不得而知。
创建一个数组对象时,如果元素是引用则会被置为null,如果是基础类型,则会被自动初始化为0。
2.3
在c++中有较大作用域的变量隐藏起来的做法,Java不允许这样的做法。
2.4
若类的某个成员是基本数据类型,即使没有进行初始化,Java会给它赋予一个默认值。大多说数据类型是0,boolean是false,而char是'\u0000', 在书中的表格里'\u0000'的用括号标注为null,在程序里使用其实它是一个空格;
注意默认初始化只适用于类的变量而不适用于方法中的局部变量。如果在方法中定义基本类型不初始化直接使用编译器会报错。
2.5
字符串中的每个字符的尺寸都是两个字节,以此来提供对Unicode字符集的支持。
2.7
System.getProperties().list()
获取所有环境变量属性,并输出到PrintStream或PrintWriter的对象中。
2.8
IBM的jikes编译器也是一种常用的javac编译器
2.8.2小节的第一段话有点别扭,用自己的话总结一下:javadoc注释中有两种内容:第一,直接嵌入HTML中的内容;第二,文档标签,文档标签以@字符开头,如果文档标签独占一行,则需要@在行开头(不算表示注释的*),如果不独占一行,则需要将文档标签用花括号括起来(包括@)。
javadoc只能为public何protected成员进行文档注释,private和默认访问的成员的注释会被忽略。可以在使用javadoc时添加-private参数将private成员的注释也包括在内。
在javadoc注释中可以使用HTML标签,以便控制生成的HTML格式,但是不要使用标题标签例如
或
,因为这会和javadoc自己插入的标题冲突。
书中介绍的一些文档标签:
(1)@see 引用其他类的文档,格式:
@see classname
@see fully-qualified-classname
@see fully-qualified-classname#method-name
生成文档时会加入一个具有超链接的See Also条目,但是javadoc不会检查超链接是否有效;
(2){@link package.class#member label}
该标签与@see相似,只用于行内,用label作为超链接的文本而不是See Also
(3){@docRoot}
生成到文档根目录的相对路径,用于文档树页面的显示超链接
(4){@inheritDoc}
从当前这个类的直接基类中继承相关文档到当前的文档注释中。
(5)@version version-information
version-information是任何包含在版本说明中的重要信息。如果javadoc命令使用了-version参数,则从生成的HTML文档中特别提取出版本信息。
(6)@author author-information
包含作者信息,javadoc同样有-author参数。可以使用多个标签以便列出所有作者,但是它们必须连续放置。全部作者信息会合并到同一段落。
(7)@since
指定程序代码最早使用的版本
(8)@param parameter-name description
参数的描述
(9)@return
返回值的描述
(10)@throws
该方法抛出异常的说明
(11)@deprecated
表示一些旧特性已由改进的新特性取代,建议用户不要再使用这些旧特性。
/Output标签那段话不是很明白,应该是与之前提到的作者自己实现的doclets相关。有没有筒子能解释一下呢?谢谢。