[学习]操作符“==”与对象的equal()方法 和 instanceof 操作符

[学习]操作符“==”与对象的equal()方法 和 instanceof 操作符
1、操作符“==”
用来比较两个操作元是否相等,这两个操作元既可以是基本类型,也可以是引用类型。
代码01:
/**
 * Demo01.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007        CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * discription:    操作符“==”
 * 
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo01 {

    
/**
     * <pre>
     *     操作符“==”用来比较两个操作元是否相等,这两个操作元既可以是基本类型,也可以是引用类型。
     * </pre>
     
*/
    
public   static   void  f1() {
        
int  a1  =   1 , a2  =   3 ;
        
boolean  b1  =  a1  ==  a2;  //  "=="的操作元为基本类型,b1变量值为false
        System.out.println(b1);

        String str1 
=   " Hello " , str2  =   " World " ;
        
boolean  b2  =  str1  ==  str2;  //  "=="的操作元为引用类型,b2变量值为false
        System.out.println(b2);
    }

    
/**
     * <pre>
     *     当操作符“==”两边都是引用类型时,这两个引用变量必须都引用同一个对象,结果才为true。
     * </pre>
     
*/
    
public   static   void  f2() {
        Integer int1 
=   new  Integer( 1 );
        Integer int2 
=   new  Integer( 1 );
        Integer int3 
=  int1;  //  int3和int1引用同一个对象

        
int [] array1  =   new   int [ 1 ];
        
int [] array2  =   new   int [ 1 ];
        
int [] array3  =  array1;  //  array3和array1引用同一个对象

        System.out.println(
" int1==int2 is  "   +  (int1  ==  int2));
        System.out.println(
" int1==int3 is  "   +  (int1  ==  int3));
        System.out.println(
" array1==array2 is  "   +  (array1  ==  array2));
        System.out.println(
" array1==array3 is  "   +  (array1  ==  array3));
    }

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        System.out.println(
" -----------f1()----------- " );
        Demo01.f1();
        System.out.println(
" -----------f2()----------- " );
        Demo01.f2();
    }

}

输出结果:
----------- f1() -----------
false
false
----------- f2() -----------
int1
== int2 is  false
int1
== int3 is  true
array1
== array2 is  false
array1
== array3 is  true


  2、操作符“==”与多态性
  a、对于引用类型变量,Java编译器根据变量被显式声明的类型去编译。当“==”用于比较引用类型变量时,“==”两边的变量被显式声明的类型必须是同种类型或有继承关系,即位于继承树的同一个继承分支上,否则编译出错。
  b、在运行时,Java 虚拟机将根据两边的引用变量实际引用的对象进行比较。
    假设有4个类--Creature、Animal、Dog和Cat类,它们的继承关系如图所示:
[学习]操作符“==”与对象的equal()方法 和 instanceof 操作符_第1张图片

代码02:
/**
 * Demo02.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007                CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * 
 * <pre>
 *     操作符“==”与多态性
 *         1、对于引用类型变量,Java编译器根据变量被显式声明的类型去编译。当“==”用于比较引用
 *             类型变量时,“==”两边的变量被显式声明的类型必须是同种类型或有继承关系,即位于
 *             继承树的同一个继承分支上,否则编译出错。
 *         2、在运行时,Java 虚拟机将根据两边的引用变量实际引用的对象进行比较。
 * </pre>
 * 
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo02 {

    
/**
     * 
     
*/
    
public   static   void  f1() {
        Dog dog 
=   new  Dog();  //  dog变量被声明为Dog类型
        Creature creature  =  dog;  //  变量creature和dog引用同一个Dog对象
        Animal animal  =   new  Cat();  //  animal 变量被声明为 Animal 类型
        System.out.println(dog  ==  animal);  //  合法,打印false
        System.out.println(dog  ==  creature); //  合法,打印false

    }

    
/**
     * <pre>
     *     这里变量dog被声明为Dog类型,变量cat被声明为Cat类型,Dog类和Cat类之间没有继承关系,
     *     因此这两个变量不能用“==”比较。
     * </pre>
     
*/
    
