数据类型

Java虚拟机中,数据类型可以分为两类:基本类型引用类型。

  • 基本数据类型
    • 整型:byte、shot、int、long
      • byte
        • byte(8位,有符号的,以二进制补码表示的整数
        • 最小值是 -128(-2^7),也就是一个字节;最大值是 127(2^7-1);默认值是 0;
      • shot
        • 数据类型是 16 位、有符号的以二进制补码表示的整数
        • 最小值是 -32768(-2^15);最大值是 32767(2^15 - 1);默认值是 0;
      • int
        • 数据类型是32位、有符号的以二进制补码表示的整数;
        • 最小值是-2^31;最大值是2^31 - 1;默认值是 0
      • long
        • long 数据类型是 64 位、有符号的以二进制补码表示的整数;
        • 最小值是-2^63;最大值是2^63 -1;默认值是 0L
        • 例子: long a = 100000L,Long b = -200000L
        • 为了分辨L最好大写,如果不写L数据会自动变为int类型
    • float、double
      • float
        • 数据类型是单精度、32位、符合IEEE 754标准的浮点数
        • 默认值是 0.0f;
        • 浮点数不能用来表示例如货币这样精确地值
        • 例子:float f1 = 234.5f。
      • double
        • 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
        • double类型同样不能表示精确的值,如货币
        • 默认值是 0.0d
        • 例子:double d1 = 123.4。
    • 字符型:char
      • char类型是一个单一的 16 位 Unicode 字符;
    • 逻辑型:boolean
      • 默认值是 false;
  • 引用数据类型

    包装类

    byte->Byte; short->Short; int->Integer; long->Long; double->Double; float->Float; char->Charecter; boolean->Boolean;

Java 编译器对基本类型的自动装箱拆箱:
image.png
编译后的class文件:
image.png

注意:Integer.valueOf(i),这个函数,当i值在-128~127之间时,不会创建新的对象,但当i值超出这个范围就会新建一个对像,比如:

  1. Integer a = 200;
  2. Integer b = 200;
  3. // 当a和b的值在-128~127之间时,返回true,否则返回false,因此在实际开发中要用 equals 进行比较
  4. // System.out.println(a==b);’
  5. System.out.println(a.equals(b));

为什么会这样?是因为Integer缓存,默认是 -128~127,当然这个值可以配置。

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() {}
}

当==两边是基本数据类型时,==于比较的是两边的两个值是否相等,当==两边是引用类型时比较的是两个内存地址

另外一些简单但容易出错的代码:

Integer a = 100;
Integer b = 100;
System.out.println(a.equals(b));
System.out.println(a==b);

Integer c = 200;
Integer d = 200;
System.out.println(c.equals(d));
System.out.println(c==d);

int int1 = 100;
int int2 = int1;
int1 = 500;
System.out.println(int1);
System.out.println(int2);
System.out.println(int1 == int2);

int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = arr1;
arr1[3] = 8;
System.out.println(arr1[3]);
System.out.println(arr2[3]);

UserVo userVo = new UserVo();
userVo.setUserName("zhangsan");
UserVo userVo1 = userVo;
userVo.setUserName("lisi");
System.out.println(userVo.getUserName());
System.out.println(userVo1.getUserName());

结果为:

true true true false

500

100

false

8

8

lisi

lisi

java equals

image.png

结果为 true,false,false

equals是一个普通的方法,该方法返回的结果依赖于自身的实现,所以在进行判断时,要看对应的实现。

  1. person 对象并没有 equals 方法,但是他会默认继承 Object 类,在 Object 类里有equals 方法如下,实际是判断两个引用是否指向堆内存的同一地址
public boolean equals(Object obj) {
    return (this == obj);
}

image.png

  1. Integer 包装类中的 equals 实现如下:
public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

首先判断传入的对象是否是 Integer 对象,不是直接返回false,是的话再比较值是否相等

  1. String 中 equals 实现如下:
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
  • 如果两个对象指向同一个引用,则返回true;
  • 否则判断传入的对象是否是 String 对象
  • 判断两个字符串底层 char 数组的长度是否一致
  • 循环判断底层数组里的每一个 char 字符,看看是否相等。

String 底层:链接