第3章 操作符
一,别名现象与对象引用
int a = b 表示将b的值赋给a,之后a和b是两个独立的部分。但是在为对象进行“赋值”的时候,情况却发生了变化。对一个对象进行操作时,我们真正操作的是对象的引用。所以倘若“将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方。Object a = b 则a 将被 b引用覆盖,a和b指向b所指的对象。
如下代码
public class Test{
private int level;
private String name;
public void add()
{
level++;
}
public void Subtract(Test t)
{
t.level--;
}
public String getLevel()
{
return name+":"+level;
}
public Test(String name ,int level)
{
this.name=name;
this.level=level;
}
public static void main(String[] args) {
Test t1=new Test("t1",10);
Test t3=new Test("t3",30);
Test t4=new Test("t4",40);
Test t2=new Test("t2",20);
t2=t1;
t2.add();
System.out.println(t1.getLevel()+"|address:"+t1.toString());
System.out.println(t2.getLevel()+"|address:"+t2.toString());
t3.Subtract(t4);
System.out.println(t3.getLevel()+"|address:"+t3.toString());
System.out.println(t4.getLevel()+"|address:"+t4.toString());
}
}
运行结果:
表达式t2=t1;将t1在内存中的引用传递给t2,原来t2的引用被覆盖。t1和t2是对同一内存空间的引用,所以t2的level加1后,t1的level也加1改变。t3.Subtract(t4);说明以对象作为函数参数可以实现对该对象进行操作。在上面两个例子中,其实都是Java中的别名现象,只不过表现形式不同,他们都是在对同一个引用进行操作。我们可能并不希望第一个例子中t1中的level也增加了,
在java中有接口Cloneable,实现它方法clone()。然后将 Person p2 = p1替换成Test t2 = t1.clone()即可。
代码如下:
public class Test implements Cloneable{
private int level;
private String name;
public void add()
{
level++;
}
public void Subtract(Test t)
{
t.level--;
}
public String getLevel()
{
return name+":"+level;
}
public Test(String name ,int level)
{
this.name=name;
this.level=level;
}
public Test clone(){
Test object = null;
try {
object = (Test) super.clone();
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return object;}
public static void main(String[] args) {
Test t1=new Test("t1",10);
Test t3=new Test("t3",30);
Test t4=new Test("t4",40);
//Test t2=new Test("t2",20);
Test t2=t1.clone();
t2.add();
System.out.println(t1.getLevel()+"|address:"+t1.toString());
System.out.println(t2.getLevel()+"|address:"+t2.toString());
t3.Subtract(t4);
System.out.println(t3.getLevel()+"|address:"+t3.toString());
System.out.println(t4.getLevel()+"|address:"+t4.toString());
}
}
运行结果
clone()方法是在内存中再次给t2划分出一块资源,t1与t2各自拥有一个引用,此时的p1和p2是在内存中是两个完全独立的部分,谁都不能对另一个对象进行任何操作,但是这两个对象中的值又是完全相同的(刚刚调用clone方法后),包括name,level等其他变量或者方法,
二,“==”与“equals()”
观察下面代码
public class Test1 {
int t;
public static void main(String[] args) {
int a=2;
int b=2;
Integer n1=new Integer(3);
Integer n2=new Integer(3);
Test1 t1=new Test1();
Test1 t2=new Test1();
t1.t=t2.t=7;
System.out.println(a==b);
System.out.println(n1==n2);
System.out.println(n1.equals(n2));
System.out.println(t1==t2);
System.out.println(t1.equals(t2));
}
}
结果:
true
false
true
false
false
“==”对于基本数据类型,判断两个变量的值是否相等,“equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。
因为对象变量的存储的是对象在内存中的路径,即内存地址。所以用“==”比较时,即使 对象的值相等,但是他们的内存地址不同,所以==的结果为false。总之: “==”比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】 equals()用于比较两个对象的值是否相同【不是比地址】
【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==”不同,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
Integer类·的equals方法
Object类的equals方法