public   static   void  f2() {
        Dog dog 
=   new  Dog();
        Cat cat 
=   new  Cat();
        
//  System.out.println(dog == cat); //  编译出错
    }

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        Demo02.f1();
    }

}

class  Creature {

}

class  Animal  extends  Creature {

}

class  Dog  extends  Animal {

}

class  Cat  extends  Animal {

}

输出结果:
false
true

3、操作符“==”用于数组类型
数组类型也是引用类型,可以用“==”进行比较

代码03:
/**
 * Demo03.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007        CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * <pre>
 *     操作符“==”用于数组类型
 * </pre>
 * 
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo03 {

    
/**
     * <pre>
     *     数组类型也是引用类型,可以用“==”进行比较
     * </pre>
     
*/
    
public   static   void  f1() {
        
//  boolean b1 = new int[4] == new long[5]; // 编译出错,两边类型不一致
         boolean  b2  =   new   int [ 4 ==   new   int [ 4 ]; //  合法,b2的值为false
        System.out.println(b2);

        
int [] array1  =   new   int [ 4 ];
        
int [] array2  =  array1;
        
boolean  b3  =  array1  ==  array2;  //  合法,b3的值为true
        System.out.println(b3);
    }

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        Demo03.f1();
    }

}

输出结果:
false
true

4、equals() 方法
equals() 方法是在 Object 类中定义的方法,它的声明格式如下:
    public   boolean  equals(Object obj)
Object 类的 equals() 方法的比较规则为:当参数 obj 引用的对象与当前对象为同一个对象时,就返回true,否则返回false。 

 在JDK中有一些类覆盖了 Object 类的equal()方法,它们的比较规则为:
  如果两个对象的类型一致,并且内容一致,则返回true。
 这些类包括:java.io.File、java.util.Date、java.lang.String、包装类(如java.lang.Integer和java.lang.Double类)。

代码04:
/**
 * Demo04.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007        CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo04 {

    
/**
     * <pre>
     *     equals() 方法是在 Object 类中定义的方法,它的声明格式如下:
     *         public boolean equals(Object obj)
     *     Object 类的 equals() 方法的比较规则为:当参数 obj 引用的对象与当前对象为
     *     同一个对象时,就返回true,否则返回false。 
     * </pre>
     
*/
    
public   boolean  equals(Object obj) {
        
if  ( this   ==  obj) {
            
return   true ;
        } 
else  {
            
return   false ;
        }
    }

    
/**
     * <pre>
     *         1、a1和a2变量引用不同的对象,因此用“==”或 equals() 方法比较的结果都为 false;
     *         2、a1和a3变量都引用同一个Dog对象,因此用“==”或equals()方法比较的结果都为true;
     * </pre>
     
*/
    
public   static   void  f1() {
        Animal a1 
=   new  Dog();
        Animal a2 
=   new  Cat();
        Animal a3 
=  a1;

        System.out.println(a1 
==  a2);  //  打印false
        System.out.println(a1.equals(a2));  //  打印false

        System.out.println(a1 
==  a3);  //  打印true
        System.out.println(a1.equals(a3));  //  打印true
    }

    
/**
     * <pre>
     *     在JDK中有一些类覆盖了 Object 类的equal()方法,它们的比较规则为:
     *         如果两个对象的类型一致,并且内容一致,则返回true。
     *     这些类包括:java.io.File、java.util.Date、java.lang.String、
     *         包装类(如java.lang.Integer和java.lang.Double类)。 
     * </pre>
     
*/
    
public   static   void  f2() {
        Integer int1 
=   new  Integer( 1 );
        Integer int2 
=   new  Integer( 1 );

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

        System.out.println(int1 
==  int2);  //  打印false
        System.out.println(int1.equals(int2));  //  打印true

        System.out.println(str1 
==  str2);  //  打印false
        System.out.println(str1.equals(str2));  //  打印true
    }

    
