Carson带你学Java:关于数据类型的那些必知必会
Java的8种数据类型
整型:byte,short,int,long 字符:char 布尔:boolean 浮点:float,double
String
String是字符串常量,被fianl修饰的类,不可以被继承。其中存放字符的数组也被final修饰,所以string只能被赋值一次,不能够被修改。 StringBuffer是线程安全的字符串变量,适用于多线程下需要频繁修改的字符串变量 StringBuilder是线程不安全的字符串变量,适用于在单线程下的字符串变量
对于String对象我们对它重新赋值,其实是创建了一个新的对象,让string重新指向这个新对象。
int和Integer的区别
- 基本数据类型和引用数据类型的区别
- Integer与int的比较
- int与int变量比较
- int与Integer变量比较
- int与非new创建的Integer变量
- int与new创建的Integer变量
- Integer与Integer变量比较
- 两个new创建的Integer变量
- 两个非new创建的Integer变量
- 一个new创建的和一个非new创建的Integer对象
基本数据类型和引用数据类型的区别
- int是基本数据类型,Integer是引用数据类型
- Integer实际是对象的引用,指向new出来的对象,int存放的是数值
- Integer的默认值是null,int的默认值是0
Integer与int的比较
int与int变量比较
两个基本数据类型毋庸置疑,==比较的就是数值
//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比较,比较的是值。
//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,比较的是两者指向堆区的内存地址,这显然是不等的。
//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()生成的变量指向堆中新建的对象,两者在内存中的对象引用(地址)不同
# 因为在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对象,比较存在两种情况:
- 如果两者的值在一个字节范围内【-128,127】,那么比较结果相等
- 如果不在这个范围内,那么比较结果不等
//非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对象的比较无异,比较的是两者指向堆区的内存地址
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache静态内部类
/**
缓存以支持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() {}
}