1. 在 Java 中, 没有 goto 语句. 因为大量使用 goto 语句会降低程序的可读性和可维护性, 所以 Java 语言取消了 goto 的使用. 同时, 为了避免程序员自行使用 goto 所带来的混乱, Java 语言仍将 goto 定义为一个关键字, 但是没有定义任何语法, 故称为 "保留字".
2.true,false 和 null 在 IDE 中虽然以不同的颜色显示, 但是并不是关键字, 而是 "字面常量", 就和 String 类型的 abc 一样.
3. 定义名称时尽量避免使用 $, 因为编译器在对. java 文件进行编译的时候, 会将 "$" 编译成顶层类型与底层类型的连接符. 见下例:
在编译 (javacTest3.java) 这段代码的时候, 编译器会报以下错误: Test.java:12: 错误: 类重复: com.javastack.Test.Outer.InnerclassInner{^
4Unicode 转义字符处理的非常早, 在解析程序之前. 例如:
在程序中出现这两行代码编译报错. 这两个 Unicode 码分别表示 "换行" 和 "回车", 所以, 在编译器编译的时候, 代码是这样的:
5.Unicode 码使用 16 位字符编码, 在 Java 中用 char 类型来表示. 现在 Unicode 已经扩展到一百万个字符, 超出 16 位限制的成为增补字符. 所有增补字符都不能用字符常量来表示.
6. 当 short,byte,char 参加运算时, 结果为 int 型, 而非与较高的类型相同. 如果变量是 byte,short,byte 类型, 当对其赋予编译时期的常量, 而该常量又没有超过变量的取值范围时, 编译器就可以进行隐式的收缩转换. 这种隐式的收缩转换是安全的, 因为该收缩转换只适用于变量的赋值, 而不适用于方法调用语句, 即不适用于方法调用时的参数传递.(详见 java 中默认类型转换的小问题)
7. 注意 char 类型, 这是一个无符号类型. 因此, char 与 short 或 char 与 byte 之间的转换必须显示地使用类型转换. 从 byte 到 char 的转换为扩展收缩转换, 该转换比较特殊, 即先将 byte 扩展转换到 int, 然后再收缩到 char.
8. 在整型数据间的扩展转换中, 如果操作数是 char 类型(无符号类型), 则进行无符号扩展, 扩展位为 0. 如果操作数是 byte,short 或 int(有符号类型), 则进行有符号扩展, 扩展位为该变量的符号位.
9. 整型数据之间的收缩转换, 仅仅是截断并丢弃高位, 不做任何其他处理.
10.0.1+0.2 不等于 0.3.System.out.println((double)0.1+(double)0.2); 这条语句的输出结果是 0.30000000000000004. 因为计算机使用二进制来存储数据, 而很多小数都不能够准确地使用二进制来表示(事实上, 大多数地小数都是近似的), 就像使用十进制小数不能准确地表示 1/3 这样地分数一样. 大多数地浮点型, 在计算机中只是近似地存储其值, 而不像整型那样准确地存储. 又例, 这是一个死循环: for(floatf=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.Cloneable 与 java.io.Serializable 接口. 数组的成员包括变量 length(隐式存在)与从 Object 类继承的成员. Cloneable 与 Serializable 是两个标记的接口, 这两个接口中没有显式声明任何成员.
28. 接口是完全抽象的设计, 不能实例化. 使 A 用 new 方式创建的借口类型, 实际上是创建了一个匿名类, 该匿名类实现了接口类型.
29. 如果两个接口声明了相同的变量 x, 则当某接口同时继承这两个接口, 或者某类同时实现这两个接口时, 通过简单名称访问会产生编译错误.
30. 如果两个接口中声明了相同名称的方法 m, 并且两个方法没有构成重载, 则当某接口能够同时继承这两个接口, 或者某类能够同时继承这两个接口时, 必须存在一种方法签名, 使得该签名同时为两个 m 方法签名的子签名, 并且在方法的返回类型上, 必须存在一种类型, 使得该类型同时为两个 m 方法返回类型的可替换类型.
来源: http://developer.51cto.com/art/201804/571105.htm