为什么要使用 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();