文章目录
一、前言二、基本类型常量池2.1 Boolean常量池代码1——常量池比较 true代码2——新建对象比较 一定返回false代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.2 字符型(Character)常量池代码1——常量池比较(涉及常量池:Character在(0 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)代码2——新建对象比较(直接比较new对象,一定为false,拆箱比较,一定为true)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.3 Byte常量池代码1——常量池比较(-128~127全部为true,byte也不能超过这个范围,所以byte全部为true)代码2——新建对象后比较(直接比较new对象,一定为false,拆箱比较,一定为true)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.4 Short常量池代码1——常量池比较(涉及常量池:Short在(-128 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)代码2——新建对象后比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.5 Integer常量池代码1——常量池比较(涉及常量池:Integer在(-128 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)代码2——新建对象比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.6 Long常量池代码1——常量池比较(涉及常量池:Long在(-128 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)代码2——新建对象比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.7 Float常量池代码1——常量池比较(涉及常量池:Float无常量池技术,所以在堆中新建对象,所以返回为false)代码2——新建对象比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较;整个过程与常量池技术无关)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
2.8 Double常量池代码1——常量池比较(涉及常量池:Double无常量池技术,所以在堆中新建对象,所以返回为false)代码2——新建变量比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较;整个过程与常量池技术无关)代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
三、引用类型常量池(String常量池)四、面试金手指4.1 对象类型4.2 基本类型4.3 常量池技术
五、尾声
一、前言
Java中常量池大体可以分为:静态常量池,运行时常量池。
class文件常量池:存在于class文件中,如经常使用的javap -verbose中;
运行时常量池:就是在class文件被加载进了内存之后,常量池保存在了方法区中。
通常说的常量池指的是运行时常量池,本文讨论的都是运行时常量池。
二、基本类型常量池
Java中基本类型的常量池技术不是由基本类型实现的,而是由基本类型对应的包装类型实现的。但是因为Java5.0后引入自动装包和自动拆包,所以这一点已经不重要了。
基本类型包装类型常量池技术常量池范围
boolBoolean实现了常量池true/falsecharCharacter实现了常量池0~127byteByte实现了常量池-128~127shortShort实现了常量池-128~127intInterger实现了常量池-128~127longLong实现了常量池-128~127floatFloat未实现常量池未实现常量池doubleDouble未实现常量池未实现常量池
2.1 Boolean常量池
代码1——常量池比较 true
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Boolean boolean1
= true;
Boolean boolean2
= true;
System.out.println
(boolean1
== boolean2
);// 打印true 包装类型Boolean实现了常量池技术
boolean1
= false;
boolean2
= false;
System.out.println
(boolean1
== boolean2
);//
true
}
}
输出:
true
true
代码2——新建对象比较 一定返回false
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Boolean boolean1
= new Boolean
(true
);
Boolean boolean2
= new Boolean
(true
);
System.out.println
(boolean1
== boolean2
);//
false 不同对象指向不同地址
}
}
输出:
false
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
boolean _b1
=true
;
boolean _b2
=true
;
System.out.println
(_b1
==_b2
);//true
}
}
输出:
true
金手指:Boolean/boolean
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,常量池(编译时类型为包装类型,运行时类型为基本类型)比较介于两者之间,常量池范围内(true|false)为true,又常量池覆盖Boolean所有范围(true|false),故Boolean常量池均为true。
2.2 字符型(Character)常量池
代码1——常量池比较(涉及常量池:Character在(0 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Character _cCharacter
= (char
) -1
;
Character _cCharacter2
= (char
) -1
;
System.out.println
(_cCharacter
== _cCharacter2
);//
false
Character _cCharacter3
= (char
) 0
;
Character _cCharacter4
= (char
) 0
;
System.out.println
(_cCharacter3
== _cCharacter4
);//
true
Character _cCharacter5
= (char
) 127
;
Character _cCharacter6
= (char
) 127
;
System.out.println
(_cCharacter5
== _cCharacter6
);//
true
Character _cCharacter7
= (char
) 128
;
Character _cCharacter8
= (char
) 128
;
System.out.println
(_cCharacter7
== _cCharacter8
);//
false
}
}
输出:
false
true
true
false
代码2——新建对象比较(直接比较new对象,一定为false,拆箱比较,一定为true)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Character _cCharacter0
= new Character
((char
) 0
);
Character _cCharacter
= new Character
((char
) -1
);
Character _cCharacter2
= new Character
((char
) -1
);
System.out.println
("新建对象后比较: " +
(_cCharacter
== _cCharacter2
));
System.out.println
("自动拆箱后比较: " +
(_cCharacter
== _cCharacter2 + _cCharacter0
));
Character _cCharacter3
= new Character
((char
) 0
);
Character _cCharacter4
= new Character
((char
) 0
);
System.out.println
("新建对象后比较: " +
(_cCharacter3
== _cCharacter4
));
System.out.println
("自动拆箱后比较: " +
(_cCharacter3
== _cCharacter4 + _cCharacter0
));
Character _cCharacter5
= new Character
((char
) 127
);
Character _cCharacter6
= new Character
((char
) 127
);
System.out.println
("新建对象后比较: " +
(_cCharacter5
== _cCharacter6
));
System.out.println
("自动拆箱后比较: " +
(_cCharacter5
== _cCharacter6 + _cCharacter0
));
Character _cCharacter7
= new Character
((char
) 128
);
Character _cCharacter8
= new Character
((char
) 128
);
System.out.println
("新建对象后比较: " +
(_cCharacter7
== _cCharacter8
));
System.out.println
("自动拆箱后比较: " +
(_cCharacter7
== _cCharacter8 + _cCharacter0
));
}
}
输出:
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
char _cCharacter
= (char
) -1
;
char _cCharacter2
= (char
) -1
;
System.out.println
(_cCharacter
== _cCharacter2
);//
true
char _cCharacter3
= (char
) 0
;
char _cCharacter4
= (char
) 0
;
System.out.println
(_cCharacter3
== _cCharacter4
);//
true
char _cCharacter5
= (char
) 127
;
char _cCharacter6
= (char
) 127
;
System.out.println
(_cCharacter5
== _cCharacter6
);//
true
char _cCharacter7
= (char
) 128
;
char _cCharacter8
= (char
) 128
;
System.out.println
(_cCharacter7
== _cCharacter8
);//
true
}
}
输出:
true
true
true
true
金手指:Character/char
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,常量池(编译时类型为包装类型,运行时类型为基本类型)比较介于两者之间,常量池范围内(0~127)为true,常量池范围外jvm会重新新建对象,故为false。
2.3 Byte常量池
代码1——常量池比较(-128~127全部为true,byte也不能超过这个范围,所以byte全部为true)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
// Byte _bByte
=(byte
) -129
;
// Byte _bByte2
=(byte
) -129
; byte仅一个字节 -128~127 超出范围
Byte _bByte3
= -128
;
Byte _bByte4
= -128
;
System.out.println
(_bByte3
== _bByte4
);
Byte _bByte5
= 127
;
Byte _bByte6
= 127
;
System.out.println
(_bByte5
== _bByte6
);
// Byte _bByte7
=(byte
) 128
;
// Byte _bByte8
=(byte
) 128
; byte仅一个字节 -128~127 超出范围
}
}
输出:
true
true
代码2——新建对象后比较(直接比较new对象,一定为false,拆箱比较,一定为true)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Byte _bByte0
= new Byte
((byte
) 0
);
Byte _bByte3
= new Byte
((byte
) -128
);
Byte _bByte4
= new Byte
((byte
) -128
);
System.out.println
("新建对象后比较: " +
(_bByte3
== _bByte4
));
System.out.println
("自动拆箱后比较: " +
(_bByte3
== _bByte4 + _bByte0
));
Byte _bByte5
= new Byte
((byte
) 127
);
Byte _bByte6
= new Byte
((byte
) 127
);
System.out.println
("新建对象后比较: " +
(_bByte5
== _bByte6
));
System.out.println
("自动拆箱后比较: " +
(_bByte5
== _bByte6 + _bByte0
));
}
}
输出:
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
byte _bByte3
= -128
;
byte _bByte4
= -128
;
System.out.println
(_bByte3
== _bByte4
);
byte _bByte5
= 127
;
byte _bByte6
= 127
;
System.out.println
(_bByte5
== _bByte6
);
}
}
输出:
true
true
金手指:Byte/byte
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,常量池(编译时类型为包装类型,运行时类型为基本类型)比较介于两者之间,常量池范围内(-128 ~ 127)为true,又常量池覆盖Byte所有范围(-128~127),故Byte常量池均为true。
2.4 Short常量池
代码1——常量池比较(涉及常量池:Short在(-128 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Short _sShort
=-129
;
Short _sShort2
=-129
;
System.out.println
(_sShort
==_sShort2
);
Short _sShort3
=-128
;
Short _sShort4
=-128
;
System.out.println
(_sShort3
==_sShort4
);
Short _sShort5
=127
;
Short _sShort6
=127
;
System.out.println
(_sShort5
==_sShort6
);
Short _sShort7
=128
;
Short _sShort8
=128
;
System.out.println
(_sShort7
==_sShort8
);
}
}
输出:
false
true
true
false
代码2——新建对象后比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Short _sShort0
= new Short
((short
) 0
);
Short _sShort
= new Short
((short
) -129
);
Short _sShort2
= new Short
((short
) -129
);
System.out.println
("新建对象后比较: " +
(_sShort
== _sShort2
));
System.out.println
("自动拆箱后比较: " +
(_sShort
== _sShort2 + _sShort0
));
Short _sShort3
= new Short
((short
) -128
);
Short _sShort4
= new Short
((short
) -128
);
System.out.println
("新建对象后比较: " +
(_sShort3
== _sShort4
));
System.out.println
("自动拆箱后比较: " +
(_sShort3
== _sShort4 + _sShort0
));
Short _sShort5
= new Short
((short
) 127
);
Short _sShort6
= new Short
((short
) 127
);
System.out.println
("新建对象后比较: " +
(_sShort5
== _sShort6
));
System.out.println
("自动拆箱后比较: " +
(_sShort5
== _sShort6 + _sShort0
));
Short _sShort7
= new Short
((short
) 128
);
Short _sShort8
= new Short
((short
) 128
);
System.out.println
("新建对象后比较: " +
(_sShort7
== _sShort8
));
System.out.println
("自动拆箱后比较: " +
(_sShort7
== _sShort8 + _sShort0
));
}
}
输出:
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
short _sShort
= -129
;
short _sShort2
= -129
;
System.out.println
(_sShort
== _sShort2
);
short _sShort3
= -128
;
short _sShort4
= -128
;
System.out.println
(_sShort3
== _sShort4
);
short _sShort5
= 127
;
short _sShort6
= 127
;
System.out.println
(_sShort5
== _sShort6
);
short _sShort7
= 128
;
short _sShort8
= 128
;
System.out.println
(_sShort7
== _sShort8
);
}
}
输出:
true
true
true
true
金手指:Short/short
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,常量池(编译时类型为包装类型,运行时类型为基本类型)比较介于两者之间,常量池范围内(-128~127)为true,常量池范围外会jvm重新新建对象,故为false。
2.5 Integer常量池
代码1——常量池比较(涉及常量池:Integer在(-128 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Integer _iInteger
=-129
;
Integer _iInteger2
=-129
;
System.out.println
(_iInteger
==_iInteger2
);
Integer _iInteger3
=-128
;
Integer _iInteger4
=-128
;
System.out.println
(_iInteger3
==_iInteger4
);
Integer _iInteger5
=127
;
Integer _iInteger6
=127
;
System.out.println
(_iInteger5
==_iInteger6
);
Integer _iInteger7
=128
;
Integer _iInteger8
=128
;
System.out.println
(_iInteger7
==_iInteger8
);
}
}
输出:
false
true
true
false
代码2——新建对象比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Integer _iInteger0
=new Integer
(0
);
Integer _iInteger
=new Integer
(-129
);
Integer _iInteger2
=new Integer
(-129
);
System.out.println
("新建对象后比较: "+
(_iInteger
==_iInteger2
));
System.out.println
("自动拆箱后比较: "+
(_iInteger
==_iInteger2+_iInteger0
));
Integer _iInteger3
=new Integer
(-128
);
Integer _iInteger4
=new Integer
(-128
);
System.out.println
("新建对象后比较: "+
(_iInteger3
==_iInteger4
));
System.out.println
("自动拆箱后比较: "+
(_iInteger3
==_iInteger4+_iInteger0
));
Integer _iInteger5
=new Integer
(127
);
Integer _iInteger6
=new Integer
(127
);
System.out.println
("新建对象后比较: "+
(_iInteger5
==_iInteger6
));
System.out.println
("自动拆箱后比较: "+
(_iInteger5
==_iInteger6+_iInteger0
));
Integer _iInteger7
=new Integer
(128
);
Integer _iInteger8
=new Integer
(128
);
System.out.println
("新建对象后比较: "+
(_iInteger7
==_iInteger8
));
System.out.println
("自动拆箱后比较: "+
(_iInteger7
==_iInteger8+_iInteger0
));
}
}
输出:
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
int _int1
= -129
;
int _int2
= -129
;
System.out.println
(_int1
== _int2
);
int _int3
= -128
;
int _int4
= -128
;
System.out.println
(_int3
== _int4
);
int _int5
= 127
;
int _int6
= 127
;
System.out.println
(_int5
== _int6
);
int _int7
= 128
;
int _int8
= 128
;
System.out.println
(_int7
== _int8
);
}
}
输出:
true
true
true
true
金手指:Integer/int
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,常量池(编译时类型为包装类型,运行时类型为基本类型)比较介于两者之间,常量池范围内(-128~127)为true,常量池范围外会jvm重新新建对象,故为false。
2.6 Long常量池
代码1——常量池比较(涉及常量池:Long在(-128 ~ 127)使用常量池技术,返回为true,范围外在堆中新建对象,返回为false)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Long _iLong
= (long
) -129
;
Long _iLong2
= (long
) -129
;
System.out.println
(_iLong
== _iLong2
);
Long _iLong3
= (long
) -128
;
Long _iLong4
= (long
) -128
;
System.out.println
(_iLong3
== _iLong4
);
Long _iLong5
= (long
) 127
;
Long _iLong6
= (long
) 127
;
System.out.println
(_iLong5
== _iLong6
);
Long _iLong7
= (long
) 128
;
Long _iLong8
= (long
) 128
;
System.out.println
(_iLong7
== _iLong8
);
}
}
输出:
false
true
true
false
代码2——新建对象比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Long _iLong0
= new Long
(0
);
Long _iLong
= new Long
((long
) -129
);
Long _iLong2
= new Long
((long
) -129
);
System.out.println
("新建对象后比较: " +
(_iLong
== _iLong2
));
System.out.println
("自动拆箱后比较: " +
(_iLong
== _iLong2 + _iLong0
));
Long _iLong3
= new Long
((long
) -128
);
Long _iLong4
= new Long
((long
) -128
);
System.out.println
("新建对象后比较: " +
(_iLong3
== _iLong4
));
System.out.println
("自动拆箱后比较: " +
(_iLong3
== _iLong4 + _iLong0
));
Long _iLong5
= new Long
((long
) 127
);
Long _iLong6
= new Long
((long
) 127
);
System.out.println
("新建对象后比较: " +
(_iLong5
== _iLong6
));
System.out.println
("自动拆箱后比较: " +
(_iLong5
== _iLong6 + _iLong0
));
Long _iLong7
= new Long
((long
) 128
);
Long _iLong8
= new Long
((long
) 128
);
System.out.println
("新建对象后比较: " +
(_iLong7
== _iLong8
));
System.out.println
("自动拆箱后比较: " +
(_iLong7
== _iLong8 + _iLong0
));
}
}
输出:
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
新建对象后比较:
false
自动拆箱后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
long _iLong
= -129L
;
long _iLong2
= -129L
;
System.out.println
(_iLong
== _iLong2
);
long _iLong3
= -128L
;
long _iLong4
= -128L
;
System.out.println
(_iLong3
== _iLong4
);
long _iLong5
= 127L
;
long _iLong6
= 127L
;
System.out.println
(_iLong5
== _iLong6
);
long _iLong7
= 128L
;
long _iLong8
= 128L
;
System.out.println
(_iLong7
== _iLong8
);
}
}
输出:
true
true
true
true
金手指:Long/long
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,常量池(编译时类型为包装类型,运行时类型为基本类型)比较介于两者之间,常量池范围内(-128~127)为true,常量池范围外会jvm重新新建对象,故为false。
2.7 Float常量池
代码1——常量池比较(涉及常量池:Float无常量池技术,所以在堆中新建对象,所以返回为false)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Float _fFloat
= 1.0f
;
Float _fFloat2
= 1.0f
;
System.out.println
(_fFloat
== _fFloat2
);//
false 浮点型没有实现常量池技术
}
}
输出:
false
代码2——新建对象比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较;整个过程与常量池技术无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Float _fFloat0
= new Float
(0.0f
);
Float _fFloat
= new Float
(1.0f
);
Float _fFloat2
= new Float
(1.0f
);
System.out.println
("新建对象后比较: " +
(_fFloat
== _fFloat2
));
System.out.println
("自动拆箱后比较: " +
(_fFloat
== _fFloat2 + _fFloat0
));
}
}
输出:
新建对象后比较:
false
新建对象后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
float _float1
= 1.0f
;
float _float2
= 1.0f
;
System.out.println
(_float1
== _float2
);
}
}
输出:
true
金手指:Float/float
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,Float无常量池技术,常量池比较jvm会重新新建对象,故为false。
2.8 Double常量池
代码1——常量池比较(涉及常量池:Double无常量池技术,所以在堆中新建对象,所以返回为false)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Double _dDouble
= 1.0d
;
Double _dDouble2
= 1.0d
;
System.out.println
(_dDouble
== _dDouble2
);//
false 浮点型没有实现常量池技术
}
}
输出:
false
代码2——新建变量比较(直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较;整个过程与常量池技术无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
Double _dDouble0
= new Double
(0.0d
);
Double _dDouble
= new Double
(1.0d
);
Double _dDouble2
= new Double
(1.0d
);
System.out.println
("新建对象后比较: " +
(_dDouble
== _dDouble2
));//
false 浮点型没有实现常量池技术
System.out.println
("自动拆箱后比较: " +
(_dDouble
== _dDouble2 + _dDouble0
));
}
}
输出:
新建对象后比较:
false
自动拆箱后比较:
true
注意: 当出现运算符的时候,包装类型不可能直接用来运算,所以会进行一次拆箱成为基本数字进行比较,所以变成了两个基本类型之间的比较,仅比较值,则为true。
代码3——基本类型比较(true 栈内存中,数值相等即为true,与常量池无关)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
double _dDouble
= 1.0d
;
double _dDouble2
= 1.0d
;
System.out.println
(_dDouble
== _dDouble2
);
}
}
输出:
true
金手指:Double/double
第一,基本类型仅比较值,全为true;
第二,新建对象比较引用(即内存地址),全为false, 运算符拆箱后变为基本类型,全为true;
第三,Double无常量池技术,常量池比较jvm会重新新建对象,故为false。
三、引用类型常量池(String常量池)
package mypackage
;
public class TestConstantPool
{
public static void main
(String
[] args
) {
String s1
= "Hello";
String s2
= "Hello";
String s3
= "Hel" +
"lo";
String s4
= "Hel" + new String
("lo");
String s5
= new String
("Hello");
String s6
= s5.intern
();
String s7
= "H";
String s8
= "ello";
String s9
= s7 + s8
; //
System.out.println
(s1
== s2
); //
true 理由:s1和s2右边赋值都是显式写死的,是编译器可以预知的,编译期间,直接放到class文件的常量池中,运行时,指向同一个地址
System.out.println
(s1
== s3
); //
true 理由:s1右边是显式写死的,s3也是显式写死的,没有使用变量,所有s1、s3都是编译器可以预见的,编译时放入静态常量池中,指向同一地址
System.out.println
(s1
== s4
); //
false 理由:s4右边拼接的时候使用了new String
(),编译时不可预知,需要运行时确定,
System.out.println
(s1
== s9
); //
false 理由:s9由s7、s8拼接,s7和s8都是变量,编译时不可预知
System.out.println
(s4
== s5
); //
false 理由:s4右边使用new String
(),编译时不可预知,s5右边也使用new String
(),编译时不可预知
System.out.println
(s1
== s6
); //
true 理由:s5已经在堆中,s6
= s5.intern
();
//intern方法会尝试将Hello字符串添加到常量池中,并返回其在常量池中的地址,因为常量池中已经有了Hello字符串,所以intern方法直接返回地址;而s1在编译期就已经指向常量池了,因此s1和s6指向同一地址,相等。
}
}
输出:
true // 两边都有变量,但是没有变量拼接
true // 两边变量,右边常量拼接
false // 两边变量,右边变量拼接,有newString
() 一定false
false // 两边都有变量,右边变量拼接,为false,没有intern
()和final
false // 两边都有变量,右边变量拼接,有newString
() 一定false
true 两边都有变量,右边变量拼接,但是右边intern
()
四、面试金手指
4.1 对象类型
对于八种对象(即boolean character byte short int long float double):
第一,如果直接比较new对象,一定为false,与-128 ~ 127范围无关,纯对象比较;
第二,对于拆箱:short int long float double (即后面五种)拆箱比较,一定为true,与-128 ~ 127范围无关,纯数值比较(拆箱比较等同于下面的基本数据类型比较,全为true),整个过程与常量池技术无关。
4.2 基本类型
对于基本类型(boolean char byte short int long float double)都栈内存上,不涉及-128 ~ 127的数值范围,与常量池技术无关。
4.3 常量池技术
对于六种类型使用的常量池技术:
boolean 全部为true 取值就两个;
Character 0-127 全部为true 超出为false;
byte -128~127 为true,但是它的取值范围就是这样,所有全部为true;
Short Integer Long -128 ~ 127 全部为true,其他为false;
Float Double 全部为false,没有常量池技术,都要在堆上新建。
五、尾声
各种数据类型的常量池技术,完成了。
天天打码,天天进步!!!