common knowledge of java (避坑指南)

1. java语言中 函数参数是基本数据类型时传参是值传递的, 参数是对象时参数也是值传递只不过时的是传递对象的引用。

2. java基本数据类型

- byte     1个字节     取值  -128(10000000,-2^7)——+127(01111111,2^7-1)
- short 2个字节    取值      -32768(-2^15)————32767(2^15-1)
- int    4个自己    取值  -2,147,483,648(-2^31)————2,147.483,647(2^31-1)
- long    8个字节    取值      -9,223,372,036,854,775,808(-2^63)————0,223,372,036,854,775,807(2^63-1)

3. 溢出示例

1
2
3
4
5
6
int i = Integer.MAX_VALUE;
int j = Integer.MAX_VALUE;
int k = i + j;
System.out.println("k="+k);
output:
k=-2

3. 浮点数不能来表示金额,应该使用BigDecimal或者Long(单位为分)来表示金额。

4. transient 关键字修饰的对象或成员变量在序列化时会被忽略,反序列化时设为初始值。

5. instanceof 关键字时一个二元操作符类似‘==’,‘>’。

6. synchronized 特性 synchronized既可以修饰方法也可以修饰代码块

+ 可见性
+ 有序性
+ 原子性  synchronized的原子性指的是一个操作不可能中断,必须完全执行完毕, 否则就不执行。

7. volatile 特性 volatile 关键字是一个轻量级的synchronized,只能修饰变量 不能修饰方法和代码块。 当java内存模型中多级缓存写操作volatile修饰的变量时jvm会lock这个变量并且将这个变量回写到主缓存中。

+ 可见性
+ 有序性
+ 不具原子性

8. String的所有方法都不改变原有值只是返回一个新对象

9. 其他字符串类

+ StringBuffer      //线程安全
+ StringBuilder        //线程不安全
+ apache.commons.StringUtil        //拼接数组 

循环体内推荐使用StringBuffer或者 StringBuilder拼接 使用+每次都会new一个新String 资源浪费!

10. 字符串拼接效率 StringBuild>StringBuffer>concat>StringUtil.join

11. 常量池

- Class常量池
- 字符串常量池
- 运行时常量池

12. 字符串常量池存放位置

- JDK1.7以前 : 存在永久代 
- JDK1.7     : 存放在堆内存中, 
- JDK1.7以后 : 再次移动到永久代

13. Class常量池可以看作Class文件的资源仓库

查看Class文件中常量池的方法:

1
javap -v helloword.class

14. 常量池中存放的常量分两大类

- 字面量(Literal)
- 符号引用(symbolic references)

15. 字面量 - 是由字母,数字等构成的数值。指的是等号右边的值。

- 字母
- 数字

16. 符号引用

- 类和接口的权限定名      //eg: public class xxx
- 字段的名称和描述符        //eg: public String name
- 方法的名称和描述符        //eg: public void add()

17. 运行时常量

- 运行时常量分配在JVM的方法区
- JDK1.7之前 存在于永久代
- JDK1.7 存在于    堆内存
- JDK1.7后 存在于元空间

JVM虚拟机启动时把class文件载入到运行时常量池就是内存中, 如果class常量池中包含字符串
会被装载到字符串常量池

18. intern作用: 返回字符串常量池中该字符串引用,如果字符串常量池没油该字符串就创建并返回它的引用

19. 一个String的编译期最大长度时 65534, 运行期最大 Integer.MAX_VALUE~4G

20. 包装类与拆装箱

- 8大基本数据类型对应包装类

基本数据类型 包装类
byte Byte
boolean Boolean
short Short
char Character
int
long Long
float Float
double Double
  • 基本数据类型存储在栈中,效率高。
  • 为什么需要包装类? 因为面向对象的集合容器的元素等很多地方需要是Object

java SE5之前

1
Integer i= new Integer(10);   //装箱

java SE5之后

1
2
Integer i = 10;     //自动装箱
int b = i; //自动拆箱

21. 自动装箱缓存

1
2
3
4
5
6
7
8
9
10
	Integer i1 = 3;
Integer i2 = 3;
Integer i3 = 300;
Integer i4 = 300;
System.out.println(i1==i2);
System.out.println(i3==i4);

output:
true
false

tips:
- Java5开始整型对象数值区间 -128——127 之间数值 自动装箱时会实现缓存重用。

- Java6最大值+127 可以通过 java.lang.Integer.IntegerCache.high设置
- 通过 –XX:AutoBoxCacheMax=size 修改

22. 自动拆装箱缓存变量范围

- Integer: -128——127
- Boolean: true false
- Character '\u0000' 至 '\u007f' 

tips: 超出缓存范围内的变量 需要使用 equals比较,缓存范围内可以使用==比较
如果for循环内有大量拆装箱操作 ,会浪费很大资源

boolean/Boolean类型及命名(succecss/isSuccess)规范

  • boolean success
  • boolean isSuccess
  • Boolean success
  • Boolean isSuccess

    tips: POJO类型中布尔变量 不能前面加’is’ (避免getter setter问题)

基础数据类型和包装类型使用规范

- 所以POJO类属性,必须使用包装类型
- 所有RPC类方法的参数和返回值必须使用包装类
- 所有局部变量必须使用基础数据