/**
     * <pre>
     *  Boolean 类是包装类,只要两个Boolean对象的布尔值内容一样,
     *  equals()方法的比较结果就为true。
     * </pre>
     
*/
    
public   static   void  f3() {
        Boolean b1 
=   new  Boolean( true );
        Boolean b2 
=   new  Boolean( true );
        
if  (b1  ==  b2) {
            
if  (b1.equals(b2)) {
                System.out.println(
" a " );
            } 
else  {
                System.out.println(
" b " );
            }
        } 
else  {
            
if  (b1.equals(b2)) {
                System.out.println(
" c " );  //  执行这段代码
            }  else  {
                System.out.println(
" d " );
            }
        }
    }

    
/**
     * <pre>
     *  b1和obj1被声明为不同的类型,但它们实际引用的是同一个Dog对象,
     *  因此用“==”或equals()方法比较的结果都为true。
     * </pre>
     
*/
    
public   static   void  f4() {
        Boolean b1 
=   new  Boolean( true );
        Object obj1 
=  (Object) b1;
        
if  (b1  ==  obj1) {
            
if  (b1.equals(obj1)) {
                System.out.println(
" a " );  //  执行这段代码
            }  else  {
                System.out.println(
" b " );
            }
        } 
else  {
            
if  (b1.equals(obj1)) {
                System.out.println(
" c " );
            } 
else  {
                System.out.println(
" d " );
            }
        }
    }

    
/**
     * <pre>
     *  Float 和 Double 类型是包装类型,只要两个 Float 对象或两个 Double对象的内容一样,
     *      equals()方法比较的结果就为true。
     * </pre>
     
*/
    
public   static   void  f5() {
        Float f1 
=   new  Float( " 10F " );
        Float f2 
=   new  Float( " 10F " );
        Double d1 
=   new  Double( " 10D " );

        System.out.println(f1 
==  f2);  //  打印false
        System.out.println(f1.equals(f2));  //  打印true
        System.out.println(f1.equals(d1));  //  打印false,因为f2和d1不是相同类型
        System.out.println(f1.equals( new  Float( " 10 " )));  //  打印true
    }

    
/**
     * <pre>
     *  例如以下变量a和b引用不同的String对象,但它们包含的内容都是“helle”,
     *      所以a.equals(b)的结果为true;
     *  而变量c是字符串数组类型,因此a.equals(c)的结果为false。
     * </pre>
     
*/
    
public   static   void  f6() {
        String a 
=   " hello " ;
        String b 
=   new  String(a);
        
char [] c  =  {  ' h ' ' e ' ' l ' ' l ' ' o '  };

        System.out.println(a 
==   " hello " );  //  打印true
        System.out.println(a  ==  b);  //  打印false
        System.out.println(a.equals(b));  //  打印true
        System.out.println(a.equals(c));  //  打印false
    }

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        System.out.println(
" ----------f1()------------ " );
        Demo04.f1();
        System.out.println(
" ----------f2()------------ " );
        Demo04.f2();
        System.out.println(
" ----------f3()------------ " );
        Demo04.f3();
        System.out.println(
" ----------f4()------------ " );
        Demo04.f4();
        System.out.println(
" ----------f5()------------ " );
        Demo04.f5();
        System.out.println(
" ----------f6()------------ " );
        Demo04.f6();
    }

}

输出结果:
---------- f1() ------------
false
false
true
true
---------- f2() ------------
false
true
false
true
---------- f3() ------------
c
---------- f4() ------------
a
---------- f5() ------------
false
true
false
true
---------- f6() ------------
true
false
true
false

5、在用户自定义的类中也可以覆盖Object类的equals()方法,重新定义比较规则。
代码05:
/**
 * Demo05.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007        CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo05 {

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        Person p1 
=   new  Person( " Tom " );
        Person p2 
=   new  Person( " Tom " );
        System.out.println(p1 
==  p2);  //  打印 false
        System.out.println(p1.equals(p2));  //  打印 true
    }

}

class  Person {
    
private  String name;

    
public  Person(String name) {
        
this .name  =  name;
    }

    
/*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     
*/
    
