java常识1:弄清楚equals()和“==”

本文深入探讨了Java中==与equals操作符的区别,尤其是在处理基本数据类型和引用类型时的行为差异。通过具体示例,解释了浮点型数据比较的特殊处理方式,以及String类型在比较时利用缓存机制的原理。

一、传统认知

运算

基本数据类型比较的对象

引用数据类型比较的对象

==

堆内存空间

equals

默认堆内存空间,覆写的方法除外

二、通过程序找问题

import com.leon.java.reflect.Person;

class Dog{
    private String name ;
    Dog(){}
    Dog(String name){
        this.name = name;
    }
}

public class EqualsDemo<T> {

     void test(T t1,T t2){
        System.out.println("t1是否==t2:" + (t1 == t2));
        System.out.println("t1是否equals t2:" + (t1.equals(t2)));
    }

    public static void main(String[] args) {

        // == 比较 基本类型
        System.out.println("\n--------比较基本类型-------");

        System.out.println("\n1.比较Byte");
        new EqualsDemo<Byte>().test((byte)123,(byte)123);

        System.out.println("\n2.比较Short");
        new EqualsDemo<Short>().test((short)123,(short)123);

        System.out.println("\n3.比较Integer");
        new EqualsDemo<Integer>().test(1,1);

        System.out.println("\n4.比较Long");
        new EqualsDemo<Long>().test(123L,123L);

        System.out.println("\n5.比较Float");
        new EqualsDemo<Float>().test(1.4f,1.4f);

        System.out.println("\n6.比较Double");
        new EqualsDemo<Double>().test(1.433333,1.433333);

        System.out.println("\n7.比较char");
        new EqualsDemo<Character>().test('a','a');

        System.out.println("\n8.比较Boolean");
        new EqualsDemo<Boolean>().test(true,true);

        //发现的问题1:浮点型两个“相同的数” == 比较结果不同。解决方法:浮点型数据比较是否相等时,转化成包装类型,使用equals进行比较。

        //比较引用类型
        System.out.println("\n--------比较引用类型-------");

        Dog d1 = new Dog("旺旺");
        Dog d2 = new Dog("旺旺");
        System.out.println("\n比较自定义的Dog类");
        new EqualsDemo<Dog>().test(d1,d2);

        System.out.println("\n比较String");
        new EqualsDemo<String>().test("aaa","aaa");

        //发现问题:String是引用类型,==比较引用类型时,比较的应该是地址才对。为什么在这里两个String对象的比较结果是true。
    }
}

JDK1.8下输出结果为:

--------比较基本类型-------

1.比较Byte
t1是否==t2:true
t1是否equals t2:true

2.比较Short
t1是否==t2:true
t1是否equals t2:true

3.比较Integer
t1是否==t2:true
t1是否equals t2:true

4.比较Long
t1是否==t2:true
t1是否equals t2:true

5.比较Float
t1是否==t2:false
t1是否equals t2:true

6.比较Double
t1是否==t2:false
t1是否equals t2:true

7.比较char
t1是否==t2:true
t1是否equals t2:true

8.比较Boolean
t1是否==t2:true
t1是否equals t2:true

--------比较引用类型-------

比较自定义的Dog类
t1是否==t2:false
t1是否equals t2:false

比较String
t1是否==t2:true
t1是否equals t2:true

这里我们不难发现两个问题:

       问题1:浮点型两个“相同的数” == 比较结果为什么不同?

       问题2:String是引用类型,==比较引用类型时,比较的应该是地址才对。为什么在这里两个String对象的比较结果是true?

三、解决问题

       1.浮点型数据判断是否相等

答:这个问题的由来比较古老,是浮点型这种数据类型的设计导致了这种情况。当然,JDK的开发人员也知道这个问题,于是他们提供了这样的解决方法:

意思是:只要参数传入的对象是Double类型,且当前对象和传入对象的“doubleToLongBits()”相同即认定为两者相等。

我们来看doubleToLongBits(double value)方法。

第一行就调用了另一个方法:

doubleToRawLongBits();

        java.lang.Double.doubleToRawLongBits() 方法返回根据IEEE754浮点“双精度格式”位布局,不是非数字(NaN)值,返回指定浮点值的表示。它包括以下要点:

  •    如果参数为正无穷大,其结果是 0x7ff0000000000000L.
  •    如果参数为负无穷大,其结果是 0xfff0000000000000L.
  •    如果参数为NaN,那么结果是长整型表示实际NaN值。doubleToLongBits方法不同,doubleToRawLongBits不垮所有的位模式NaN编码为一个单一的“规范”NaN值。

简单理解:

上面的内容有点多不想看,可以简单理解为:Double的equals()方法是通过将double型转换成long型变量,来进行数值比较的。

 

2.String是引用类型,==比较引用类型时,比较的应该是堆内存才对。为什么在这里两个String对象的比较结果是true?

答:java代码实际的执行引擎是jvm,jvm为String型变量提供了缓存机制,只要内容相同的String实例,不会重新创建对象,而是重用已经存在的对象。

