zl程序教程

您现在的位置是:首页 >  Java

当前栏目

JAVA自动拆装箱、equals与==比较

2023-02-26 09:47:37 时间

一.自动拆装箱

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。

java中有8中基本的数据类型,这八种基本的数据类型都有对应的封装类型,下面是对应关系:

int——Integer float——Float double——Double byte——Byte long——Long char——Character boolean——Boolean short——Short

1.引入原因

举个例子:主要是用于java集合中,List<Inteter> list=new ArrayList<Integer>(); list集合如果要放整数的话,只能放对象,不能放基本类型,因此需要将整数自动装箱成对象,基本数据类型,如int,float,double,boolean,char,byte,不具备对象的特征,不能调用方法。

2.又是怎么实现的呢?(怎么做)

实现原理:javac编译器的语法.

自动装箱过程是通过调用valueOf方法实现(如Integer.valueOf(10)),而拆箱过程是通过调用包装器的 xxxValue方法实现(如Integer.intValue(a))。

(举个例子)

装箱:将基本类型转换成包装类对象

int i=10; Integer x=new Integer(i);手动装箱 Integer y=10;自动装箱 拆箱:将包装类对象转换成基本类型的值 Integer j=new Integer(8); int m=j.intValue();//手动拆箱 int n=j;//自动拆箱

看下面这段代码,为什么?(T为true,F为false)

public class Main {     public static void main(String[] args) {          int i = 30;         Integer a = 10;         Integer b = 20;         Integer c = 30;         Integer d = 30;         Integer e = 320;         Integer f = 320;         Long g = 30L;         Long h = 20L;         System.out.println(i==(a+b));//T         System.out.println(c==d);//T         System.out.println(e==f);//F         System.out.println(c==(a+b));//T         System.out.println(c.equals(a+b));//T         System.out.println(g==(a+b));//T         System.out.println(g.equals(c));//F         System.out.println(g.equals(a+b));//F         System.out.println(g.equals(a+h));//T,a和h自动拆箱后进行add运算的会向上转型为long类型     } }

3解释:

1) "=="运算符既可以用来比较基本类型变量和引用类型变量。当两个操作数都是包装器类型的变量时,判定标准为他们是否指向同一个对象;而如果其中有一个操作数是表达式(即包含算术运算)则会先进行自动拆箱,再进行对应基本类型变量比较。

2)基本包装类型重写了equals方法,基本包装类型的equals不会进行类型的转换,类型不同的包装类型的变量直接被判定为false,尽管他们的数值有可能是相等的。

Integer的equals源码如下:

    public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
    }

如果obj如果符合instanceof判定,那么会将obj自动拆箱,实际比较的是两个Integer对象的数值。

这就解释了虽然e和f是不同的对象(==判定为false),但是equals判定为true,因为其数值都为250。

3)针对-128~+127之间的数据,做了一个数据缓冲池 ,就直接调用IntegerCache类,返回缓存中的数据,,则不创建新的对象,否则创建

自动装箱调用valueOf方法. 

public static Integer valueOf(int i) {//Integer包装类的         if (i >= IntegerCache.low && i <= IntegerCache.high)             return IntegerCache.cache[i + (-IntegerCache.low)];         return new Integer(i);     }

4).注意点:

Integer、Short、Byte、Character、Long包装类型有缓存机制(cache数组)。

Boolean类型有TRUE 和 FALSE两个静态成员。Double和Float没有缓存机制。

(Double包装类的valueOf方法直接新建一个新对象)

(Boolean包装类valueOf方法,返回 (b ? TRUE : FALSE),)其他的请自行查看,判断.同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值,其实就是自动装箱的相反操作.

容易生成无用对象,因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加GC压力,拉低程序的性能。所以在写循环时一定要注意代码,避免引入不必要的自动装箱操作.

关于java的自动拆装箱若干细节问题https://www.cnblogs.com/qcblog/p/7670159.html

二、equals和==的比较

== 中基本数据类型比较的是值,复合数据类型比较对象的地址。

Object类中的equals方法和“==”是一样的,没有区别,而String,Double,Integer,Date,Point类等等一些类,是重写了equals方法,比较的是两个对象的内容是否相等

声明赋值语句是java中唯一不需要new 就可以产生对象的途径,即当声明一个变量后,JVM会在常量池中先查找有有没有一个值相同的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个,即以声明赋值的变量,只要值相等,任何多个引用都指向同一对象

”==”比”equal”运行速度快,因为”==”只是比较引用.

String s1 = "Monday";
String s2 = new String("Monday");

s1 == s2//false
s1 equals s2//true

-----------------------------------

String s1 = "Monday";
s2 = s2.intern();//检查字符串池里是否存在

s1 == s2//true
s1 equals s2//true