常量池的分类:
- Class类中有一个常量池保存字面量(就是一些字符串和被final修饰的变量)和符号引入(类名、方法名、变量名)
- 运行时常量池,在类被加载到内存之后,将Class中常量池转变为运行时常量池,存在于方法区
- 字符串常量池,顾名思义就是保存字符串的常量池,jdk1.7之后放在堆中。
总结:也就是说Class类中常量池一部分变为运行时常量池,一部分变为字符串常量池
问题引入
字符串
// 会创建两个对象,因为“123”在类加载之后会被放到字符串常量池,也就是new对象之前就已经存在啦。
//而new 会在堆中开辟一个内存保存:"123",所以说会创建两个对象
String s1=new String("123");
// 因为“123”已经存在字符串常量池,所以只生成一个对象。如果字符串常量池没有,则会在
//字符串常量池生成一个,并返回。
String s2="123";
//intern函数在不同jdk版本不同,在jdk1.6及之前,先看常量池有没有,有则返回,没有就创建。
// jdk1.7及之后,有就返回,没有则在堆中创建一个对象,并把该引用,存入到字符串常量池中。
String s3=s1.intern();
//首先字符串常量池中,已经存在"123",会调用StringBuilder中的append方法,在堆中生成一个新对象。
String s4=new String("123")+new String("123");
封装类型
// 共8中封装类型
Character Byte Short Integer Float Long Double Boolean
//其中Float Double没有常量池,所以==比较的是地址,如果用equals则比较的是数值,但如果比较的不是同类型,则也是false,
//例
Float b=1f;
Float a=1f;
Integer d=1;
Double c=1d;
System.out.println(a.equals(d));//false
System.out.println(d.equals(c)); //false
System.out.println(a.equals(b)); //true
// 剩下的5种有常量池,
// 说明,equals 只会比较数值大小,== 两侧如果有算数运算符也比较数值大小
Integer d=256;
Integer f=256;
System.out.println(f.equals(d)); //true
System.out.println(f==d); //false 因为常量池的大小是-127至128
Integer d=1;
Integer f=1;
System.out.println(f.equals(d)); //true
System.out.println(f==d); //true
```java
// Long类型首先比较是不是 Long,不是直接false
Long e=1l;
System.out.println(e.equals(d));//false