Skip to content

Carson带你学Java:关于数据类型的那些必知必会

Java的8种数据类型

整型:byte,short,int,long 字符:char 布尔:boolean 浮点:float,double

String

String是字符串常量,被fianl修饰的类,不可以被继承。其中存放字符的数组也被final修饰,所以string只能被赋值一次,不能够被修改。 image.png StringBuffer是线程安全的字符串变量,适用于多线程下需要频繁修改的字符串变量 StringBuilder是线程不安全的字符串变量,适用于在单线程下的字符串变量 image.png

对于String对象我们对它重新赋值,其实是创建了一个新的对象,让string重新指向这个新对象。

int和Integer的区别

  1. 基本数据类型和引用数据类型的区别
  2. Integer与int的比较
    1. int与int变量比较
    2. int与Integer变量比较
      1. int与非new创建的Integer变量
      2. int与new创建的Integer变量
    3. Integer与Integer变量比较
      1. 两个new创建的Integer变量
      2. 两个非new创建的Integer变量
      3. 一个new创建的和一个非new创建的Integer对象

基本数据类型和引用数据类型的区别

  1. int是基本数据类型,Integer是引用数据类型
  2. Integer实际是对象的引用,指向new出来的对象,int存放的是数值
  3. Integer的默认值是null,int的默认值是0

Integer与int的比较

int与int变量比较

两个基本数据类型毋庸置疑,==比较的就是数值

java
//int与int比较 
int a=100;
int b=100;
System.out.println("int与int比较:");
System.out.println(a==b);//true

int与Integer比较

int与Integer比较时,Integer对象会自动拆箱成int类型和int比较,所以本质上就是int和int比较,比较的是值。

java
//int与new Integer比较
int a1=100;
Integer b1=new Integer(100);
System.out.println("int与new Integer比较:");
System.out.println(a1==b1);//true  自动插箱

//int与非new的Integer比较
int a2=100;
Integer b2=100;//自动装箱
System.out.println("int与非new的Integer比较:");
System.out.println(a2==b2);//true  自动插箱

Integer与Integer比较

new Integer()生成的变量之间比较,我们知道new出来的对象是存放在堆区,栈中只存放对象的引用,所以new出来的Integer比较,肯定为false,比较的是两者指向堆区的内存地址,这显然是不等的。

java
//new的Integer与new的Integer比较
Integer a3=new Integer(100);
Integer b3=new Integer(100);
System.out.println("new的Integer与new的Integer比较:");
System.out.println(a3==b3);//false

非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。因为非new生成的Integer变量指向的是静态常量池中cache数组中存储的指向了堆中的Integer对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的对象引用(地址)不同

java
# 因为在Integer初始化时会自动缓存一个字节范围的数据【-128~127】,
# 因此当是直接赋值时在一个字节范围内,
# ==比较就是相等的,而大于这个范围==比较就不是相等的。

//new的Integer与非new的Integer比较
Integer a4=new Integer(100);
Integer b4=100; //自动装箱
System.out.println("new的Integer与非new的Integer比较:");
System.out.println(a4==b4);//false

对于非new创建的Integer对象,比较存在两种情况:

  1. 如果两者的值在一个字节范围内【-128,127】,那么比较结果相等
  2. 如果不在这个范围内,那么比较结果不等
java
//非new的Integer与非new的Integer比较
Integer a5=127;
Integer b5=127;
System.out.println("非new的Integer与非new的Integer比较:");
System.out.println(a5==b5);//true
Integer a6=128;
Integer b6=128;
System.out.println(a6==b6);//false

源码解析

Integer.valueOf()

为什么非new的Integer比较会有差异?为什么是【-128,127】?非new的Integer的引用存放在哪里,也是栈区吗? 首先来看一段源码: 在执行_**Integer a=100;**_时Java会自动装箱,调用valueOf()方法,IntegerCache是Integer类中的一个静态内部类,而low和high是其中的静态变量,low和high在默认情况下为-128和127,cache[]是静态数组,默认大小是_**cache = new Integer[(high - low) + 1];**_。 因此这就是为什么赋值为【-128,127】之间时,比较为true,因为是从静态数组中取值,而cache静态数组对象是存放在静态常量池中,是线程共享的。 但是存放在cache数组中的值不是静态的,源码中有如下一句_**cache[k] = new Integer(j++);**_ 这些对象是new出来的,说明存放在堆区,而cache数组中只是存储着指向这些Integer对象的引用。 如果赋值不在【-128,127】这个区间,那么就是直接**_return new Integer(i);_**这与两个直接new出来的Integer对象的比较无异,比较的是两者指向堆区的内存地址

java
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

IntegerCache静态内部类

java

/**
缓存以支持JLS要求的对-128到127(包括)之间
的值进行自动装箱的对象标识语义。
缓存在第一次使用时初始化。
缓存的大小可以通过-XX:AutoBoxCacheMax=<size>选项来控制。
在VM初始化过程中,java.lang.Integer.IntegerCache.high属性
可能会被设置并保存在sun.misc.VM类的私有系统属性中。*/
private static class IntegerCache {
    
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}