Java中 == 与 equals方法的异同

Java中 == 与 equals方法的异同

首先明确一点:java中的变量被分为基本数据类型和引用数据类型(Variables in Java are classified into primitive and reference variables.)

基本数据类型/变量(primitive type)包括:

浮点型:float(4 byte), double(8 byte)
整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
字符型: char(2 byte)
布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值"true"和"false")

而引用数据类型/变量(reference variables)包括:

String类,Date类和自己定义的类对象等。

其次,java的存储机制可以简单的分为两部分,一部分是栈(stack),而另一部分为堆(heap)。

其中,栈中存储所有的局部变量,包括参数还有调用方法时的栈帧;而堆存储所有的对象,包括数组以及类变量
)
(图片来源于UCB 61B)

== :

对于基本数据类型:

由于局部变量存储在栈中,且存储的就是数值,而不是对对象的引用,
所以 == 比较的就是数值本身是否相等。而由于基本数据类型并没有equals方法,所以若使用primitive type调用equals方法会报错。
比如:

	    int n=3;
        int m=3;
        System.out.println(n==m); //  结果为 true
        System.out.println(n.equals(m));  //会直接报错

对于引用类型:

== 比较的是变量所引用的对象的地址是否相等,其中变量存在栈中,而对象存储在堆中,比如:

  String str1 = new String("123");
  String str2 = new String("123");     
  System.out.println(str1==str2); //结果会为false
  str1 = str2;
  System.out.println(str1==str2); //结果会为true

对于第一个结果会为false,有如下讲解:
String str1 这句话声明了一个引用类型的变量,此时它并没有和任何对象关联。而通过new String(“123”)来产生一个对象,并将str1引用了这个对象:

str1= new String(“hello”);

那么str1指向了一个对象,此时变量str1中存储的是它指向的对象在内存中的存储地址,并不是“值”本身。

对于第二个结果为true, 因为str1 = str2 表明将str2的引用也赋给了str1,它们现在都在指向str2所引用的对象,所以他们所引用的对象地址相同,结果为true。

equals方法:

对于基本数据类型:

前面已经讲解了,基本数据类型不具有equals方法。

对于引用类型:

  1. 对于自己定义的类对象,equals方法的使用是和 == 一样的,如下代码片段:
public class Test {
        protected int number;
        protected String name;
        public Test(){}
        public Test(int number,String name){
            this.number = number;
            this.name = name;
        }
        public static void main(String[] arg){
            Test test1 = new Test(123,"name"); //初始化时对象的值不同
            Test test2 = new Test(); //初始化时对象的值不同
            test1 = test2; // 令test1和test2指向同一个对象
            System.out.println(test1.equals(test1)); //由此可判断并不是判断是否对象中值相等
            System.out.println(test1 == test2);
            Test test3 = new Test(); //初始化时值均为空
            Test test4 = new Test();//初始化时值均为空
            System.out.println(test3.equals(test4));//但指向不同对象,所以还是为false
            System.out.println(test3 == test4);

        }

}

得到的结果是true, true, false , false。
如果需要使equals方法有其它的用途,我们可以将此方法进行重写。

  1. 有的人有疑问了,像String类型使用equals方法时,比较的就是两个String变量里的内容是否相等呀,比如如下的代码,输出的结果为true。
String str1 = new String("123");
String str2 = new String("123");    
System.out.println(str1.equals(str2));

这是因为String类将equals方法进行了重写:

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

重写之后,比较的就是两个字符串内容是否相等。

补充:

4 degrees of equality:

Reference equality, just simple == equality

Shallow structural equality: two objects may be not the same, but their fields have same reference(==)

Deep structural equality: two objects may be not the same, and their fields may not have same reference, but fields are equals() (*the equals() methods are usually overridden to compare the content in fields are equal) // can call recursively

Take single list for example:

public class SList{
    private SListNode head;
    private int size;
    public SList(){
        head = null;
        size = 0;
    }
    public int getSize(){
        return this.size;
    }
    public void insertFront(String item){
        head = new SListNode(item,head);
        size++;
    }
    public boolean equals(Object other){
        if(!(other instanceof SList)){
            return false;
        }
        SList o = (SList)other;
        if(size != o.size){   // SList
            return false;
        }
        SListNode n1 = head;
        SListNode n2 = o.head;
        while(n1 != null){
            if(!n1.item.equals(n2.item)){
                return false;
            }
            n1 = n1.next;
            n2 = n2.next;
        }
        return true;
    }
    public static void main(String[] arg){
        SList s1 = new SList();
        s1.insertFront("2");
        s1.insertFront("5");
        System.out.println("size of s1: " + s1.getSize());
        SList s2 = new SList();
        s2.insertFront("2");
        s2.insertFront("5");
        System.out.println("size of s2: " + s2.getSize());
        System.out.println("if s1 equals to s2 : " + s1.equals(s2)); // true
    }
}
class SListNode {
    String item;
    SListNode next;
    public SListNode(String item,SListNode next){
        this.item = item;
        this.next = next;
    }
    public SListNode(String item){
        this(item,null);
    }
    public SListNode(){}
}

Logical equality: the same meaning of two different data structures
examples:
a) fractions 1/3 and 2/6
b) mathematical “set” objects are equals if they contain same elements(even stored in different orders)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值