从Java的equals和==初识面向对象

来源:互联网 发布:don t starve for mac 编辑:程序博客网 时间:2024/06/05 18:36

Java算是我第一门认真学的对象语言,之前学过C和MATLAB,C++和Python也有过一定接触,所以对Java的学习基本能接受。但是在equals和==上Java出现了一个明显不同于过程语言的特性。


举个例子

下面有一段代码

public class Test {    public static void main(String args[]) {        Integer n1 = new Integer(2);        Integer n2 = new Integer(2);        System.out.println(n1.equals(n2));        System.out.println(n1==n2);    }}

凭直感我们认为结果都会是true,然而并不是!前一个结果为ture而后一个为false。

这一个问题的关键在于:
Java 中一切都是对象,但操作的标识符实际是对象的一个引用。
==和!=适用于所有对象,但它们是比较对象的引用是否相同。

我们初始一个对象

    String s;

创建的是引用,不是对象。创建引用后,一种安全的做法是对其进行初始化。

初始化可以直接赋值,也可以使用new操作符。

String s = "abc";String s =  new String("abc");

这里new操作符的作用是创建一个新对象,并将对象与引用结合起来。

也就是说,对于上面那个例子,如果使用==,实际上比较的是两个引用,尽管它们看起来是内容相同,但是比较的两个引用是不相等的。而equals(),它不适用于基本类型,它比较出来的结果是相等的。

这里还有一点,就是对于equals的使用,如果这个函数出现在C或者MATLAB或者Python里,十有八九这个的调用方式是equals(a, b),返回一个比较的结果。
而在Java里这个方法的调用方式为a.equals(b),也侧面表明了Java中一切皆对象,在这里equals是作为a这个对象的方法而存在,而使用的。
所以尽管Java并不算完全的面向对象语言,但在这个例子里Java已经明显不同于面向过程的语言了。


更近一步[1]

Java神书《Java编程思想》一书中的原话:

“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”。

要理解这句话,先看一个例子:

public class test {    public static void main(String[] args) {        Integer n1 = new Integer(2);        Integer n2 = new Integer(2);        System.out.println(n1==n2);            int n3=3;        int n4=3;        System.out.println(n3==n4);        String str = new String("hello");        String str1 = new String("hello");        String str2 = new String("hello");        System.out.println(str1==str2);        str1 = str;        str2 = str;        System.out.println(str1==str2);    }}

这个结果是 false, true, false, true。

怎么样,晕了没有?

实际上也好理解,对于第一个,我们创建的同一对象的两个引用,结果当然不等;第二个我们创建的是两个变量,两个变量当然相等;第三个我们创建的也是两个引用,所以不等。

那第四个呢?

这里先说说理解Java基本数据类型变量和非基本数据类型变量的区别:

Java的8种基本数据类型:

  浮点型: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”)

  对于这8种基本数据类型的变量,变量直接存储的是“值”,要注意浮点型和整型都是有符号类型的,而char是无符号类型的(char类型取值范围为0~2^16-1)。
  
而非基本数据类型的变量,也就是我们称为“引用类型的变量”。

所以当我们进行比较时,基础数据类型变量比较的是值,而非基本数据类型比较的是引用。换句话说,基础数据类型比较的是存储的值,而非基本数据类型比较的是存储的位置,所以第三个==是false而第四个==是ture,因为两个都指向了str存储的“hello”,结果当然是ture了。

而对于equals方法,它作为Object基类的方法,首先equals方法不能作用于基本数据类型的变量;其次如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址,而String、Date等类对equals方法进行了重写,比较的是所指向的对象的内容

以上进一步的内容包括equals的源码海子先生在浅谈Java中的equals和==里有更详细的描述,有兴趣的不妨去读一读。


以上就是从Java的equals和==对Java面向对象的一个初次体验,管中窥豹,得一隅而望天下,Java的路还很漫长啊。


引用:
[1]海子,浅谈Java中的equals和==