2019-12-17 · instanceof 关键字的使用

为什么要使用 instanceof 关键字?

我们学习使用到多态以后,父类的引用指向子类的对象,例如(Person p2 = new Man();)。这个时候,我们使用虚拟方法调用,例如(p2.eat();)结果是当调用子父类同名同参数的方法时,实际调用的是子类重写父类的方法。
也就是说,虚拟方法调用只可以调出来子类重写父类的方法,而且必须是子父类同名同参数的方法。
但是我们就想调用子类中定义的独立的方法的时候,我们就要用到向下转型:使用强制类型转换符。

基本数据类型转换和引用数据类型转换
//我们使用父类引用指向子类的对象。
//这个时候我们可以进行强制类型转换。
//使用“()”来转。转换成功后,我们就可以通过引用来调用子类定义的方法了。
      Person p2 = new Man();
      Man m11 = (Man)p2;//转换格式
      m11.earnMoney();
      m11.isSmoking = true;

再回到一开始的问题...

为什么要使用 instanceof 关键字?

因为我们在使用向下强制转换的时候,可能会出现ClassCastException的异常(程序终止),所以我们在向下转型之前,要先进行 instanceof 的判断,一旦返回 true,就进行向下转型。如果返回 false,不进行向下转型。

//父类的变量名 p2,指向子类 Man()类型。
//所以进行向下转型,Man 会成功,Woman 会失败。
Person p2 = new Man();
if(p2 instanceof Woman) {
            Woman w1 = (Woman)p2;
            w1.goShopping();
            System.out.println("***Woman***");
        }
        //如果a  instanceof  A返回true,则a  instanceof  B也返回true.
if(p2 instanceof Man) {
            Man m2 = (Man)p2;
            m2.earnMoney();
            System.out.println("***Man***");
        }

再补充一点:

如果 a instanceof A返回 true,则 a instanceof B也返回true。其中,类 B 是类 A 的父类。

a instanceof A 的意思类似于:

a 是变量名或者对象,判断这个 a 是 A 的类型就返回 true。a 和 A 没有如何关系,就返回 false。

        Person p2 = new Man();
        //如果 a  instanceof  A 返回true,则 a  instanceof  B 也返回 true.
        if(p2 instanceof Man) {
            Man m2 = (Man)p2;
            m2.earnMoney();
            System.out.println("***Man***");
        }
        //其中,类B是类A的父类。
        if(p2 instanceof Person) {//Person 类是 Man 类的直接父类
            Person p0 = (Person)p2;
            p0.walk();
            System.out.println("***Person***");
        }
        if(p2 instanceof Object) {//Object 类是所有类的间接父类
            System.out.println("***Object***");
        }

最后附上完整笔记代码:

Person 类:

package com.it17;

public class Person {
    String name;
    int age;
    
    int id = 1001;
    
    public void eat() {
        System.out.println("人吃饭");
    }
    public void walk() {
        System.out.println("人走路");
    }
}

Man 类:

package com.it17;

public class Man extends Person {
    
    boolean isSmoking;
    
    int id = 1002;
    
    public void earnMoney() {
        System.out.println("男人负责挣钱养家");
    }
    public void eat() {
        System.out.println("男人多吃肉");
    }
    public void walk() {
        System.out.println("男人走路要霸气");
    }
}

Woman 类:

package com.it17;

public class Woman extends Person{

    boolean isBeauty;
    
    public void goShopping() {
        System.out.println("女人喜欢购物");
    }
    public void eat() {
        System.out.println("女人少吃,为了减肥");
    }
    public void walk() {
        System.out.println("女人走路");
    }
}

PersonTest 测试类:

package com.it17;
/*
 * 面向对象特征的多态性
 * 
 * 1.理解多态性:可以理解为一个事物的多种形态。
 * 2.何为多态性:
 *      对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
 * 
 * 3.多态的使用:虚拟方法调用
 *  有了对象的多态性以后(Person p2 = new Man();),我们在编译期,
 *  只能调用父类中声明的方法,但是在运行期,我们实际上执行的是子类中重写的同名方法。
 *  总结:编译看左边;运行看右边。
 * 
 * 4.多态性的使用前提:一,类的继承关系; 二,方法的重写。
 * 
 * 5.对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)
 * ************************************************************
 * 
 * 
 * 
 */
public class PersonTest {
    public static void main(String[] args) {
        //常规的声明,new对象。
        Person p1 = new Person();
        p1.eat();
        
        Man m1 = new Man();
        m1.eat();
        m1.age = 25;
        m1.earnMoney();
        
        System.out.println("**************");   
//**************************************************************
        //多态情况下声明,new对象。
        //对象的多态性:
        //父类的引用,指向子类的对象。声明了一个变量,new出来的对象有多种形态
        Person p2 = new Man();
        
        //多态的使用:也称为虚拟方法调用
        //当调用子父类同名同参数的方法是,实际执行的是子类重写父类的方法。
        p2.eat();
        p2.walk();
        
        //对象的多态性,不适用于调用属性
        System.out.println(p2.id);  
        System.out.println("**************");   
//**************************************************************
        
        //不能调用子类所特有的方法,属性;编译时,p2是person类型。
        p2.name = "Tom";
//      p2.earnMoney();
//      p2.isSmoking = true;
        /*
         * 有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,
         * 但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。
         * 子类特有的属性和方法不能调用。
         */
        //如何才能调用子类特有的属性和方法?
        //向下转型:使用强制类型转换符。
        Man m11 = (Man)p2;
        m11.earnMoney();
        m11.isSmoking = true;
        
        //使用强转时,可能出现ClassCastException的异常
//      Woman w1 = (Woman)p2;
//      w1.goShopping();
        
        /*
         * instanceof关键字的使用
         * 
         * a  instanceof  A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
         * 
         * 使用情境:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,
         * 先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
         * 
         * 如果a  instanceof  A返回true,则a  instanceof  B也返回true.
         * 其中,类B是类A的父类。
         */
        if(p2 instanceof Woman) {
            Woman w1 = (Woman)p2;
            w1.goShopping();
            System.out.println("***Woman***");
        }
        //如果a  instanceof  A返回true,则a  instanceof  B也返回true.
        if(p2 instanceof Man) {
            Man m2 = (Man)p2;
            m2.earnMoney();
            System.out.println("***Man***");
        }
        //其中,类B是类A的父类。
        if(p2 instanceof Person) {
            Person p0 = (Person)p2;
            p0.walk();
            System.out.println("***Person***");
        }
        if(p2 instanceof Object) {
            System.out.println("***Object***");
        }
    }
}

最最最后面关于 instanceof 的练习:

        //练习:
        //问题一:编译时通过,运行时不通过
        //举例一:
        Person p3 = new Person();
        Man m3 = (Man)p3;
        //举例二:
        Person p5 = new Person();
        Man m4 = (Man)p5;
        
        //问题二:编译时通过,运行时也通过
        Object obj = new Woman();
        Person p3 = (Person)obj;
        
        //问题三:编译不过(右边new的东西必须是左边的子类)
        //举例一:
        Man m5 = new Woman();
        //举例二:
        String str = new Date();
        
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容