Andy Back-end Dev Engineer

Java基础-数据类型


数据类型

Java是强类型的编程语言,定义变量时必须声明变量的类型,数据类型分为两种,基本数据类型和引用数据类型。

基本数据类型

数据类型
1.整数类型 整数范围
2.浮点数类型 整浮点数范围
注意: (1) 在long类型后面需要加l或者L,在float类型下需要加f或者F。 (2) 精度损失时需要进行强转

代码举例:

double d = 12.345;
float f = (float) d;

// 将double类型的12.345强转为float类型
float f1 = (float) 12.345;
// f2直接就是float类型, 建议采用这种方式。
float f2 = 12.345F;

3.字符数据类型:占用空间2个字节,可以用0-65535范围的整数进行赋值。所以可以存储汉字

4.布尔类型:布尔数据类型只有两个可能的值:真和假。使用此数据类型为跟踪真/假条件的简单标记。这种数据类型就表示这一点信息,但是它的“大小”并不是精确定义的。

可以看出,boolean类型没有给出精确的定义,《Java虚拟机规范》给出了4个字节,和boolean数组1个字节的定义,具体还要看虚拟机实现是否按照规范来,所以1个字节、4个字节都是有可能的。这其实是运算效率和存储空间之间的博弈,两者都非常的重要。

参考:Oracle官方文档Boolean类型占几个字节

自动类型转换

自动类型转换 这里涉及到long可以转换为float,long为64位,float32位,但是为什么还是可以转换?原因在于float的数值表示范围大于long的表示范围,并且底层存储结构不同, 具体可参考float存储原理

另外注意:

  1. float类型值范围比较大,但是不代表区间内的所有值都一定能精确表示,事实上0.3就不能精确表示,所以不管是long到float的自动转换还是float到long的强制类型转换都有可能丢失精度。
  2. final修饰的short,char变量相加后不会被自动提升。

代码举例:

{
    byte a = 1;
    byte b = 2;
    
    // 编译出错,需要进行强转:a = (byte) (a + b), 而且byte优先级大于+,所以a = (byte) a + b这种写法是错误的。
    a = a + b;
    
    // 编译正确,+=直接隐式将右边的变量转换为左边的数据类型,在这里转为了byte类型,等价于 a = (byte) (a + b)
    //而且+= 使用的位运算,速度比上面的表达式快。
    a += b; 
}

// 几个常见byte值:
byte b1 = (byte) 128 // -128
byte b2 = (byte) 129 // -127
byte b3 = (byte) 130 // -126

// byte short定义的时候接收的式int值,然后自己做数据判断,看在不在范围内。

包装类

在Java中,很多方法需要接收引用类型的对象,因此JDK提供了乙烯类的包装类,通过这些包装类可以把基本数据类型的值包装为引用类型的对象。 包装类

Integer类的基本应用:

    // int -- String 
	int number = 100;
	String str = String.valueOf(number);
	String str2 = Integer.toString(number);
	
	// String -- int
	String str = "100";
	Integer number = new Integer(str);
	int num = number.intValue();
	
	// 注意,参数不能为null
	int num2 = Integer.parseInt(str);
	
	// 十进制到其他进制,进制范围:2-36
	// 注意,参数不能为null
	Integer.toString(100, 2);// 1100100
	// 其他进制转为十进制
	Integer.parseInt("100", 2); // 4

自动拆装箱

JDK5新特性,支持自动拆装箱 装箱:基本类型转为引用类型 拆箱:引用类型转为基本类型

    // 自动装箱
    Integer i = 100;
    // 注意判断不能为null
	if(i != null) {
		i += 100;
	}
	// 自动拆箱
	int y = i;
	
	// 通过反编译工具可以查看上一段代码
	// 自动装箱
	Integer i = Integer.valueOf(100);
	// 先自动拆箱然后自动装箱
	i = Integer.valueOf(i.intValue() + 100);

缓存池

先看一段测试代码

    Integer i1 = new Integer(127);
	Integer i2 = new Integer(127);
	System.out.println(i1 == i2);  // false
	System.out.println(i1.equals(i2)); // true
		
	Integer i3 = new Integer(128);		        Integer i4 = new Integer(128);
	System.out.println(i3 == i4);  // false
	System.out.println(i3.equals(i4)); // true
		
	Integer i5 = 127;
	Integer i6 = 127;
	System.out.println(i5 == i6); //true
	System.out.println(i5.equals(i6)); //true
		
	Integer i7 = 128;
	Integer i8 = 128;
	System.out.println(i7 == i8);  //false
	System.out.println(i7.equals(i8)); //true
	}

通过反编译工具可以看到Integer i = 127;在执行时的语句为Integer i = Integer.valueof(127), 而new Integer(127) 与 Integer.valueof(127)区别在于

  • new Integer(127)每次都会新建一个对象
  • Integer.valueof(127)会从使用缓存中的对象,多次调用会取得同一个对象的引用。

valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容,不在则使用new Integer(i)进行创建对象。

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

在java8中,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() {}
    }

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

  • 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

下一篇 Spring-AOP

Comments

Content