室友领个快递的时间我居然学会了多态?(详细分析)

26 篇文章 3 订阅

目录

多态 

虚拟方法调用

面试题:多态是编译时行为,还是运行时行为?

方法的重载和重写 

对象类型的转换

向下类型转换 


多态 

对象的多态性父类的引用指向子类的对象(可以直接应用在抽象类和接口上)

利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。

视频笔记:Java引用对象分为两个类型,编译时类型运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。

若编译时类型和运行时类型不一样,则体现了对象的多态性(Polymorphism)

多态情况下的  看左边:看的是父类的引用(父类中不具备子类特有的方法)

                        看右边:看的是子类的对象(实际运行的是子类重写父类的方法)

理解多态性,可以理解为一个事物的多种形态


public class student {
	 int m=2;
	  public student() {
		  
	  }
 public void study()
{
	System.out.println("学生"); 
}
}

public class studentA extends student//继承父类
{
	int age=10;
	public studentA()
	{	
		}
	public void study() {
		System.out.println("小明");
	}
	public static void main(String[] args)
	{
	student A=new studentA();
	A.study();
	}
}

 多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法——虚拟方法调用。所以我们编译结果是

 

但是当我们声明一个子类所有的函数,父类没有的时候,想要调用

 

编译时,看左边。这时候就会报错,因为编译器检查的变量A的类型是student,但是在student类型中没有发现kk方法,所以编译报错

多态的使用前提:1.类的继承关系.2.方法的重写3.父类引用指向子类对象

下面看一段代码

public class student {
	 int m=2;
	  public student() {
		  
	  }
 public void study()
{
	System.out.println("学生"); 
}
}
public class studentA extends student//继承父类
{
	int age=10;
	public studentA()
	{	
    }
	public void study() {
		System.out.println("小明");
	}

}
public class studenttest {
	public static void main(String[] args)
	{
		studenttest a1=new studenttest();
          a1.test(new student());
   
	}
	public void test(student a)
	{
		a.study();
	}
}

原理和上面一样

对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)

public class student {
	 int age=2;
	  public student() {
		  
	  }
}
public class studentA extends student//继承父类
{
	int age=10;
	public studentA()
	{	
    }
}
public class studenttest {
	public static void main(String[] args)
	{
		student B=new studentA();
		System.out.println(B.age);
	}
}

 这里我们运行产生的结果是父类定义的属性,值为2.

虚拟方法调用

1.正常的方法调用

student B=student();
 B.study();

2.虚拟方法调用:子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类该方法,这样的方法在编译器期是无法确定的。

student B=new studentA();
B.study();

编译时B为student类型,而方法的调用是在运行时确定的,所以调用的是studentA类的study()方法。——动态绑定

面试题:多态是编译时行为,还是运行时行为?

public class student {
	  public void study() {
		  System.out.println("student");
	  }
}
public class studentA extends student//继承父类
{
	int age=10;
public void study()
{
	System.out.println("A");
}
}
public class studentB extends student  {
	public void study()
	{
		System.out.println("B");
	}
}
public class studentC extends student{
	public  void study()
	{
		System.out.println("C");
	}
}
package gh;
import java.util.Random;
public class studenttest {
	public static student test(int key)
	{
		switch(key)
		{
		case 0:return new studentA ();
		case 1:return new studentB();
		default :return new studentC();
		
		}
	}
	public static void main(String[] args)
	{
	int key=new Random().nextInt(2);
	System.out.println(key);
	student s1=test(key);
	s1.study();
	}
}

 

 通过以上代码我们可以看出多态是运行时行为

方法的重载和重写 

重载是编译时多态
调用重载的方法 , 在编译期间就要确定调用的方法是谁 , 如果不能确定则编译报错

重写是运行时多态  

调用重写的方法 , 在运行期间才能确定这个方法到底是哪个对象中的。这个取决于调用方法的引用 , 在运行
期间所指向的对象是谁 , 这个引用指向哪个对象那么调用的就是哪个对象中的方法。 ( java 中的方法调用 ,
是运行时动态和对象绑定的 )
3 、多态的注意事项
1. 多态是方法的多态,属性没有多态性。
2. 编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。但是
如果两个没有关联的类进行强制转换,会报: ClassCastException 。 比如:本来是狗,我把它转成
猫。就会报这个异常。
3. 多态的存在要有 3 个必要条件:要有继承,要有方法重写,父类引用指向子类对象
以下三种类型的方法是没
有办法表现出多态特性的(因为不能被重写):
1.static 方法,因为被 static 修饰的方法是属于类的,而不是属于实例的
2.final 方法,因为被 fifinal 修饰的方法无法被子类重写
3. private 方法和protected 方法,前者是因为被 private 修饰的方法对子类不可见,后者是因为尽管被
protected修饰的方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的,

视频笔记: 

对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为"早绑定"或"静态绑定";

对于重写而言,只有等到方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为"晚绑定"或"动态绑定".

引用一句Bruce Eckle的话:不要犯傻,只要不是晚绑定,它就不是多态

对象类型的转换

 A instanceof B

A:某类对象的引用;B:某个类

 检验A是否为类B的对象,返回值为boolean型。

1.要求A所属的类与类B必须是子类和父类的关系,否则编译错误

2.如果A属于类B的子类C, A instanceof C 值也为true.

下面看一段代码

class  shape{}
class square extends shape{}
class Circular()
public class demo{
public static void main(String[] args)
{
shape a=new shape();//四边形对象
square  s=new square();//正方形对象
System.out.println(a instanceof s);//判断四边形对象是否为正方形的子类
System.out.pritnln(s  instanceof  shape);//判断正方形是否为四边形的子类
{
{
false
true

向下类型转换 

 下面看一段代码

class Bird()
{
class Pigeon extends Bird{}
public class demo{
public static void main(String[] agrs)
{
Bird bird=new Pigeon();//某只鸽子是一只鸟
Pigeon pigeon=bird;//某只鸟是一只鸽子
}
}

此时编译会报错,但是如果想告诉编译器“某只鸟就是一只鸽子”,应该如何修正?答案就是强制类型转换。也就是说,要想实现向下转型,需要借助强制类型转换。语法如下:

子类类型  子类对象=(子类类型)父类对象;

因此我们可以将代码改为如下

Pigeon pigeon=(pigeon)bird; 

有了对象的多态性以后,由于变量声明为父类类型,导致只能调用父类中声明属性和方法,子类特有的属性和方法不能调用。

那么如何调用子类特有的属性和方法?来吧,展示!

public class student {
	  public void study() {
		  System.out.println("student");
	  }
}
public class studentA extends student//继承父类
{
	int age=10;
public void study()
{
	System.out.println("A");
}
public void unstudy(){
	System.out.println("A不想学习");
}
public static void main(String[] args)
{
	student A=new studentA();
	studentA B=(studentA)A;
	B.unstudy();
}
}

 写到这里,还差点意思哈哈,再来!

public class student {
	int age=20;
	  public void stage() {
		  System.out.println(this.age);
	  }
}
public class studentA extends student//继承父类
{
	int age=10;
public void stage()
{
	System.out.println(this.age);
}
public static void main(String[] args)
{
studentA A=new studentA();
System.out.println(A.age);//10
A.stage();//10
student B=A;
System.out.println(B==A);//true
System.out.println(B.age);//20
B.stage();//10
}
}

 运行后看到最后一个为10感觉有点懵,其实是多态性的理解啦,我们在调用的是子类重写的stage()方法,当然是放在子类那里去处理this咯!

学习如逆水行舟,不进则退。和小吴一起加油吧!

  • 39
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 50
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 50
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小吴有想法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值