目录
一、 首先介绍instanceof关键字
格式:对象 instanceof 类名称
作用:判断对象是否是特定类的一个实例,是返回true,否则返回false.
- 举个栗子:
package zl;
public interface Person {
public void eat();
}
package zl;
public class People implements Person {
@Override
public void eat() {
System.out.println("people eat...");
}
}
package zl;
public class xiaoming extends People {
@Override
public void eat() {
System.out.println("xiaoming eats...");
}
}
package zl;
public static void main(String[] args) {
People p=new People();
xiaoming x=new xiaoming();
System.out.println(p instanceof Person);//true
System.out.println(p instanceof xiaoming);//false
System.out.println(x instanceof Person);//true
System.out.println(x instanceof People);//true
}
结果解释:
Person是接口,People类继承接口Person,xiaoming类继承People类。
从上述结果可以总结:
对象instanceof接口,都为true;
对象instanceof父类,都为true;
对象instanceof他的子类为false。
- 再举个栗子:
package zl;
interface A{
}
class B implements A{
}
class C extends B{
}
public class Iinstanceof {
public static void main(String[] args) {
A ab=new B();
A ac=new C();
B bc=new C();
B bb=new B();
C cc=new C();
//对象实现一个接口,用这个对象和这个接口进行instanceof判断,都为true。
System.out.println("ab instanceof A="+(ab instanceof A));
System.out.println("ac instanceof A="+(ac instanceof A));
System.out.println("bc instanceof A="+(bc instanceof A));
System.out.println("bb instanceof A="+(bb instanceof A));
System.out.println("cc instanceof A="+(cc instanceof A));
//对象和父类进行instanceof判断,都为true
System.out.println("ab instanceof B="+(ab instanceof B)); //true
System.out.println("ac instanceof B="+(ac instanceof B));
System.out.println("bc instanceof B="+(bc instanceof B));
System.out.println("bb instanceof B="+(bb instanceof B));
System.out.println("cc instanceof B="+(cc instanceof B));
//对象和他的子类进行instanceof判断为false
System.out.println("ab instanceof C="+(ab instanceof C));
System.out.println("ac instanceof C="+(ac instanceof C)); //true
System.out.println("bc instanceof C="+(bc instanceof C)); //true
System.out.println("bb instanceof C="+(bb instanceof C));
System.out.println("cc instanceof C="+(cc instanceof C));
}
}
运行结果:
结果解释:
此例与上例不同之处在于注释行,进行了向上转型,综上,可总结为:
对象instanceof接口,都为true;
对象instanceof父类,都为true;
对象instanceof他的子类为false;
(对象)instanceof(他的向上转型使用的子类),为true。
二、向上转型
将子类对象转为父类对象,此处父类对象可以是接口(父<--子)
- 举个栗子:
package zl;
public abstract class Animal {
public abstract void eat();
}
package zl;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("Just for fun !");
}
}
package zl;
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("吃肉");
}
public void lookHome(){
System.out.println("二哈看家");
}
}
package zl;
public class demo_instanceof {
public static void main(String[] args) {
Animal animal = new Cat(); //向上转型
animal.eat(); //调用cat.eat()
//animal.catchMouse(); 出现红波浪线错误
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.lookHome();
}
if (animal instanceof Cat) { //向上转型后的父类对象还是子类的一个实例
Cat cat = (Cat) animal; //向下转型
cat.catchMouse();
}
giveMeAnAnimal(new Cat());
giveMeAnAnimal(new Dog());
}
private static void giveMeAnAnimal(Animal animal) { //向上转型
if (animal instanceof Dog) {
Dog dog = (Dog) animal; //向下转型
dog.lookHome();
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;//向下转型
cat.catchMouse();
}
}
}
运行结果:
结果解释:
Animal animal = new Cat();向上转型时animal会遗失除与子类对象共有的其他方法,此处遗失catchMouse();调用与子类对象共有的方法时将调用子类的方法,即调用animal.eat(); 相当于调用cat.eat()。
animal instanceof Cat(Animal的向上转型使用的子类) 结果为true;animal instanceof Dog(Animal的子类) 结果为false;
向上转型的好处 :
giveMeAnAnimal(Animal animal)方法以父类为参数,调用时用子类作为参数 giveMeAnAnimal(new Cat()); giveMeAnAnimal(new Dog());利用了向上转型。此时需使用instanceof判断要执行的代码块。
如果giveMeAnAnimal以子类对象为参数,则有多少个子类就需要写多少个函数。这也体现了JAVA的抽象编程思想。
三、 向下转型
把父类对象转为子类对象
package zl;
public class Girl {
public void smile(){
System.out.println("girl smile()...");
}
}
package zl;
public class MMGirl extends Girl{
@Override
public void smile() {
System.out.println("MMGirl smile sounds sweet...");
}
public void c(){
System.out.println("MMGirl c()...");
}
}
package zl;
class Main{
public static void main(String[] args) {
Girl g1=new MMGirl(); //向上转型
g1.smile(); //MMGirl.smile()
MMGirl mmg=(MMGirl)g1; //向下转型,编译和运行皆不会出错
mmg.smile();
mmg.c(); //要调用非公共方法时,必须 向下转型
Girl g2=new Girl();
// MMGirl mmg1=(MMGirl)g2; //不安全的向下转型,编译无错但运行会出错 java.lang.ClassCastException
// mmg1.smile();
// mmg1.c();
//替换掉上述注释的代码
if(g2 instanceof MMGirl){ //避免 不安全的向下转型(即没有经过向上转型不可以进行向下转型)
MMGirl mmg1=(MMGirl)g2;
mmg1.smile();
mmg1.c();
}
}
}
运行结果:
结果解释:
c()方法只有MMGirl类有,Girl类中无,要想调用c()方法,必须进行向下转型,此处为MMGirl mmg=(MMGirl)g1;
直接向下转型Girl g2=new Girl(); MMGirl mmg1=(MMGirl)g2;不安全,通过判断g2 instanceof MMGirl可避免出现java.lang.ClassCastException错误。
向下转型的好处:
由上述例子可总结为:1.通过向下转型调用子类中父类没有的方法;2.使用向下转型时一定要使用instanceof 判断。
参考链接:https://www.cnblogs.com/ggzhangxiaochao/p/9528656.html,https://blog.csdn.net/liuchaoxuan/article/details/79937538,https://blog.csdn.net/chenz_yang/article/details/75137973,https://blog.csdn.net/mingxu_W/article/details/86362031