java基础数据类型有:byte,char,short,int,long,float,double,boolean。
其对应的包装类型有:Byte,Character,Short,Integer,Long,Float,Double,Boolean。
自动装箱:基本类型转换为包装类型。
自动装箱的作用:可以将基本数据类型按照对象来使用,以调用其方法。
自动拆箱:包装类型转换为基本类型。
自动拆箱的作用:可以使对象变成基本数据类型进行加减乘除。
举例:
//在jdk1.5之前定义一个Integer对象:
Integer a=new Integer(10);
//从jdk1.5开始定义一个Integer对象,即自动装箱;
Integer b=10;
//自动拆箱;
int c=b;
享元模式:在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象,而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象(Byte、Short、Integer、Long适用,Float、Double不适用)。
如源码所示:
/**
* Returns a Integer instance representing the specified
* int value.
* If a new Integer instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Integer(int)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param i an int
value.
* @return a Integer instance representing i.
* @since 1.5
*/
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
int a=1;
Integer b=1;
Integer b1=1;
Integer c=2;
Integer e=300;
Integer f=300;
Long g=3L;
Long h=2L;
Integer i = new Integer(1);
Integer j = new Integer(1);
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.print(i == j); //false
2)非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)//Integer和New Integer()比较值:
Integer a=300;
Integer b = new Integer(300);
System.out.print(a == b); //false
3)对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。 //Integer和Integer的值在区间-128到127之间比较值:
Integer a=1;
Integer b=1;
Integer c=2;
Integer d=3;
System.out.print(a == b); //true
System.out.print(d == (b+c)); //true
System.out.print(d.equals(b+c)); //bcd全部是是Integer,所以b+c的结果是Integer对象,自然返回Ture;
//nteger和Integer的值不在区间-128到127之间比较值:
Integer e=300;
Integer f=300;
System.out.print(e == f); //false
3) int和Integer的比较:Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
int a=1;
Integer b=1;
Integer c = new Integer(1);
//int和Integer比较值:
System.out.print(a == b); //true
//int和New Integer()比较值:
System.out.print(a ==c); //true
//
这是Integer和Long的equals方法的源码:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
下面来看例子:
Integer a = 1;
Integer b = 2;
Long c = 3L;
Long d = 2L;
// “==”比较的并不是内容,而是其内存地址,即引用对象是否是同一个;a,b均来源与缓存区,自然地址一样(不是数字一样);
System.out.print(c == (a+b)); //true
//计算a+b的结果是Integer,所以为直接返回False
System.out.print(c.equals(a+b)); //false
//计算a+d的过程中发生了类型提升,结果为Long,所以就调用了longValue(),自然为True;
System.out.print(c.equals(a+d)); //true
String str = "sl";
//代替下面的声明方式
String str = new String("sl");
问题String s = new String(“hello”) 和String s = “hello”; 的区别?
String的值都在方法区的常量池中,前者要在堆中创建s对象和常量池中创建hello对象。后者只需要在常量池中创建hello对象;前者会创建2个对象,后者创建1个对象。
看一下程序的结果:
public class St {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = "hello";
String s5 = new String("world");
System.out.println(s3 == s1 + s2);// false 地址不一样
System.out.println(s3.equals((s1 + s2)));// true 值相等
System.out.println(s3 == "hello" + "world");// true 常量池中有
System.out.println(s3.equals("hello" + "world"));// true 值相等
System.out.println(s4 ==s1);// true 常量池中有
System.out.println(s5 == s2);//false 地址不一样
}
字符串如果是变量相加,先开辟空间,再拼接。字符串如果是常量相加,是先拼接,然后再常量池找,如果有就直接返回,否则,就创建。
参考:
https://blog.csdn.net/wangxundeng/article/details/52091378
https://blog.csdn.net/qq_39949109/article/details/80207492