public   boolean  equals(Object o) {
        
if  ( this   ==  o) {
            
return   true ;
        }

        
final  Person other  =  (Person) o;
        
if  ( this .name.equals(other.name)) {
            
return   true ;
        } 
else  {
            
return   false ;
        }
    }
}

输出结果:
false
true

6、 instanceof操作符

 instanceof操作符用于判断一个引用类型所引用的对象是否是一个类的实例。
 instanceof操作符左边的操作元是一个引用类型,右边的操作元是一个类名或接口名。
 形式如下:

  obj  instanceof  ClassName

或者:

obj  instanceof  InterfaceName 


   例如:

  Dog dog  =   new  Dog();
  Systom.out.println(dog 
instanceof  XXX); // XXX表示一个类名或接口名


  一个类的实例包括类本身的实例,以及所有直接或间接的子类的实例,因此当&quot;XXX&quot;是以下
 值时,instanceof 表达式的值为true。
  ● Dog类
  ● Dog类的直接或间接父类
  ● Dog类实现的接口,已经所有父类实现的接口。


代码06:
/**
 * Demo06.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007        CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * <pre>
 *     instanceof操作符用于判断一个引用类型所引用的对象是否是一个类的实例。
 *     instanceof操作符左边的操作元是一个引用类型,右边的操作元是一个类名或接口名。
 *     形式如下:
 *         obj instanceof ClassName
 *     或者:
 *         obj instanceof InterfaceName 
 *          例如:
 *         Dog dog = new Dog();
 *         Systom.out.println(dog instanceof XXX);//XXX表示一个类名或接口名
 * 
 *         一个类的实例包括类本身的实例,以及所有直接或间接的子类的实例,因此当&quot;XXX&quot;是以下
 *     值时,instanceof 表达式的值为true。
 *         ● Dog类
 *         ● Dog类的直接或间接父类
 *         ● Dog类实现的接口,已经所有父类实现的接口。
 * </pre>
 * 
 * 
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo06 {

    
/**
     * <pre>
     *     由于Animal是Dog的直接父类,Creature类和Object类是Dog的间接父类,
     *     因此以下 instanceof 表达式的值为true。
     * </pre>
     
*/
    
public   static   void  f1() {
        Dog dog 
=   new  Dog();
        System.out.println(dog 
instanceof  Dog);  //  打印 true
        System.out.println(dog  instanceof  Animal);  //  打印 true
        System.out.println(dog  instanceof  Creature);  //  打印 true
        System.out.println(dog  instanceof  Object);  //  打印 true
    }

    
/**
     * <pre>
     *     instanceof 右边的操作元也可以是接口名。
     * </pre>
     
*/
    
public   static   void  f2() {
        B b 
=   new  B();
        System.out.println(b 
instanceof  I);  //  打印 true
    }

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        System.out.println(
" -----------f1()----------- " );
        Demo06.f1();
        System.out.println(
" -----------f2()----------- " );
        Demo06.f2();

    }

}

interface  I {

}

class  A  implements  I {

}

class  B  extends  A {

}

输出结果:
----------- f1() -----------
true
true
true
true
----------- f2() -----------
true

7、  instanceof 与多态性
   对于引用类型变量,Java 编译器只根据变量被先生声明的类去编译。
   instanceof 左边操作元被显式声明的类型与右边操作元必须是同种类或者有继承关系,即位于继承树的同一个继承分支上,否则编译出错。
    Dog dog  =   new  Dog();
    System.out.println(dog 
instanceof  Cat);  //  编译出错
 
    Cat cat 
