Java常见的30个误区与细节!

昨天整整一天,我都呆在图书里。本打算找一些书学习“正则表达式”,很失望,没找到有这部分的内容的书。发现了一本《Java深刻解析》,其中涉及了不少平时没有注意的一些误区,也许开发的时候用不上,可是对这些概念却不能模糊。书中的内容仍是颇有用处,这里摘要了一些笔记。
1 在Java中,没有goto语句。由于大量使用goto语句会下降程序的可读性和可维护性,因此Java语言取消了goto的使用。同时,为了不程序员自行使用goto所带来的混乱,Java语言仍将goto定义为一个关键字,可是没有定义任何语法,故称为“保留字”。java

2 true、false和null在IDE中虽然以不一样的颜色显示,可是并非关键字,而是“字面常量”,就和String类型的abc同样。程序员

3 定义名称时尽可能避免使用$,由于编译器在对.java文件进行编译的时候,会将”$”编译成顶层类型与底层类型的链接符。见下例:正则表达式

package com.laixintao.Test;
 
public class Outer$Inner {
    public static void main(String[] args) {
        Outer o = new Outer();
        Outer.Inner i = o.new Inner();
        i.innerPrint();
    }
}
欢迎加入java中高端架构师交流群:603619042
面向1-5年java人员
帮助突破划水瓶颈,提高思惟能力
class Outer {
    class Inner {
        void innerPrint() {
            System.out.println("Inner Print!");
        }
    }
}