<think>好的,我现在需要解释“等于等于”“eq”的区别。首先,我得弄清楚这两个术语在编程中的具体含义应用场景。用户可能是在不同的上下文中遇到这些概念,比如不同的编程语言或者不同的比较方法。 首先,“等于等于”通常指的是“==”操作符。这在很多编程语言中都是用来比较两个变量的值是否相等。例如在Java、Python、JavaScript中,使用“==”来比较基本数据类型的值是否相同。不过需要注意的是,对于引用类型,“==”通常比较的是对象的内存地址,而不是实际内容。这时候可能需要使用像“equals()”这样的方法来进行内容比较。比如在Java中,String类型的变量如果使用“==比较,实际上比较的是它们是否是同一个对象,而不是字符串内容是否相同。因此,这里可能存在一些陷阱,用户需要特别注意。 接下来是“eq”。这个术语在不同语言中可能有不同的含义。例如,在Java中并没有直接的内置“eq”操作符,但可能在某些框架或库中作为方法名出现,比如字符串比较equals()方法,有时可能简写为“eq”。但在其他语言比如Lisp或某些脚本语言中,“eq”可能是一个直接的比较操作符,用于比较两个变量是否相同,可能是值比较或者引用比较,具体取决于语言的设计。例如,在Lisp中,eq比较的是对象的身份(即是否同一个对象),而equal比较的是值是否相等。这时候需要具体语言具体分析。 用户可能在使用不同的编程语言时混淆了这两个概念,或者在某个特定框架中遇到了这两种比较方式。比如在Java中,比较字符串内容是否相等应该使用equals()方法,而不是“==”,而“eq”可能出现在某些测试框架或工具中,比如JUnit中的断言方法可能使用类似“assertEquals(expected, actual)”这样的形式,但这里的“eq”并不是直接的操作符,而是方法名的一部分。 另外,可能需要考虑的是,某些语言或环境中的语法差异。比如在Shell脚本中,“==“eq”可能用于不同的条件判断结构中,比如在Bash中使用“==”进行字符串比较,而“-eq”用于数值比较。这时候用户可能因为语法环境的不同而产生困惑。 总结起来,用户需要明确当前使用的编程语言或环境,以及具体的上下文,才能正确理解使用“等于等于”“eq”进行比较操作。需要指出的是,不同语言中的比较操作符可能有不同的行为,特别是在处理基本类型引用类型时的差异,以及值比较引用比较的区别。此外,还需要注意自动类型转换的问题,比如在JavaScript中,“==”会进行类型转换再比较,而“===”不会,这也可能引起误解。 在解释的时候,应该分点说明,先介绍“==”操作符的常见用法注意事项,然后介绍“eq”在不同语言中的不同表现,再举例说明它们之间的区别,最后给出使用建议。同时,要提醒用户注意不同语言的具体语法比较规则,避免混淆错误。</think>--- ### **等于等于(==)与 eq 的区别解析** 在编程中,“等于等于”(即 `==` 操作符) `eq` 是两种常见的比较方式,但它们的含义行为因语言场景不同而存在显著差异。 --- #### **一、等于等于(==)** - **基本定义** `==` 是多数编程语言(如 Java、Python、JavaScript)中的**值比较操作符**,用于判断两个变量的**值是否相等**。 - **具体行为** - **基本数据类型**(如 `int`、`double`):直接比较值是否相等。 ```java int a = 5; int b = 5; System.out.println(a == b); // true ``` - **引用类型**(如对象、字符串):比较内存地址(即是否为同一对象)。 ```java String s1 = new String("hello"); String s2 = new String("hello"); System.out.println(s1 == s2); // false(地址不同) ``` - **JavaScript 的特殊性**: `==` 会进行隐式类型转换后比较值(如 `5 == "5"` 为 `true`),而 `===` 严格比较类型(`5 === "5"` 为 `false`)。 - **注意事项** 对引用类型,若需比较内容是否相同,需使用特定方法(如 Java 的 `equals()`、Python 的 `==` 重载)。 --- #### **二、eq** - **常见场景** `eq` 是某些语言或框架中用于比较的关键字,但具体行为因环境而异: 1. **Lisp 语言** - `eq` 比较对象的**内存地址**(身份是否相同)。 - `equal` 比较对象的**内容**是否相同。 ```lisp (eq 'a 'a) ; => t(相同符号) (eq (list 1) (list 1)) ; => nil(不同对象) ``` 2. **Shell 脚本** - `-eq` 用于数值比较,`==` 用于字符串比较。 ```bash if [ "$a" -eq 5 ]; then # 数值比较 if [ "$str" == "hello" ]; then # 字符串比较 ``` 3. **Java 框架(如 JUnit)** - `assertEquals(expected, actual)` 方法用于内容比较(缩写可能与 `eq` 相关,但非语法关键字)。 4. **其他场景** - 部分模板引擎(如 Thymeleaf)用 `eq` 表示等于逻辑: ```html <div th:if="${status eq 'active'}">...</div> ``` --- #### **三、核心区别** | **比较方式** | **适用场景** | **比较逻辑** | **示例语言/环境** | |--------------|-----------------------------|----------------------------------|-------------------------| | `==` | 值比较(基本类型或重载后对象) | 值相等或引用地址相等 | Java、Python、JavaScript | | `eq` | 身份/内容比较(依语言而定) | 可能比较地址或内容(需具体分析) | Lisp、Shell、模板引擎 | --- #### **四、使用建议** 1. **明确语言规则** - 在 Java 中,字符串内容比较必须用 `equals()`,而非 `==`。 - 在 JavaScript 中,优先使用 `===` 避免隐式类型转换。 2. **注意引用类型陷阱** ```java Integer x = 127; Integer y = 127; System.out.println(x == y); // true(缓存范围内) Integer m = 128; Integer n = 128; System.out.println(m == n); // false(超出缓存范围,地址不同) ``` 3. **框架/库的特殊语法** 如 Thymeleaf 的 `eq` 是逻辑运算符,需按文档使用。 --- **总结**: - `==` 是通用值比较操作符,但需注意类型语言差异。 - `eq` 的行为高度依赖具体语言或框架,可能是地址比较、内容比较或逻辑运算符。 - 始终查阅当前环境的文档以避免误用!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值