=   new  Cat();
    System.out.println(cat 
instanceof  Dog);  //  编译出错

  instanceof 用于数组类型
    boolean  b1  =   new   int [ 4 instanceof   long [];  //  编译出错,两边操作元类型不一致
    boolean  b2  =   new   int [ 4 instanceof   int [];  //  合法,b2的值为true

代码07:
/**
 * Demo07.java
 *
 * Provider: CoderDream's Studio
 *
 * History
 *    Date(DD/MM/YYYY)    Author          Description
 * ----------------------------------------------------------------------------
 *    Nov 13, 2007        CoderDream        Created
 
*/
package  com.coderdream.operator;

/**
 * <pre>
 *     instanceof 与多态性
 *         对于引用类型变量,Java 编译器只根据变量被先生声明的类去编译。
 *         instanceof 左边操作元被显式声明的类型与右边操作元必须是同种类或者有继承关系,
 *         即位于继承树的同一个继承分支上,否则编译出错。
 *             Dog dog = new Dog();
 *             System.out.println(dog instanceof Cat); // 编译出错
 * 
 *             Cat cat = new Cat();
 *             System.out.println(cat instanceof Dog); // 编译出错
 *         
 *     instanceof 用于数组类型
 *         boolean b1 = new int[4] instanceof long[]; // 编译出错,两边操作元类型不一致
 *         boolean b2 = new int[4] instanceof int[]; // 合法,b2的值为true
 * </pre>
 * 
 * 
@author  CoderDream
 * 
 
*/
public   class  Demo07 {

    
/**
     * <pre>
     *     在运行时,将根据左边操作元实际引用的对象来判断。
     * </pre>
     
*/
    
public   static   void  f1() {
        Animal a 
=   new  Dog();  //  a 变量被声明为Animal类型,引用Dog对象
        System.out.println(a  instanceof  Animal);  //  合法, 打印true
        System.out.println(a  instanceof  Dog);  //  合法, 打印true
        System.out.println(a  instanceof  Cat);  //  合法, 打印false
    }

    
/**
     * <pre>
     *     假定Animal类是非抽象类,允许实例化,
     * 
     * </pre>
     
*/
    
public   static   void  f2() {
        System.out.println((
new  Demo07()).isInstanceOfAnimal( new  Dog()));  //  打印fasle
        System.out.println(( new  Demo07()).isInstanceOfAnimal( new  Cat()));  //  打印fasle
        System.out.println(( new  Demo07()).isInstanceOfAnimal( new  Animal()));  //  打印true
        System.out.println(( new  Demo07()).isInstanceOfAnimal( new  Creature()));  //  打印fasle
    }

    
/**
     * <pre>
     *     假定Animal类是非抽象类,允许实例化,以下判断规则:
     *         只有当参数 obj 引用 Animal 类本身的实例,而不是它的子类Dog或Cat多实例时,
     *         才返回true。
     * 
     *     如果 obj instanceof Animal为true,那么obj有可能引用 Animal本身、Dog类本身
     *         或Cat类本身的实例;
     *     如果 obj instanceof Dog 和 obj instanceof Cat均为false,那么 obj 不会引用
     *         Dog类本身或Cat类本身的实例。
     *     如果同时满足这几个条件,就可以得出 obj 引用 Animal 类本身的实例的结论。
     * </pre>
     * 
     * 
@param  obj
     * 
@return
     
*/
    
public   boolean  isInstanceOfAnimal(Object obj) {
        
return  obj  instanceof  Animal  &&   ! (obj  instanceof  Dog)
                
&&   ! (obj  instanceof  Cat);
    }

    
/**
     * <pre> 
     *     instanceof 用于数组类型
     * </pre>
     
*/
    
public   static   void  f3() {
        
//  boolean b1 = new int[4] instanceof long[];  //  编译出错,两边操作元类型不一致
         boolean  b2  =   new   int [ 4 instanceof   int [];  //  合法,b2的值为true
        System.out.println(b2);
    }

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        System.out.println(
" -----------f1()----------- " );
        Demo07.f1();
        System.out.println(
" -----------f2()----------- " );
        Demo07.f2();
        System.out.println(
" -----------f3()----------- " );
        Demo07.f3();
    }

}

输出结果:
----------- f1() -----------
true
true
false
----------- f2() -----------
false
false
true
false
----------- f3() -----------
true

你可能感兴趣的:([学习]操作符“==”与对象的equal()方法 和 instanceof 操作符)