java 不同类 equals枚举类比较是用==还是equals

=======================原理速记===================================
equals重载后比较内容,==比较指针。否则equls等同于== (Java里源码如此)
所有的&==&都是基于指针级的,也就是说只有它们指向的是同一个对象才被认为是相等.而对于对象值的相等判断则需要重写并使用.equal()方法在多数常用类,譬如String中,.equal()已经被默认重写为是值相等的了
两个对象用==号比较,比较的就是 两个对象的引用。而equals方法比较的是内容。比较String就覆盖了equals方法(自己重定义逻辑相等)
因为内容相等,所以始终输出equals的效果,而==却不一定,例子:/zhxhdean/archive//1995431.html
================================equals哲学============================
1. 何时需要重写equals()当一个类有自己特有的&逻辑相等&概念(不同于对象身份的概念)。
2. 设计equals()[1]使用instanceof操作符检查&实参是否为正确的类型&。[2]对于类中的每一个&关键域&,检查实参中的域与当前对象中对应的域值。[2.1]对于非float和double类型的原语类型域,使用==比较;[2.2]对于对象引用域,递归调用equals方法;[2.3]对于float域,使用Float.floatToIntBits(afloat)转换为int,再使用==比较;[2.4]对于double域,使用Double.doubleToLongBits(adouble) 转换为int,再使用==比较;[2.5]对于数组域,调用Arrays.equals方法。
3.&当改写equals()的时候,总是要改写hashCode()根据一个类的equals方法(改写后),两个截然不同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode方法,它们仅仅是两个对象。因此,违反了&相等的对象必须具有相等的散列码&。
4.&hashCode最大的用处是什么呢?&
Java中的集合(Collection)有两类,一类是List,再有一类是Set。 前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。 那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。Java采用了哈希表的原理, 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上. 初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。 有了hashCode,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。 所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
5. 为什么在Hibernate里要重写hashCode和equals这两个方法? 在hibernate中,经常使用set集合来保存相关对象,而set集合是不允许重复的, so, 道理同上。
===========================一道写HashCode的题===========================
一道java hashCode()的面试题 最近面试老是被问到这个问题。。。
public class ValuePair {
public int a = 4,
public boolean equals(Object other) {
ValuePair o = (ValuePair)
return ((a == o.a) && (b == o.b)) || ((a == o.b) && (b == o.a));
} catch (ClassCastException cce) {
return false;
public int hashCode() {
// 请选择下边的答案(多选)
A。return 0;B.C. return a+b;D. return a-b;E. return a^b;F. return (a&&16)|b;请说明理由。
------------------------------------第一种解答----------------------------------------------------------------------hashCode 的常规协定是: 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
然后再看重写的equals方法。。(a==o.a;;b==o.b) || (a==o.b;;b==o.a);
说明交换a,b的值不会对结果产生影响,也要生成相同的hashcode值。
所以选ACE。。。(Cliff评注:A还是不能选)
------------------------------------第二种解答----------------------------------------------------------------------
根据一般约定:如果2个对象 equals 比较为true,那么hashCode也最好(不是必须)相同。(Cliff:我也比较同意,这是最好,但不是必须)如果2个对象 equals 比如为false,那么hashCode也最好(不是必须)不同。
因此对于这个题目,如果从纯语法层面考虑,全部都是可选的但是从程序运行效率来看,最好是该hashCode里,a,b值可以互换,而又尽可能做到不同的a,b值返回不同的值。因为C,E最好.
A. return 0; 效率太低B. 不满足a,b的互换性D. return a-b; 不满足a,b的互换性F. return (a&&16)|b; 不满足a,b的互换性
另外,比如 a * b 也满足互换性,但是效率稍低,毕竟没加法和位运算快
* Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
* If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
* It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
===========================另一个例子,用来熟悉语法===========================
import java.util.HashS
import java.util.I
import java.util.S
public class SetTest {
public static void main(String[] args) {
// Set&String& set = new HashSet&String&();
// set.add("abc"); //将对象的地址增加到集合中了
// set.add("xyz");
// set.add("abc");
// for(Iterator&String& iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
Set&People& set = new HashSet&People&();
set.add(new People("zhangfei"));
set.add(new People("guanyu"));
for (Iterator&People& iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next().getName());
// Object object = new Object();
// System.out.println(Integer.toHexString(object.hashCode()));
class People {
public People(String name) {
this.name =
public String getName() {
public boolean equals(Object object) {
if (this == object) { // 第一步
return true;
if (object instanceof People) { // 第二步
People people = (People)
if (name.equals(people.getName())) { // 第三步,这里很巧妙的使用了String的比较,属于递归调用
return true;
return false;
public int hashCode() {
return name.hashCode();
三、小结1,如果要用自己的类作为HashMap的key,必须同时覆盖hashCode和equals方法。2,重写hashCode方法的关键:(1)对同一个对象调用hashCode()都应该生成同样的值。(2)hashCode()方法不要依赖于对象中易变的数据,当数据发生变化时,hashCode()就会生成一个不同的散列码,即产生了一个不同的label。(3)hashCode()不应依赖于具有唯一性的对象信息,例如对象地址。(4)散列码应该更关心速度,而不是唯一性,因为散列码不必是唯一的。(5)好的hashCode()应该产生分步均匀的散列码。参考:http://blog.csdn.net/lazy_tiger/article/details/1816946
Views(...) Comments()Java中的数据比较(再谈==与equals的区别)
Java中的变量与对象有区别吗?
引子:变量与对象
变量是Java中最基本的存储单元,为变量赋值可以使用赋值表达式。如:
int&i&=&10;&&
该表达式的含义是将一个字面量(literal)10赋值给一个类型为int型的变量,变量名为i。这是一个为基本数据类型的变量赋值的例子,它表达了一个非常朴素的信息,那就是变量i的值为10。
那么这种赋值表达式引申到引用类型的变量时,其含义又有什么变化呢?再看一个赋值表达式:
String&str&=&null;&&
该表达式的含义是将空内存地址(null)赋值给String类型的变量,变量名为str。朴素的说法是变量str的值为null。对于引用类型的变量而言,赋值操作只是将对象的内存地址保存到变量中。也就是说引用类型的变量值是对象的内存地址而不是对象的内容。如下例:
String&str1&=&"abc";&&
String&str2&=&new&String("abc");&&
上述两种赋值操作本质上没有任何区别,最大的区别是生成对象的方法不同(这一点与赋值操作无关)。对于变量而言,其值仍然是所指对象的内存地址。
相对于变量,对象也是存储单元的一种。对象有自己的属性与方法,其内容的表现形式由实例化该对象所用的类决定。如:
new&java.sql.Time(0L);&&
要使用对象,必须将对象的内存地址指定到一个引用类型的变量中(也就是变量的赋值操作)。该变量的类型可以与对象的类型一致,也可以是对象类型的父类,或者是对象类型实现的接口。后两种是典型的多态应用。如:
java.util.Date&date&=&new&java.sql.Time(0L);&&
当然,我们只能通过变量去调用对象的方法或者设置对象的属性,其作用无非是取得或者修改对象的内容。如:
java.util.Date&date&=&new&java.sql.Time(0L);&&
date.setTime(3600000L);&&
System.out.println(date.toString());&&
注意,变量的内涵只有一个,就是它的值。我们通过变量调用对象的方法时,可以改变的也只是对象的内容。区分变量与对象是很有必要的,当我们讨论变量时总是与它们的值有关;当我们讨论对象时更多的是在讨论如何取得或修改它们的内容。记住:
变量的值只能通过赋值表达式来改变;对象的内容只能通过自身的方法或属性来改变。
变量值的比较
当我们讨论变量之间是否相等时,通常使用“==”关系运算符。如:
int&i&=&10;&&
int&j&=&20;&&
if&(i&==&j)&{&&
&&&&System.out.println("两个变量的值相等");&&
上例是基本数据类型之间的比较,本质上是变量之间值的比较。对于两个引用变量的比较,如:
String&str1&=&"abc";&&
String&str2&=&new&String("abc");&&
if&(str1&==&str2)&{&&
&&&&//&判断无法成立,因为两个变量所指对象的内存地址不同。&&
&&&&System.out.println("两个变量的值相等");&&
本质上引用类型的变量之间的比较也是值的比较,也就是内存地址的比较。上例不会打印出“两个变量的值相等”,因为两个变量指向了不同内存地址的对象。
对象内容的比较
对于引用变量而言,如果我们不想仅限于对内存地址的比较,而是想做更深层次的(比如对象的内容)比较。如何实现呢?Java的Object类提供了equals方法,此方法实现了对象之间内容上的比较。由于Object类是所有Java类的父类,所以我们只要在自己的类中改写equals方法,就可实现该类对象之间的内容比较。如:
String&str1&=&"abc";&&
String&str2&=&new&String("abc");&&
if&(str1.equals(str2))&{&&
&&&&//&判断成立,因为两个对象的内容都是"abc"。&&
&&&&System.out.println("两个对象的内容相等");&&
关于如何改写equals方法以及与之相关的hashCode方法,可以参考潘爱民翻译的《Effective
Java中文版》一文中第7条:在改写equals的时候请遵守通用约定 以及
第8条:改写equals时总是要改写hashCode。
老生常谈:==与equals的区别
对于Java初学者而言,==与equals是容易混淆的。当然区分它们也是简单的,只要记住:
==只针对变量的值;equals只针对对象的内容。
记住上句话的同时,请记住下面的一句话:
引用类型的变量值是所指对象的内存地址。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。枚举在MSDN的定义是:
enum 关键字用于声明枚举,即一种由一组称为枚举数列表的命名常数组成的独特类型。每种枚举类型都有基础类型,该类型可以是除 char 以外的任何整型。枚举元素的默认基础类型为 int。默认情况下,第一个枚举数的值为 0,后面每个枚举数的值依次递增1。
关于枚举的个方面已经有一片很不错的文章说明了,可以通过以下链接访问:
我这里的研究更加简单和浅显一些,主要是将它在实际应用中遇到的问题做一个说明。
我们知道 SqlServerType.Access.ToString() 将取得一个字符串 &Access&,那么下面的方法A和方法B,你认为哪一个可以正确执行呢?
protected&enum&SqlServerType&{&&&&Access,&&&&SqlServer}protected&void&A()&{&&&&switch&(&Access&)&...{&&&&&&&&case&SqlServerType.Access.ToString():&&&&&&&&&&&&...&//Code&&&&&&&&case&SqlServerType.SqlServer.ToString():&&&&&&&&&&&&...&//Code&&&&}}protected&void&B()&{&&&&switch&(SqlServerType.Access.ToString())&{&&&&&&&&case&&Access&:&&&&&&&&&&&&...&//Code&&&&&&&&case&&SqlServer&:&&&&&&&&&&&&...&//Code&&&&}}
虽然他们看起来都是字符串在比较,但其实不是,方法A将无法编译,在 case 处提示应输入常量值。无论如何都无法让 switch 认为 SqlServerType.Access.ToString() 是一个字符串。事实上这个问题应该是 switch 的问题,我以为 case 是和 .ToString() 比较,但其实 case 先比较了 SqlServerType ,所以导致了程序出错,为什么会这样呢?我想和 switch 的运行机制有关,这个等稍后我再研究。
但是我希望通过 ConfigurationManager.ConnectionStrings[&DatabaseType&] 来取得数据库类型,该怎么办呢?我们可以将字符串转换成一个 enum 值。
SqlServerType&sType&=&Enum.Parse(typeof(SqlServerType),&ConfigurationManager.ConnectionStrings[&DatabaseType&].ToString());switch&(sType)&{&&&&case&SqlServerType.Access:&&&&case&SqlServerType.SqlServer:}
通过这样的转换,就 enum 型的数据就可以和 string 比较了。
本文已收录于以下专栏:
相关文章推荐
以前也遇到过类似的问题。就是对于一些参数,比如type之类的,对不同的type需要进行不同的处理。
对于这种情况,使用switch应该算是最恰当的了,但问题是switch并不支持String类型(听...
在有多个选择路径的情况下,利用Switch可以使程序更加简洁有效。但由于其只能对整数选择因子进行判断,所以限制了其在其他类型尤其是String的使用,本文利用JDK1.5新推出的enum,实现了一种可...
枚举类和String类互相转换
枚举类转换成字符类型有两种方法
1.toString() 
说明: 这两个方法都可以返回此枚举常量的名称
字符类型...
字符串 比较:model.getType().equals(&RANGE&)
枚举比较:model.getType()==CompanyVendorRecruit.Type.RANGE
一般在Java代码里面,涉及到比较2个值的问题,除了是简单的一般数据类型意外,字符串除外,我们都是使用==来判断是否相等的,但是对于字符串和对象以及封装类型的数据都是使用equals方法,来判断2个值...
我知道Java枚举会被编译成一个包含私有构造参数和一堆静态方法的类,当去比较两个枚举的时候,总是使用equals()方法,例如:
public useEnums(SomeEnum a...
这两个不太常用的小知识点,今天碰到了,所以特来总结一下。union类union X
他的最新文章
讲师:汪剑
讲师:刘道宽
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)5431人阅读
JAVA(125)
我知道Java枚举会被编译成一个包含私有构造参数和一堆静态方法的类,当去比较两个枚举的时候,总是使用equals()方法,例如:
public useEnums(SomeEnum a)
if(a.equals(SomeEnum.SOME_ENUM_VALUE))
除此之外,我也可以使用 == 替代equals() 方法
public useEnums2(SomeEnum a)
if(a == SomeEnum.SOME_ENUM_VALUE)
我有5年以上的java编程经验,并且我想我也懂得 == 和 equals() 之间的区别,但是我仍然觉得很困惑,哪一个操作符才是我该使用的。
二者皆对,如果你看过枚举的源码,你会发现在源码中,equals也仅仅非常简单的 == 。 我使用 == ,因为无论如何,这个左值是可以为 null的
译者补充 java.lang.Enum 中Equals 代码:
public final boolean equals(Object other) {
return this==
能在枚举中使用
== 进行判断?
答案是肯定的,因为枚举有着严格的实例化控制,所以你可以用 == 去做比较符,这个用法,在官方文档中也有明确的说明。
JLS 8.9 Enums 一个枚举类型除了定义的那些枚举常量外没有其他实例了。 试图明确地说明一种枚举类型是会导致编译期异常。在枚举中final clone方法确保枚举常量从不会被克隆,而且序列化机制会确保从不会因为反序列化而创造复制的实例。枚举类型的反射实例化也是被禁止的。总之,以上内容确保了除了定义的枚举常量之外,没有枚举类型实例。
因为每个枚举常量只有一个实例,所以如果在比较两个参考值,至少有一个涉及到枚举常量时,允许使用“==”代替equals()。(equals()方法在枚举类中是一个final方法,在参数和返回结果时,很少调用父类的equals()方法,因此是一种恒等的比较。)
== 和 equals 不一样?
As a reminder, it needs to be said that generally, == is NOT a viable alternative to equals. When it is, however (such as with enum), there are two important differences to consider: 通常来说 == 不是一个 equals的一个备选方案,无论如何有2个重要的不同处需要考虑:
不会抛出 NullPointerException
enum Color { BLACK, WHITE };
Color nothing = null;
if (nothing == Color.BLACK);
// runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException
在编译期检测类型兼容性
enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };
if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT);
// DOESN'T COMPILE!!! Incompatible types!
什么时候使用
Bloch specifically mentions that immutable classes that have proper control over their instances can guarantee to their clients that == is usable. enum is specifically mentioned to exemplify. 具体来说,那些提供恰当实例控制的不可变类能够保证 == 是可用的,枚举刚好符合这个条件。
考虑静态工厂方法代替构造器 它使得不可变的类可以确保不会存在两个相等的实例,即当且仅当a==b的时候才有a.equals(b)为true。如果类保证了这一点,它的客户端可以使用“==”操作符来代替equals(Object)方法,这样可以提升性能。枚举类型保证了这一点
总而言之,在枚举比较上使用 == , 因为: 1. 能正常工作 2. 更快 3. 运行时是安全的 4. 编译期也是安全的
stackoverlfow链接:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:840135次
积分:16113
积分:16113
排名:第694名
原创:655篇
转载:416篇
评论:132条
总有一天你将破蛹而出,成长得比人们期待的还要美丽。
但这个过程会很痛,会很辛苦,有时候还会觉得灰心。
面对着汹涌而来的现实,觉得自己渺小无力。
但这,也是生命的一部分。做好现在你能做的,然后,一切都会好的。
我们都将孤独地长大,不要害怕。
——&寂地《踮脚张望的时光》
文章:94篇
阅读:67583
文章:86篇
阅读:22635
文章:19篇
阅读:20604
(15)(34)(27)(34)(24)(36)(36)(29)(2)(9)(14)(26)(19)(29)(35)(22)(8)(1)(8)(5)(4)(12)(2)(1)(9)(37)(1)(2)(1)(1)(4)(8)(3)(2)(1)(20)(41)(36)(51)(1)(3)(46)(85)(55)(37)(27)(27)(44)(97)(2)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'java中equals()与==比较
Java中equals()与==的区别
java中的数据类型,可分为两类:
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
& 他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
3。为什么equals重写后hashCode必须要重写?
equals重写后可能是按值比较,那么为了能够将对象正常装入散列表不被覆盖所以要重写hashCode方法。比如String和基本数据类型的包装类就是重写了hashCode方法,其hashCode方法是按值给出的散列吗,有可能会导致覆盖问题。所以当用到集合框架中的Set时一定要检查hashCode,因为Set集合必须保证值唯一。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。
public&class&TestString&{&&
public&static&void&main(String[]&args)&{&&
String&s1&=&"Monday";&&
String&s2&=&"Monday";&&
if&(s1&==&s2)&&
System.out.println("s1&==&s2");}&&
System.out.println("s1&!=&s2");}&&
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = "Monday";
if (s1 == s2)
System.out.println("s1 == s2");}
System.out.println("s1 != s2");}
编译并运行程序,输出:s1 == s2说明:s1 与 s2 引用同一个 String 对象 --
2.再稍微改动一下程序,会有更奇怪的发现:
public&class&TestString&{&&
public&static&void&main(String[]&args)&{&&
String&s1&=&"Monday";&&
String&s2&=&new&String("Monday");&&
if&(s1&==&s2)&&
{System.out.println("s1&==&s2");}&&
{System.out.println("s1&!=&s2");}&&
if&(s1.equals(s2))&{System.out.println("s1&equals&s2");}&&
System.out.println("s1&not&equals&s2");}&&
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
if (s1 == s2)
{System.out.println("s1 == s2");}
{System.out.println("s1 != s2");}
if (s1.equals(s2)) {System.out.println("s1 equals s2");}
System.out.println("s1 not equals s2");}
我们将s2用new操作符创建
程序输出:
s1 equals s2
说明:s1 s2分别引用了两个"Monday"String对象
3. 字符串缓冲池
原来,程序在运行的时候会创建一个字符串缓冲池当使用 s2 = "Monday"
这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的
将s2引用s1所引用的对象"Monday"
第二段程序中,使用了 new
操作符,他明白的告诉程序:"我要一个新的!不要旧的!"于是一个新的"Monday"Sting对象被创建在内存中。他们的值相同,但是位置不同,一个在池中游泳一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?
4.再次更改程序:
public&class&TestString&{&&
public&static&void&main(String[]&args)&{&&
String&s1&=&"Monday";&&
String&s2&=&new&String("Monday");&&
s2&=&s2.intern();&&
if&(s1&==&s2)&&
{System.out.println("s1&==&s2");}&&
{System.out.println("s1&!=&s2");}&&
if&(s1.equals(s2))&{System.out.println("s1&equals&s2");}&&
System.out.println("s1&not&equals&s2");}&&
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern();
if (s1 == s2)
{System.out.println("s1 == s2");}
{System.out.println("s1 != s2");}
if (s1.equals(s2)) {System.out.println("s1 equals s2");}
System.out.println("s1 not equals s2");}
这次加入:s2 = s2.intern();
程序输出:
s1 equals s2
原来,(java.lang.String的intern()方法"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。但实际上,它做了个小动作:检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。
《equals()与==比较》
&Java中的equals是十分重要的,和=
=要区别开来,最近在看孙卫琴的JAVA面向对象编程一书,觉得对其阐述写的不错,所以现在小结其
主要内容,而且要将 = =和 equals列为重要的对比概念来学习
1、声明格式
public& boolean equals(Object obj)
其比较规则为:当参数obj引用的对象与当前对象为同一个对象时,就返回true,否则返回false.
比如以下两个对象animal1和animal2,引用不同的对象,因此用==或equals()方法比较的结果为而animal1和animal3变量引用同一个DOg对象,因此用=
=或者equals()方法比较的结果为true.
&& Animal&
animal1=new Dog();
&& Animal&
animal2=new& Cat();
&& Animal animal3=animal1;
则animal1==animal2&& (FALSE)
animal1.equals(animal2)& (false)
animal1==animal3&& (true)
animal1.equals(animal3)&&
而JDK类中有一些类覆盖了oject类的equals()方法,比较规则为:如果两个对象的类型一致,并且内容一致,则返回true,这些类有:
java.io.file,java.util.Date,java.lang.string,包装类(Integer,Double等)
Integer& int1=new Integer(1);
Integer int2=new Integer(1);
String str1=new String("hello");
String str2=new String("hello");
int1==int2&&
输出:false,因为不同对象
int1.equals(int2)&& 输出:TRUE
str1==str2&& (false)
str1.equals(str2)&& (true)
当然,可以自定义覆盖object类的equals()方法,重新定义比较规则。比如,下面Person类的equals()比较规则为:只要两个对象都是Person类,并且他们的属性name都相同,则比较结果为true,否则返回false
public class Person{
&& private S
&& public Person(String
this.name=
public boolean equals(Object o)
& if (this==0)&
if (!o instanceof Person)
final Person other=(Person)o;
&if (this.name().equals(other.name()))
&&& return
注意,在重写equals方法时,要注意满足离散数学上的特性
1、 自反性&:对任意引用值X,x.equals(x)的返回值一定为true.
2&&&&对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为
传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true
一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变
非空性:任何非空的引用值X,x.equals(null)的返回值一定为false
堆与栈的例子
先看看代码呗
public&static&void&main(String&args[])&&&&&
&&&&{&&&&&
&&&&&&&&&&&&&
&&&&&&&&&&&&Integer&i1=new&Integer(13);&&&&&
&&&&&&&&Integer&i2=new&Integer(13);&&&&&
&&&&&&&&System.out.println(i1==i2);//false
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&int&i3&=&1150;&&
&&&&&&&&int&i4&=&1150;&&
&&&&&&&&&&
&&&&&&&&System.out.println(i3==i4);//true
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&int&i5=13;&&&&&
&&&&&&&&System.out.println(i2==i5);//true&
&&&&&&&&System.out.println(i5==i1);//true
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&Integer&i6&=&12;&&
&&&&&&&&Integer&i7&=&12;&&
&&&&&&&&System.out.println(i6==i7);//true
&&&&&&&&i6&=&200;&&&
&&&&&&&&i7&=&200;&&
&&&&&&&&System.out.println(i6==i7);//false
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&}&&&&&
public static void main(String args[])
Integer i1=new Integer(13);
Integer i2=new Integer(13);
System.out.println(i1==i2);//false
int i3 = 1150;
int i4 = 1150;
System.out.println(i3==i4);//true
int i5=13;
System.out.println(i2==i5);//true
System.out.println(i5==i1);//true
Integer i6 = 12;
Integer i7 = 12;
System.out.println(i6==i7);//true
System.out.println(i6==i7);//false
第一个问题应该很好理解,i1和i2是包装类型的引用,存放在栈区,new
Integer(13)生成了两份,存在于堆区。i1和i2指向了堆内存中不同的地址,所以
System.out.println(i1==i2);//false&&
System.out.println(i1==i2);//false
第二个问题,哇哦,这种基本的都拿出来,其实第二个问题主要是为了和第一个问题做比较。“==”在包装类型之间是地址比较,
“==”在基本类型之间是值比较
第三个问题,哎呀,这问题曾经着实让我纠结了很久。以前是这样子想的,因为 i5
是基本类型int的变量,所以i5是存放在栈内存中的,13这个数值也是存放在栈内存中的,i5 指向
13。可以这么理解吧,而引用变量i2指向的是堆内存中13这个integer对象,既然在i2和i3指向的内存地址不同,为什么“System.out.println(i2==i5)”
的结果为 true?
当时是不是脑子不转了,一句话 拆箱之后,值比较。其他就不要想了。
第四个问题看着挺有意思的,都是Integer类型,为什么这里存在一个范围呢?挺诡异的吧。其实看看源码就知道了。这里java在对装箱过程处理的时候,对-128到127之间的数值进行了一个缓存,我猜测,应该是这些数值比较常用,而且在处理的时候效率应该更高一些。
//&value&of&java.lang.Integer.IntegerCache.high&property&(obtained&during&VM&init)
private&static&String&integerCacheHighPropValue;&&
static&void&getAndRemoveCacheProperties()&{&&
&&&&if&(!sun.misc.VM.isBooted())&{&&
&&&&&&&&Properties&props&=&System.getProperties();&&
&&&&&&&&integerCacheHighPropValue&=&&
&&&&&&&&&&&&(String)props.remove("java.lang.Integer.IntegerCache.high");&&
&&&&&&&&if&(integerCacheHighPropValue&!=&null)&&
&&&&&&&&&&&&System.setProperties(props);&&//&remove&from&system&props
private&static&class&IntegerCache&{&&
&&&&static&final&int&&&
&&&&static&final&Integer&cache[];&&
&&&&static&{&&
&&&&&&&&final&int&low&=&-128;&&
&&&&&&&&//&high&value&may&be&configured&by&property
&&&&&&&&int&h&=&127;&&
&&&&&&&&if&(integerCacheHighPropValue&!=&null)&{&&
&&&&&&&&&&&&//&Use&Long.decode&here&to&avoid&invoking&methods&that
&&&&&&&&&&&&//&require&Integer's&autoboxing&cache&to&be&initialized
&&&&&&&&&&&&int&i&=&Long.decode(integerCacheHighPropValue).intValue();&&
&&&&&&&&&&&&i&=&Math.max(i,&127);&&
&&&&&&&&&&&&//&Maximum&array&size&is&Integer.MAX_VALUE
&&&&&&&&&&&&h&=&Math.min(i,&Integer.MAX_VALUE&-&-low);&&
&&&&&&&&}&&
&&&&&&&&high&=&h;&&
&&&&&&&&cache&=&new&Integer[(high&-&low)&+&1];&&
&&&&&&&&int&j&=&&&
&&&&&&&&for(int&k&=&0;&k&&&cache.&k++)&&
&&&&&&&&&&&&cache[k]&=&new&Integer(j++);&&
&&&&private&IntegerCache()&{}&&
public&static&Integer&valueOf(int&i)&{&&
&&&&if(i&&=&-128&&&&i&&=&IntegerCache.high)&&
&&&&&&&&return&IntegerCache.cache[i&+&128];&&
&&&&else&&
&&&&&&&&return&new&Integer(i);&&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 枚举 equals 的文章

 

随机推荐