基本数据类型111
2020-11-25 / highPhone啊

java有8种基本数据类型及其包装类

        (自动装箱)
    -------------------->
    <--------------------
        (自动拆箱)
byte    (1个字节)   --->    Byte
short   (2个字节)   --->    Short
int     (4个字节)   --->    Integer
long    (8个字节)   --->    Long
float   (4个字节)   --->    Float
double  (8个字节)   --->    Double
char    (2个字节)   --->    Char
boolean (1个字节)   --->    Boolean

基本类型之间的类型转换规则

boolean类型不参与类型转换,其他7种类型按照以下规则转换

  1. 如果运算符任意一方的类型为double,则另一方会转换为double
  2. 否则,如果运算符任意一方的类型为float,则另一方会转换为float
  3. 否则,如果运算符任意一方的类型为long,则另一方会转换为long
  4. 否则,两边都会转换为int

基本数据类型中一些有意思的现象

boolean与Boolean

boolean类型只有truefalse两个值,在底层使用0(false)和1(true)存储,所以它需要一个字节来存储。
通过自动拆箱给boolean变量初始化时,如果送入包装类Boolean的初始化参数为String类型,则送入”true”,则返回一个true,其余情况都是返回false,如下传入”aaa”,得到的boolean值为false

1
2
boolean o1 = new Boolean("true");  //true
boolean o2 = new Boolean("aaa"); //false

Boolean送入String的构造方法如下:

1
2
3
4
5
6
public Boolean(String s) {
this(parseBoolean(s));
}
public static boolean parseBoolean(String s) {
return ((s != null) && s.equalsIgnoreCase("true"));
}

int和Integer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class IntegerTest {

public static void main(String[] args) {
int i1 = 127;
Integer i2 = 127; //自动装箱:Integer i2 = Integer.valueOf(127);
Integer i3 = 127;
Integer i4 = new Integer(127);
int i6 = 128;
Integer i7 = 128;
Integer i8 = 128;
Integer i9 = new Integer(128);
System.out.println(i1 == i2); //true //自动拆箱
System.out.println(i2 == i3); //true //IntegerCache范围是-128~127,所以两次Integer.valueOf()返回的都是IntegerCache里面同一个对象,所以相等
System.out.println(i1 == i4); //true //int与Integer用==进行比较,Integer自动拆箱为int类型,所以相等
System.out.println(i6 == i7); //true //自动拆箱
System.out.println(i7 == i8); //false //128没在IntegerCache里面,所以两次Integer.valueOf()返回了不同的包装类对象,所以不相等
System.out.println(i7 == i9); //false //包装类为对象,只要比较的两个其中有一个为new创建的,==比较的就是两个不同的对象,所以不相等
}
}

JDK1.8中Integer.valueOf()和Integer缓存池源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)]; //如果在-128~127之间,返回IntegerCache里面的Integer
return new Integer(i);//如果不在-128~127之间,返回new Integer(i);
}
//内部类 IntegerCache
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() {}
}

float和double

float和double作为浮点数,在计算过程中,容易造成精度丢失问题,所以在金额的计算,例如银行等金融机构的业务中,应该避免使用浮点数来存储金额数据,为确保精确,应使用java.math.BigDecimal。

浮点数运算小数带来精度丢失问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
float f1 = 0.1f;    //0.1
double d1 = 1.0/10; //0.1
float f2 = 1.0f/10; //0.1
System.out.println(f1 == d1); //false
System.out.println(f2 == d1); //false
System.out.println(f1 == f2); //true
System.out.println(f1 * f2); //0.010000001
System.out.println("=============================");
float f3 = 0.5f; //0.5
double d2 = 1.0/2; //0.5
float f4 = 1.0f/2; //0.5
System.out.println(f3 == d2); //true
System.out.println(f4 == d2); //true
System.out.println(f3 == f4); //true
System.out.println(f3 * f4); //0.25

出现以上原因跟十进制小数如何转成二进制小数有关
算法是乘以2直到没有了小数为止:

0.1表示成二进制数:
0.1*2=0.2       取整数部分 0

0.2*2=0.4       取整数部分 0

0.4*2=0.8       取整数部分 0

0.8*2=1.6       取整数部分 1

0.6*2=1.2       取整数部分 1

0.2*2=0.4       取整数部分 0

0.4*2=0.8       取整数部分 0

0.8*2=1.6       取整数部分 1
.........
0.1二进制表示为(从上往下): 00011001......

有点类似10进制无法精确表示1/3,二进制也无法精确表示某些小数,计算时会有舍入误差。

char

所有的字符本质还是数字,所有的字符都在Unicode编码表里面找到对应的数字,范围是[0,65535),2的16次方,unicode编码用十六进制表示[u0000 - uFFFF];

1
2
3
4
5
6
7
8
9
10
char c1 = 'A';
char c2 = '中';
char c3 = '\u0061'; //unicode 编码 16进制表示

System.out.println(c1); //A
System.out.println((int)c1); //65
System.out.println(c2); //中
System.out.println((int)c2); //20013
System.out.println(c3); //a
System.out.println((int)c3); //97
本文链接:https://highphone.xyz/f7fe0af2.html