java入门概念个人理解之从字符串比较到==和equals方法区别

我们先看代码

String str1 = new String("hello");
String str2 = "hello";

System.out.println("str1==str2: " + (str1==str2));	\\1
System.out.println("str1.equals(str2): " + str1.equals(str2));	\\2

输出结果:

str1==str2: false
str1.equals(str2): true

关于==和equals,我们需要知道java中的数据类型,可分为两类:

1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。

  因为string属于符合数据类型,所以应该是使用equals,假如我们使用==比较,肯定是比较它们的内存地址了,所以\\1 \\2 的结果显而易见了

  要想判断两个对象是否相等,不能通过比较两个对象的引用是否相等,这是永远都得不到相等的结果的,因为两个对象的引用永远不会相等,所以正确的比较方法是直接比较这两个对象,比较这两个对象的实质是不是一样的,即这两个对象里面的内容是不是相同的,通过比较这两个对象的属性值是否相同而决定这两个对象是否相等。

  Object类提供了一个equals()方法来比较两个对象的内容是否相同,因此我们可以采用这个方法去比较两个对象是否在逻辑上“相等”。如:c1.equals(c2);这里是调用从Object类继承下来的equals()方法,通过查阅API文档得到Object类里的equals方法的定义如下:

public boolean equals(Object obj)

注意,在重写equals方法时,需要按照以下几个规则设计:

1自反性 :对任意引用值X,x.equals(x)的返回值一定为true.
2对称性: 对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
3传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true
4一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变
5非空性:任何非空的引用值X,x.equals(null)的返回值一定为false

再看代码:

String str2 = "hello";
String str3 = "hello";
System.out.println("str3==str2: " + (str3==str2));	\\3
System.out.println("str3.equals(str2): " + str3.equals(str2));	\\4

  

输出结果:

str3==str2: true
str3.equals(str2): true

这里的又为什么都是输出true呢,因为它们都是从缓冲池取出来的,由于string类比较特殊,jdk专门做了缓存优化。

  原来Java运行时会维护一个String Pool(String池)。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。
也就是说需要看string创建的方式:

1 当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
2 Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。
3 使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。
4 使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。

  另外,String的intern()方法是一个本地方法,定义为public native String intern(); intern()方法的价值在于让开发者能将注意力集中到String池上。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

时间: 2024-10-06 00:41:22

java入门概念个人理解之从字符串比较到==和equals方法区别的相关文章

java入门概念个人理解之集合类特性对比列表

类集合框架有很多文章都列出了继承关系图,但是我没有找到更清晰的特性对比图,我这里根据使用选择条件总结对比罗列一下它们之间的一些特点.

java入门概念个人理解之访问修饰符

  类.方法.成员变量和局部变量的对应修饰符是否可以使用 修饰符 类 成员访求 构造方法 成员变量 局部变量 abstract(抽象的) √ √ - - - static (静态的) - √ - √ - public(公共的) √ √ √ √ - protected(受保护的)   √ √ √ - private(私有的) - √ √ √ - synchronized(同步的) - √ - - - native(本地的) - √ - - - transient(暂时的) - - - √ - vo

Java中字符串比较时==和equals的区别

==是比较两个字符串引用的地址是否相同,即是否指向同一个对象,而equals方法则比较字符串的内容是否相同. 例如String a = "abc"; String b = "abc"; a == b返回true,a.equals(b)同样返回true,这是为什么呢? 原来程序在运行时有一个字符串池,创建字符串时会先查找池中是否有相应的字符串,如果已经存在的话只需把引用指向它即可,如果没有则新建一个. 上例中创建a时,会在字符串池中首先创建一个"abc&qu

Java入门:基础算法之从字符串中找到重复的字符

本程序演示从一个字符串中找出重复的字符,并显示重复字符的个数. import java.util.HashMap; import java.util.Map; import java.util.Set; public class Details { public void countDupChars(String str){ //创建一个HashMap对象 Map<Character, Integer> map = new HashMap<Character, Integer>()

Java中hashcode的理解

原文链接http://blog.csdn.net/chinayuan/article/details/3345559 如何理解hashCode的作用: 以 java.lang.Object来理解,JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做 Object的比较或者取这个对象的时候,它会根据对象的hashcode再从Hash表中取这个对象.这样做的目的是提高取对象的效率.具体过程是这 样: 1.new Object(),JVM根据这个对象的H

Java入门基础学习源码,有C或C++语言基础的可以快速掌握

以下为完整源码,需要1.8版本JDK,否则部分新特性可能出现兼容问题,去掉注释号即可运行 package hello; import java.util.Scanner; public class Hello { public static void main(String[] args) { // TODO 自动生成的方法存根 /* //这是第一个程序 System.out.println("这是一个减法计算器"); Scanner in = new Scanner(System.i

理解Java中的hashCode和equals 方法

在Java里面所有的类都直接或者间接的继承了java.lang.Object类,Object类里面提供了11个方法,如下: Java代码   ```` 1,clone() 2,equals(Object obj) 3,finalize() 4,getClass() 5,hashCode() 6,notify() 7,notifyAll() 8,toString() 9,wait() 10,wait(long timeout) 11,wait(long timeout, int nanos) ``

Java入门——深入理解Java三大特性

Java入门——深入理解Java三大特性 本Blog内容: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法(getter,setter),如果不想被外界方法,我们大可不必提供方法给外界访问. 封装确实可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码. 可以对成员变量进行更精确的控制.(在setter方法中进行实际意义的校验) 总结:控制属性访问权限,不是你想改就能改.容易修改属性类型.精确控制属性的取值范围. 继承 继承是使用已存在的类

JAVA中用堆和栈的概念来理解equals() &quot;==&quot;和hashcode()

在学习java基本数据类型和复杂数据类型的时候,特别是equals()"=="和hashcode()部分时,不是很懂,也停留了很长时间,最后终于有点眉目了. 要理解equals()"=="和hashcode(),最好先了解Java内存中堆和栈的知识: 下面一段是参考自http://www.cnblogs.com/whgw/archive/2011/09/29/2194997.html 大家也可点进去查看更详细的解释. Java 中的堆和栈  Java把内存划分成两种