常量池是以表的形式存在
constant_unit:UNF-8编码的字符串
constant_Interger:int类型的字面值
constant_float:float类型的字面值
constant_Long:long类型的字面值
constant_double:double类型的字面值
constant_Class:对一个类或接口的符号引用
constant_String:String类型的字面值
constant_Fieldref:对一个字段的符号引用
constant_Methodref:对一个类中方法的符号引用
constant_InterfaceMethodref:对接口中的方法的符号引用
constant_NameAndType:对一个字段或方法的部分符号引用
1
、知识普及
(1)方法 区中存储了类变量、类信息、方法信息、常量池(符号引用,以表的形式存在)。
(2)java中==是用来比较地址(除了基本数据类型)
(3)equals默认与“等于等于”是一样的一样,默认比较地址
(4)在java的中,所有对象的超类都是Object
2
、代码解析
(1)
public void demo{
public static void main(String[] args){
Interger num1 = 129;
Interger num2 = 129;
System.ou.print(num1==num2);
}
}
问题1
:这里会输出什么
答案
:输出:true
问题2
:将两个变量的赋值都改为128后运行,会输出什么?
答案
:输出false
这是为什么
?
想自己看具体细节可以看源码IntegerCache
类,
这里我贴一小部分且讲自己的理解
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
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() {}
}
通过类名称可以知道,这是Interger缓存池,而通过注释也可以知道默认的值大小是从-128到127,从源码也可以看到,定义的几个static静态代码块,静态代码块在加载器准备阶段就会运行,所以其实129这里也就是会开启一块新的内存空间,地址也就与原本的不同了。
(2)
public void demo{
public static void main(String[] args){
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
System.out.print(str1==str2);
System.out.print(str1==str3);
System.out.print(str1==str3.intern());
//想一下这三个输出什么
}
}
问题1
:为什么str1与str2输出是true?
问题2
:为什么str1与str3输出是false?
问题3
:str1与str3.intern()这一行输出时什么?
a.首先在加载器加载的时候会将字节码文件,也就是会将“abc”
加载为对应的编码,所以是指向了常量表中的constant_unit
表对应的编码,所以这str1==str2输出为true。
b.new一个对象,在jvm扫描到new的时候,会在堆中开辟一片空间,然后将str3指向这个空间的地址,所以str3的地址是堆中的地址,堆中的地址会指向常量表constant_String,再指向constant_unit。
c.加上intern()方法,输出会输出常量表的地址,当str3指向的字符串是第一次创建的时候,需要将字符的字面值放到常量表,然后再将常量表中的地址返回。