多态性的一些问题

本文探讨了Java中的多态性概念,包括如何通过继承和方法重写实现多态。文章举例展示了编译时与运行时的动态绑定,并解释了`instanceof`关键字的使用场景和注意事项,强调在向下转型前进行类型检查以避免`ClassCastException`异常。此外,还讨论了方法重载与重写的区别,并给出了`equals()`方法重写时可能遇到的问题。
摘要由CSDN通过智能技术生成

多态的使用:虚拟方法调用

  • 有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法。简称:编译时,看左边;运行时,看右边。
    注:对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)
public class PolyTest2 {
    public static void main(String[] args) {
        Sub s= new Sub();
        System.out.println(s.count);	//20
        s.show();//20

        Base b = s;
        //==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否一样。
        System.out.println(b == s);	//true
        System.out.println(b.count);	//10
        b.show(); //20
    }
}

class Base{
    int count=10;
    public void show(){
        System.out.println(this.count);
    }
}


class Sub extends Base {
    int count= 20;
    public void show() {
        System.out.println(this.count);
    }
}
  • 多态的使用前提:
    1:继承性
    2:方法的重写(而非重载)

public class InterviewTest1 {

	public static void main(String[] args) {
		Base base = new Sub();
		base.add(1, 2, 3);
		//输出sub_1
		//接着取消-------1的注释,输出仍为sub_1
		//子类中的方法add(int a, int[] arr)看成是对父类中的方法add(int a, int... arr)的重写,add(int a, int b, int c)看成是对父类中方法的重载。
		//接着取消-------2的注释,输出变为sub_2

//		Sub s = (Sub)base;
//		s.add(1,2,3);--------2
	}
}

class Base {
	public void add(int a, int... arr) {
		System.out.println("base");
	}
}

class Sub extends Base {

	public void add(int a, int[] arr) {
		System.out.println("sub_1");
	}

//	public void add(int a, int b, int c) {
//		System.out.println("sub_2");
//	}---------1

}

-instanceof 关键字的使用注意点:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类的属性和方法不能调用。
问:如何才能调用子类所特有的属性和方法?
答:使用强制类型转换符,也可称为:向下转型

但是使用强转时,可能出现ClassCastException异常:

   Person p=new Man();
   Woman wo=(Woman)p;//类型转换异常(编译通过,运行不通过)

instanceof关键字的使用
a instanceof A:判断对象a是否是类A的实例。如果,返回true,如果不是,返回false;
使用情境:为了避免在向下转型时出现ClassCastException异常,我们在进行向下转型之前,先进行 instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
如果a instanceof A返回true,则a instanceof B也返回true。 其中类B是类A的父类。由于这种特性,会出现如下情况:

	Person p=new Man();
	if(p instanceof Man){
		System.out.println("man");
	}
	if(p instanceof Person){
		System.out.println("Person");
	}
	//上述结果既会打印man,也会打印Person

更甚:

//      编译通过,运行时也通过
        Object obj = new Woman();
        Person p = (Person)obj;
        if(obj instanceof  Woman){
            System.out.println("obj是Woman的实例");//打印
        }
        if(obj instanceof Person){
            System.out.println("obj也是Person的实例");//打印
        }
        System.out.println(obj.getClass());//obj的类型为Woman类
        p.eat();//输出子类重写的方法:女人少吃,为了减肥。
        p.walk();//输出子类重写的方法:女人,窈窕的走路。
        System.out.println(p.getClass());//p的类型同样为Woman类
//      p.goshopping();//报错

这种情况,在重写equals()方法时就有问题
例如:下面的代码中输入为MyDate类的子类

	@Override
	public boolean equals(Object obj) {
		if(this == obj){
			return true;
		}
		if(obj instanceof MyDate){
			MyDate myDate = (MyDate)obj;
			return this.day == myDate.day && this.month == myDate.month &&
					this.year == myDate.year;
		}
		return false;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值