Java 基础 - 知识点

97 阅读4分钟

www.pdai.tech/

Java 基础 - 知识点

数据类型

包装类型

八个基本类型:

  • boolean/1
  • byte/8
  • char/16
  • short/16
  • int/32
  • float/32
  • long/64
  • double/64

基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。

缓存池

基本类型对应的缓冲池如下:

  • boolean values true and false
  • all byte values
  • short values between -128 and 127
  • int values between -128 and 127
  • char in the range \u0000 to \u007F(128)

在使用这些基本类型对应的包装类型时,就可以直接使用缓冲池中的对象。

String

String 被声明为 final,因此它不可被继承。(是说String这个类,不能被别人继承,不是说他作为属性)

内部使用 char 数组存储数据,该数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组。并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

不可变的好处

1. 可以缓存 hash 值

例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。

2. String Pool 的需要(字符串常量池)

如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。(上述的创建,指的是直接字符串声明的创建,new的方式创建String,见下面的intern)

字符串常量池和静态变量在堆中,运行时常量池在元空间中。可以通过OOM的报错,来查看他们在哪里报的错。

3. 安全性

String 经常作为参数,String 不可变性可以保证参数不可变。

4. 线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全地使用。

不可变自然会变得安全。

String, StringBuffer and StringBuilder

1. 可变性

  • String 不可变
  • StringBuffer 和 StringBuilder 可变

2. 线程安全

  • String 不可变,因此是线程安全的
  • StringBuilder 不是线程安全的
  • StringBuffer 是线程安全的,内部使用 synchronized 进行同步

通过阅读源码发现,StringBuffer内部的操作,都添加了synchronized,保证同一时刻,只有一人操作。

除了有些函数,通过调用父类函数,将参数转化成子类StringBuffer添加了synchronized的函数,进行调用。

String.intern()

使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象。

采用 new String() 的方式新建了两个不同对象,二者之间的地址是不相等的,采用String.intern() 可以获得对象引用。intern() 首先把 字符串 引用的对象放到 String Pool(字符串常量池)中,然后返回这个对象引用。

采用双引号的形式创建字符串实例,会自动地将新建的对象放入 String Pool 中。

通常来说,我们提到的常量池分为三种

  • class文件中的常量池
  • 运行时常量池
  • 字符串常量池

JAVA8方法区用元空间代替永久代,字符串常量池和静态常量放入java堆中,运行时常量池放入元空间中,元空间采用本地内存,而非原来永久代的jvm内存,避免运行时常量池OOM。元空间中维护着字符串常量池的表(这个不确定)。

BigDecimal

因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。只能无限接近于那个值。BigDecimal是Java中用来表示任意精确浮点数运算的类。价格必须要用BigDecimal来声明。Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。

BigDecimal在进行入库时, 数据库选择decimal类型, 长度可以自定义, 如18; 小数点我们项目中用的是2, 保留2位小数. 此外还要注意的就是默认值, 一定写成0.00, 不要用默认的NULL, 否则在进行加减排序等操作时, 会带来转换的麻烦!

饿了么技术专家总结之——double与BigDecimal使用姿势

阿里的编码规范中强调统一带小数的类型一律使用Decimal类型

\