java--equals和==方法

Java程序中测试两个变量是否相等有两种方式:一种是利用==运算符,另一种是利用equals()方法。当使用==来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),则只要两个变量的值相等,就将返回true。

但对于两个引用类型变量的时候,只有它们指向同一个对象时,==判断才会返回true。==不可用于比较类型上没有父子关系的两个对象。下面程序示范了使用==来判断两种类型变量是否相等的结果。

public class EqualTest {

    public static void main(String[] args) {

        int it=65;
        float f1=65.0f;
        System.out.println("65和65.0f是否相等?"+(it==f1));

        char ch='A';
        System.out.println("65和A是否相等?"+(it==ch));

        String str1=new String("hello");
        String str2=new String("hello");
        System.out.println("str1和str2是否相等?"+(str1==str2));
        System.out.println("str1是否equals str2:"+(str1.equals(str2)));

    }

}

运行结果如下:

6565.0f是否相等?true
65和A是否相等?true
str1和str2是否相等?false
str1是否equals str2:true

运行上面程序,可以看到65、65.0f和‘A’相等。但对于str1和str2,因为他们都是引用类型变量,他们分别指向两个通过new关键字创建的String对象,因此str1和str2两个变量不相等。

String还有一个非常容易迷惑的地方:“hello”直接量和new String(“hello”)有什么区别呢?当Java程序直接使用形如“hello”的字符串直接量(包括可以在编译时就计算出来的字符串值)时,JVM将会使用常量池来管理这些字符串;当时用new String(“hello”)时,JVM会先使用常量池来管理”hello”直接量,在调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中。换句话说,new String(“hello”)一共产生了两个字符串对象。

注意:
常量池(constant pool)专门用于管理在编译时被确定并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口中的常量,还包括字符串常量。

下面程序示范了JVM使用常量池管理字符串直接量的情形。

public class StringCompareTest {

    public static void main(String[] args) {

        //s1直接引用常量池中的"疯狂Java"
        String s1="疯狂Java";
        String s2="疯狂";
        String s3="Java";

        //s4后面的字符串值可以在编译时就确定下来
        //s4直接引用常量池中的"疯狂Java"
        String s4="疯狂"+"Java";

        //s5后面的字符串值可以在编译时就确定下来
        //s5直接引用常量池中的"疯狂Java"
        String s5="疯"+"狂"+"Java";

        //s6后面的字符串值不能在编译时就确定下来
        //s6不能引用常量池中的"疯狂Java"
        String s6=s2+s3;

        //使用new调用构造器将会创建一个新的String对象
        //s7引用堆内存中新创建的String对象
        String s7=new String("疯狂Java");

        System.out.println("s1==s4的结果为:"+(s1==s4));
        System.out.println("s1==s5的结果为:"+(s1==s5));
        System.out.println("s1==s6的结果为:"+(s1==s6));
        System.out.println("s1==s7的结果为:"+(s1==s7));
    }

}

代码运行结果如下:
s1==s4的结果为:true
s1==s5的结果为:true
s1==s6的结果为:false
s1==s7的结果为:false

JVM常量池保证相同的字符串直接量只有一个,不会产生多个副本。例子中的s1、s4、s5所引用的字符串可以在编译期就确定下来,因此它们都将引用常量池中的同一个字符串对象。

使用new String()创建的字符串对象是运行时创建出来的,它被保存在运行时内存区(即堆内存)内,不会放入常量池中。

但在很多时候,程序判断两个引用变量是否相等时,也希望有一种类似于”值相等”的判断规则,并不严格要求两个引用变量指向同一个对象。例如对于两个字符串变量,可能只是要求它们引用字符串对象里包含的字符序列相同即可认为相等。此时就可以利用String对象的equals()方法来进行判断,例如上面程序中的str1.equals(str2)将返回true。

equals方法是Object类提供的一个实例方法,因此所有变量都可调用该方法来判断是否与其他引用变量相等。但使用这个方法判断两个对象相等的标准与使用==运算符没有区别,同样要求两个引用变量指向同一个对象才会返回true。因此这个Object类提供的equals()方法没有太大的实际意义,如果希望采用自定义的相等标准,则可采用重写equals()方法来实现。

注意:
String已经重写了Object的equals()方法,String的equals()方法判断两个字符串相等的标准是:只要两个字符串所包含的字符序列相同,通过equals()方法比较将返回true,否则将返回false。

猜你喜欢

转载自blog.csdn.net/wilson_m/article/details/79703358