在编译(javac Test3.java)这段代码的时候,编译器会报如下错误:Test.java:12: 错误: 类重复: com.laixintao.Test.Outer.Inner class Inner{ ^数组

4 Unicode转义字符处理的很是早,在解析程序以前。例如:安全

// char c1 = 'u00a';
// char c2 = 'u00d';

在程序中出现这两行代码编译报错。这两个Unicode码分别表示”换行”和”回车”,因此,在编译器编译的时候,代码是这样的:架构

// char c1 = '
';
// char c2 = '
';

5 Unicode码使用16位字符编码,在Java中用char类型来表示。如今Unicode已经扩展到一百万个字符,超出16位限制的成为增补字符。全部增补字符都不能用字符常量来表示。post

6   当shortbytechar参加运算时,结果为int型,而非与较高的类型相同。若是变量是byteshortbyte类型,当对其赋予编译时期的常量,而该常量又没有超过变量的取值范围时,编译器就能够进行隐式的收缩转换。这种隐式的收缩转换是安全的,由于该收缩转换只适用于变量的赋值,而不适用于方法调用语句,即不适用于方法调用时的参数传递。(详见java中默认类型转换的小问题学习

, 注意char类型,这是一个无符号类型。所以,charshortcharbyte之间的转换必须显示地使用类型转换。 从bytechar的转换为扩展收缩转换,该转换比较特殊,即先将byte扩辗转换到int,而后再收缩到char编码

8   在整型数据间的扩辗转换中,若是操做数是char类型(无符号类型),则进行无符号扩展,扩展位为0.若是操做数是byteshortint(有符号类型),则进行有符号扩展,扩展位为该变量的符号位。spa

9   整型数据之间的收缩转换,仅仅是截断并丢弃高位,不作任何其余处理。

10   0.1+0.2不等于0.3.System.out.println((double)0.1+(double)0.2);这条语句的输出结果是0.30000000000000004。由于计算机使用二进制来存储数据,而不少小数都不可以准确地使用二进制来表示(事实上,大多数地小数都是近似的),就像使用十进制小数不能准确地表示1/3这样地分数同样。大多数地浮点型,在计算机中只是近似地存储其值,而不像整型那样准确地存储。又例,这是一个死循环:for(float f = 10.1f;f != 11;f+=0.1f){}

11 float类型能够保留7~8个有效数字,而double类型能够保留15~16个有效数字,于是当int类型或long类型数值多于double或float地有效数字时,该值的一些最低有效位就会丢失,从而形成精度丢失,这时,就会采用IEEE754最近舍入模式,提取与该整型值最接近的浮点值。尽管整型向浮点型的转换属于扩辗转换,但当数值很大或很小(绝对值很大)时,就会产生必定的精度丢失。

12  i+++j如何计算?(这个问题在C/C++)中讨论是没有多大意义的,由于C/C++依赖于实现的硬件结构,不一样的环境结果也会不一样。不过在Java中,这个结果是固定的,不受其运行的硬件环境与平台的影响) 答:根据贪心规则,前置++优于后置++,结果是(i++)+j

13  i++和++i其实都是先+1,再赋值。++i,没什么好说的;i++,以j=i++;为例在底层的实现是:temp = i;i = i + 1; j = temp; 因此,i=15;i=i++;这个表达式的结果是15.(由于加一以后又执行了一次赋值,从16变回15)

14   +0与-0在浮点类型变量存储中,符号位是不一样的。当-0和+0参与浮点类型的相关运算(例如相除与求余运算)时,能够产生不一样的结果。

15   浮点的相除与求余运算不一样与整型的相除与求余运算,当除数为0时,浮点运算不会产生ArithmeticException异常。

16   String类是非可变类,其对象一旦建立,就不可销毁。String类那些看似修改字符序列的方法实际上都是返回新建立的String对象,而不是修改自身对象。

17   因为String对象是不可改变的,所以具备线程安全性,能够自由地实现共享。

18   在String类内部,是使用一个字符数组(char[])来维护字符序列的。String的最大长度也就是字符数组的最大长度,理论上最大长度为int类型的最大值,即2147483647.在实际中,通常可获取的最大值小于理论最大值。

19  main()方法在表现行为上,与其余方法基本相同,能够重载,由其余方法调用,继承,隐藏,也能够抛出异常,带有类型参数。咱们也能够在一个程序中经过反射来调用main方法(或其余方法)。

20 当两个或多个方法的名称相同,而参数列表不一样时,这几个方法就构成了重载。重载方法能够根据参数列表对应的类型与参数的个数来区分,可是,参数的名称、方法的返回类型,方法的异常列表与类型参数不能做为区分重载方法的条件。

21   究竟选择哪一个方法调用,顺序是这样的:

  • 在第一阶段,自动装箱(拆箱)与可变参数不予考虑,搜索对应形参类型能够匹配实参类型而且形参个数与实参个数相同的方法;
  • 若是在步骤一不存在符合条件的方法,在第二阶段,自动装箱与拆箱将会执行。
  • 若是在步骤二中不存在符合条件的方法,在第三阶段,可变参数的方法将会考虑。
  • 若是3个阶段都没有搜索到符合条件的方法,将会产生编译错误。若是如何条件的方法多于一个,将会选择最明确的方法。最明确的方法定义为:若是A方法的形参列表类型对应的均可以赋值给B方法的形参列表类型,则A方法比B方法明确。若是没法选出最明确的方法,则会产生编译错误。

22   重写和隐藏的本质区别是:重写是动态绑定的,根据运行时引用所指向对象的实际类型来决定调用相关类的成员。而隐藏是静态绑定的,根据编译时引用的静态类型来决定调用的相关成员。换句话说,若是子类重写了父类的方法,当父类的引用指向子类对象时,经过父类的引用调用的是子类方法。若是子类隐藏了父类的方法(成员变量),经过父类的引用调用的还是父类的方法(成员变量)。

23   构造器是递归调用的,子类的构造器会调用父类的构造器,直到调用Object类的构造器为止。

24   构造器没有建立对象,构造器是使用new建立对象时由系统调用的,用来初始化类的实例成员。从顺序上说,先是建立对象,而后再调用构造器的。(构造器并无产生新的对象)

25   默认的构造器不为空,该构造器会调用父类的无参构造器,并可能执行实例成员变量的初始化。因此,默认的构造器至少调用了父类的构造器,它作的工做还可能更多,包括实例变量声明初始化与实例初始化块,都是在构造器中执行的。

26   当==或!=运算符的两个操做数的类型一个是基本数据类型,另外一个是包装类引用类型时,将引用类型拆箱转换为基本数据类型,而后比较两个基本数据类型的值是否相等。

27   在Java中,数组也是类,数组声明的引用变量指向数组类型的对象。全部的数组都继承Object类,而且实现了java.lang.Cloneablejava.io.Serializable接口。数组的成员包括变量length(隐式存在)与从Object类继承的成员。CloneableSerializable是两个标记的接口,这两个接口中没有显式声明任何成员。

28   接口是彻底抽象的设计,不能实例化。使A用new方式建立的借口类型,其实是建立了一个匿名类,该匿名类实现了接口类型。

29   若是两个接口声明了相同的变量x,则当某接口同时继承这两个接口,或者某类同时实现这两个接口时,经过简单名称访问会产生编译错误。

30   若是两个接口中声明了相同名称的方法m,而且两个方法没有构成重载,则当某接口可以同时继承这两个接口,或者某类可以同时继承这两个接口时,必须存在一种方法签名,使得该签名同时为两个m方法签名的子签名,而且在方法的返回类型上,必须存在一种类型,使得该类型同时为两个m方法返回类型的可替换类型。为了学习工做与休闲娱乐互不冲突,现新建圈【码农茶水铺】用于程序员生活,爱好,交友,求职招聘,吐槽等话题交流,但愿各位大神工做之余到茶水铺来喝茶聊天。

相关文章
相关标签/搜索