【Java基础复习1】基本数据类型、包装类型、缓存池、String等

8种基本数据类型

  • byte/8bit: 取值范围为-128~127,占用1个字节
  • short/16bit: 取值范围为-32768~32767,占用2个字节
  • int/32bit: 占用4个字节(-2的31次方到2的31次方-1)
  • float/32bit: 占用4个字节 (-3.40292347E+38~3.40292347E+38)
  • long/64bit: 占用8个字节(-2的63次方到2的63次方-1)
  • double/64bit: 占用8个字节,IEEE754
  • char/16bit:占用2个字节
  • boolean/true、false,可以使用 1 bit 来存储,但是具体大小没有明确规定。JVM 会在编译时期将 boolean 类型的数据转换为 int,使用 1 来表示 true,0 表示 false。JVM 支持 boolean 数组,但是是通过读写 byte 数组来实现的。

包装类型

所谓包装类,就是能够直接将简单类型的变量表示为一个类,在执行变量类型的相互转换时,我们会大量使用这些包装类。
包装类都为final 不可继承;包装类型都继承了Number抽象类
public final class **Integer** extends **Number** implements Comparable<Integer>
基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。
/* 手动装箱 /
Integer integer1 = Integer.valueOf(12);
/
手动拆箱 */
int intValue1 = integer1.intValue();

/* 自动装箱 /
Integer integer3 = 12;
/
自动拆箱 */
int intValue2 = integer1;

以下用途:

  • 作为基本数据类型对应的类型,提供了一系列实用的对象操作,如类型转换,进制转换等
  • 集合不允许存放基本数据类型,故常用包装类
  • 包含了每种基本类型的相关属性,如最大值,最小值,所占位数等

new Integer(123)与Integer.valueOf(123)的区别

  • new的对象都在堆里面,每次都会新建一个对象

  • Integer.valueOf(123)会使用缓存池里的对象,多次调用会取得同一个对象的引用

    valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。下面是具体的实现代码。
    image
    简单的理解,Integer 类的装箱操作,会调用 valueOf(),并开辟一块新的堆内存
    无论是手动装箱,还是自动装箱,都会调用 valueOf(),只是隐藏了这部分
    若装箱后的 Integer 对象存在于 Integer 的缓存池中,则不会创建新对象,而是直接引用自缓存池 IntegerCache

缓存池

包装类中,存在缓存池的设置,避免对象的重复创建,以 Integer 为例
在 Integer 类中,存在一个私有静态内部类 private static class IntegerCache {},如下图:
cache[],也就是Integer常量池,常量池的大小为1 Byte = 8 Bits(-128~127)
image

这是Integer缓存池的具体实现源码
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];
    static {
        int h = 127;
        String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
            }
        }
        high = h;
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
        assert IntegerCache.high >= 127;
    }
    private IntegerCache() {}
}

并非所有的包装类都存在缓存池,浮点型的 Float、Double 与 Boolean 不存在缓存池的概念。Byte、Short、Integer、Long、Character 存在缓存池,默认范围都是 -128~127

为啥把缓存设置为[-128,127]区间?

性能和资源之间的权衡。 在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax= 来指定这个缓冲池的大小。

String

String类被声明为final,因此不可以被继承。
下图是java8中的String实现,String内部使用char数组来存储数据;除此之外还有一个hash成员变量,是该String对象的哈希值的缓存
image
但在Java9之后,使用字节数组来存储了:private final byte[] value; ;成员变量 coder 的声明:private final byte coder; 使用 coder 来标识使用了哪种编码。
对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象

在Java中不可能直接操作对象本身,所有的对象都由一个引用指向,必须通过这个引用才能访问对象本身,包括获取成员变量的值,改变对象的成员变量,调用对象的方法等。
image

什么是不可变的对象?

如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。

不可变的好处:
  • 可以缓存 hash 值。以String作为HashMap的key,String的不可变保证了hash值的不可变。
  • 字符串常量池 String Pool 的需要。java 8 字符串常量池放置于方法区中。如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。
    image
  • 安全性。String 经常作为参数,String 不可变性可以保证参数不可变。如网络传输
  • 线程安全。并发场景下,多个线程同时读一个资源,不会引发竟态条件。只有对资源做写操作才有危险。不可变对象不能被写,所以线程安全。

String, StringBuffer and StringBuilder

  • String是不可变的,底层使用char[]存储
  • StringBuffer—可变的字符序列,线程安全,效率低,底层使用char[]存储,所有的方法都是synchronized同步的
  • StringBuilder—可变的字符序列;jdk5.0新增,线程不安全的,效率高,底层使用char[]存储
  • 效率从高到低:StringBuilder>StringBuffer>String
    image

AbstractStringBuilder 扩容问题:如果要添加的数据底层数组盛不下了,就需要扩容底层的数组,默认情况下扩容为原来的2倍+2,同时将原有数组中的元素复制到新的数组中

  • 在使用StringBuilder的时候,append()之后,我们一般会在后面在加上一个分隔符,例如逗号,也就是再加上一个char,而char在java中占2个字节,避免了因为添加分隔符而再次引起扩容。
    **
    开发中建议使用**:StringBuffer(int capacity) 或 StringBuilder(int capacity)//避免后续再进行扩容;

对于三者使用的总结
操作少量的数据: 适用String
单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer

posted @   tootooquan  阅读(177)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示