"=="和equals区别
1.equals比的是双方对象中的内容是否相等.
2."=="比较时分两种情况
注意:两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
(1)如果比较的双方是java的基本数据类型(char,byte,short,int,long,float,double,boolean),那么'=='比较的依据是双方的值是否相等.
int i=2;
int k=2;
System.out.println(i==k); //返回ture
String str1 = "abc";
String str2 = "abc";
Ø 以上两个语句都创建对象.引号内包含文本是String类特有创建对象的方式.
Ø 但是"=="返回的结果是true,为什么呢?因为在JVM内,存在字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率.字符串池由String类维护,我们可以调用intern()方法来访问字符串池。
Ø 当运用引号内包含文本创建对象时,所创建的对象是加入到字符串池里面的.
Ø 如果要创建下一个字符串对象,JVM首先会到字符串池中寻找,是否存在对应的字符串对象,
u 如果存在,则返回一个己存在对象的对象的引用给要创建的对象引用.
u 如果不存在,才会创建一个新的对象,并返回一个新对象的对象引用给要创建的对象引用.
小结:
以上这段话理解起来可能比较拗口.用代码理解就是str2和str1是两个对象引用,并指向了同一个对象.所以'=='返回的是true.
重点:只有引号内包含文本创建对象才会将创建的对象放入字符串池.
String str = new String("abc")这种方法创建的字符串对象是不放入到字符串池的.所以,引号内包含文本创建对象的性能要比后来那种方法创建字符串对象的性能要好.
String str3 = str1+str2; //这种创建方式是不放入字符串池的.
String str4 = str1+"cd"; //这种创建方式是不放入字符串池的.
String str5 = "ab"+str2; //这种创建方式是不放入字符串池的.
String str6 = "ab"+"cd"; //这种创建方式是放入字符串池的.这种情况实际上是创建了1个对象,abcd"1个对象
System.out.println(str1==str2); //返回ture
System.out.println(str1.equals(str2)); //返回ture
(2)如果比较的双方是对象的变量类型,那么'=='比较的依据是双方的对象的引用是否是指向同一个对象.
Date d1 = new Date();
try
{
Thread.sleep(500);
}
catch(Exception e)
{
e.printStackTrace();
}
Date d2 = new Date();
Date d3 = d1;
System.out.println(d1==d2); //返回false
System.out.println(d1==d3); //返回true
System.out.println(d1.equals(d2)); //返回false
System.out.println(d1.equals(d3));//返回true
如果没有线程休息, System.out.println(d1.equals(d2));返回ture,因为在一个时间点内创建了两个Date对象.也就是说两个对象代表的时间是相等的.
3.练习
class Value
{
int i;
};
public class Test1{
public static void main(String[] args){
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));//false
}
}
为什么最后输出是false?有没有人知道到底equals比较的是什么。是对象的引用还是内容?
另一个问题——几个String对象??
我们首先来看一段Java代码:
String str = new String("abc");
String str=new String("abc");
紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢?相信大家对这道题并不陌生,答案也是众所周知的,2个。接下来我们就从这道题展开,一起回顾一下与创建String对象相关的一些JAVA知识。
Ø 我们可以把上面这行代码分成String str、=、"abc"和new String()四部分来看待。
Ø String str只是定义了一个名为str的String类型的变量,因此它并没有创建对象;
Ø =是对变量str进行初始化,将某个对象的引用(或者叫句柄)赋值给它,显然也没有创建对象;
Ø 现在只剩下new String("abc")了。
u 那么,new String("abc")为什么又能被看成"abc"和new String()呢?我们来看一下被我们调用了的String的构造器:
public String(String original) {
//other code ...
}
大家都知道,我们常用的创建一个类的实例(对象)的方法有以下两种:
我们正是使用new调用了String类的上面那个构造器方法创建了一个对象,并将它的引用赋值给了str变量。同时我们注意到,被调用的构造器方法接受的参数也是一个String对象,这个对象正是"abc"。
小结:
1. 使用new创建对象。
2. 调用Class类的newInstance方法,利用反射机制创建对象。