Java有八大基本数据类型,分为字符型char、布尔型boolean、数值型byte、short、int、long、float、double。
1、字符型
字符型char是用单引号括起来的字符,一个字符占两个字节。对应的包装类是Character,可以进行加减乘除运算,也可以比较大小。
char c1 = 'z'; //122
char c2 = 'A'; //65
System.out.println(c1+c2); //187
System.out.println(c1-c2); //57
System.out.println(c1*c2); //7930
System.out.println(c1/c2); //1
System.out.println(c1>c2); //true
字符串a-Z的值对应ASCII码表;a-z对应97-122,A-Z对应65-90;
2、布尔型
boolean是只有true和false两个取值,不能用0和非0表示。一般用于状态标识和条件判断。不能与其他数据类型进行转换。对应的包装类是Boolean
3、数值型
整数型:byte、short、int、long
byte:1个字节,-128--127,即-2^8--2^8-1 包装型为Byte
short:2个字节,-2^16--2^16-1 包装型为Short
int:4个字节,-2^32--2^32-1 包装型为Integer
long:8个字节,-2^64--2^64-1 包装型为Long
浮点型:float、double
float:4个字节 包装型Float
double:8个字节 包装型为Double
在java中int为整数型的默认类型,double为浮点型的默认类型。
4、运算与类型转换
1、类型转换
如图中关系,每一个类型可以自动转换为箭头指向的类型,而要反向转换则需要强制转换。如:
byte b1 = 127;
int s1 = b1;
long a = 1111;
double f = a;
int s2 = a; //编译错误
int s3 = (int)a;
如上,b1为byte类型,可以直接给int类型s1指向b1;会自动进行类型转换,a为long类型,直接赋值给int类型的s2将不能编译通过,要把a赋值给int类型要进行强制类型转换,如最后一行;
2、前置+与后置+
byte b1 = 127;
byte b2 = 1;
b1++;
System.out.println(b1); //-128
b1 += 1;
System.out.println(b1); //-127
int s1 = 3;
s1 = s1++;
System.out.println(s1); //3
s1 = ++s1;
System.out.println(s1); //4
s1++是先赋值再进行加11运算,++s1是先加1运算再赋值。
3、Integer类的缓存实现IntegerCache
Integer s1 = 100;
Integer s2 = 100;
System.out.println(s1==s2); //true
Integer s3 = 130;
Integer s4 = 130;
System.out.println(s3==s4); //false
上面两个情况不一样是因为再Integer内部有一个IntegerCache类,会缓存-127--128内的数字,自动装箱是利用valueof方法进行的
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high) //如果再-127--128直接就直接返回IntegerCache类里面的缓存
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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 =
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;
}}
以上为静态内部类IntegerCache类的实现,就是把-128--127之间的数组缓存起来,当需要使用的时候直接使用缓存。有效提高了程序的性能。
4、逻辑运算和位运算
int a = 1;
int b = 2;
if((a+1==1)&(b++==3)){
}
System.out.println(a); //1
System.out.println(b); //3
int a = 1;
int b = 2;
if((a+1==1)&&(b++==3)){
}
System.out.println(a); //1
System.out.println(b); //2
上面两个的结果不同是因为&&的短路运算,就是当第一个条件a+1==1不成立的时候,不会去执行后面的条件判断了,所以第二次输出的b的值还是为2,非运算"||"和“|”和与运算符是一样的,“||”也具有短路功能。
int a = 1;
int b = 2;
a = a^b;
b = a^b;
a = a^b;
System.out.println(a); //2
System.out.println(b); //1
上面利用了异或的来实现不引入临时变量两个数的交换,原理是因为一个数a,异或b再异或b会得到a;即a^b^b=a;具体实现可自己根据异或的运算看:b^b=0;然后a^0=a;
int a = 1;
int b = 16;
int c = -8;
a = a<<3;
b = b>>2;
c = c>>2;
int d = c>>>2;
System.out.println(a); //8
System.out.println(b); // 4
System.out.println(c); //-2
System.out.println(d); //1073741822
<<左移运算符常被用作乘法,它的性能比*要好,因为是直接对二进制的数字进行移动,如:00000001左移3为就是00001000,就是上面的a左移3位变成8;有符号右移和左移一样,空出来的位置用0填充(符号位不动),所以如上b和c的值为4和-2;>>>为无符号右移,即移动的时候符号位也会移动;因为int是4个字节,有32位,所以-8用二进制表示是11111111 11111111 11111111 11111000(负数的补码是原码码符号位不变取反加1),无符号右移2为就是00111111 11111111 11111111 11111110;就是1073741822的原码。
5、总结
对于包装类的出现,主要是方便面向对象编程,以及再集合中只能存储对象,不能存储基本数据类型。两者不同的区别主要是默认值:包装类默认值是null;基本数据类型数值类默认为0,char默认是'',布尔类型默认是true;逻辑运算经常被用来作为条件判断,&&和||具有短路功能。异或可以原来交换两个数,一个数异或自己是0,一个数异或自己还是本身。左移右移运算经常被用来作为乘除运算,如Java的集合类map和list中就有用到来进行扩容操作。