浅谈Java中==和equals()方法

==运算符

Java中测量两个变量是否相等有两种方式:第一种是利用==运算符,第二种是利用equals()方法。

  1. 基本数据类型
    使用==来判断变量是否相等,当变量是四类八种基本数据类型时,并且都是数值类型,则只要两个变量的值相同,就可返回true。
public class Test {
    public static void main(String[] args) {
        char a='A';
        int b =65;
        double c=65.0d;
        System.out.println(a==b);//end=true
        System.out.println(b==c);//end=true
        System.out.println(a==c);//end=true
    }

}

在上图代码中,char字符a的ascii码值为65,因此用==运算符来判断abc三个变量都能得到true。

  1. 引用类型

对于引用类型变量,只有当两个变量类型相同或者具有父子关系时才可使用,否则会报错。两个引用类型变量使用==运算符时,只有他们指向同一个对象时,才会返回true。

 public static void main(String[] args) {
    String a=new String("abc");
    String b=new String("abc");
        System.out.println(a==b);//end=false
}

上图程序中,变量a和变量b的值都是abc,但是a和b的引用不同,因此会返回false.

字符串常量池

对于新手而言,String有许多非常容易疑惑的地方:如"abc"和new String(“abc”)有什么不同?解决这个问题,我们需要理解Java字符串常量池机制。
字符串常量池的位置
字符串常量池位于方法区中,当创建一个字符串时,首先检测常量池中是否存在该字符串,存在则直接返回该字符串的引用,不存在则在字符串常量池中创建该字符串,并返回引用。JVM保证常量池中相同的字符串直接量只有一个,不会产生多个副本。

   String a="我爱学习";
   String b="我爱"+"学习";
   String c="学习";
   final String d="学习";
   String e="我爱"+c;
   String f="我爱"+d;
   System.out.println(a==b);//end=true,因为b在编译阶段可以确定下来,
   //因此b直接返回字符串常量池中的引用,所以相等。
   System.out.println(a==e);//变量e="我爱"+c;变量c在编译时不能确定下来,因此返回false
   System.out.println(a==f);
  /*end=true 变量d加入final修饰符,final会告诉编译器变量d这个数据不会修改,在编译时直接将变量d替换成"学习",因此编译时变量f可以确定下来为"我爱学习",直接返回字符串常量池的引用,故a==f
  */

当使用new String(“abc”)时,JVM虚拟机首先在常量池中检查是否存在"abc",不存在则创建”abc“字符串,然后调用String类的构造器在堆内存中在创建一个新的String对象,值为abc,并返回堆内存中对象的引用。简单地说,使用new String()会创建两个对象。

String a=new String("abc");
String b="abc";
System.out.println(a==b);//end=false

上图中,声明a变量时,JVM首先在字符串常量池中创建"abc"对象,又在堆内存中创建"abc"对象,然后将堆内存中对象的引用返回给a。声明b变量时,JVM在字符串常量池中发现"abc",直接将常量池中对象的引用返回给b。变量a和变量b的内容相同,但一个是常量池的引用,一个是堆内存的引用。因此a==b的结果为false

equals()方法

equals()方法是Object类提供的一个实例方法,用于判断两个引用类型变量是否相等,点开Object类的源码可发现,这个方法判断两个对象是否相等和==运算符没有区别,因此Object类的这个方法意义不大,我们在实际开发中往往会重写这个方法。

//Object类源码
public boolean equals(Object obj) {
        return (this == obj);
    }

String类重写了equals()方法,只要两个字符串的序列相同,就可返回true。因此下列代码中运行结果全为true。

   String a="我爱学习";
   String b="我爱"+"学习";
   String c="学习";
   final String d="学习";
   String e="我爱"+c;
   String f="我爱"+d;
   System.out.println(a.equals(b));//end=true
   System.out.println(a.equals(e));//end=true
   System.out.println(a.equals(f));//end=true

实际开发中,我们通常需要重写equals方法。重写方法时,相等的条件是由业务要求决定的,因此equals()方法的实现也是由业务要求决定的。
通常而言,重写quals()方应该满足下列条件:

  • 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
  • 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
  • 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
  • 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
  • 对于任何非空引用值 x,x.equals(null) 都应返回 false。
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值