packagecom.lagou.task09;/**
*
*/publicclassShapeTest{//自定义成员方法实现将参数指定矩形对象特征打印出来的行为//也就是绘制图形的行为//Rect r = new Rect(1,2,3,4);//public static void draw(Rect r){// r.show(); // 1 2 3 4//}//自定义成员方法实现将参数指定圆形对象特征打印出来的行为//public static void draw(Circle c){ //重载// c.show(); // 1 2 3//}//自定义成员方法实现既能打印矩形对象又能打印圆形对象的特征//对象由参数传入,子类is a 父类//Shape r = new Rect(1,2,3,4);//Shape r = new Circle(1,2,3);//多态的使用场合之一,通过参数传递形成了多态publicstaticvoiddraw(Shape s){//重载// 父类类型的引用指向子类类型的对象,这就是多态//编译阶段调用父类的版本,运行阶段调用子类重写后的版本
s.show();// 1 2 3 4}publicstaticvoidmain(String[] args){//Rect r = new Rect(1,2,3,4);ShapeTest.draw(newRect(1,2,3,4));ShapeTest.draw(newCircle(1,2,3));}}
多态的特点------------------------------
当父类类型的引用指向子类类型的对象时
父类类型的引用可以直接调用父类独有的方法
父类类型的引用不可以直接调用子类独有的方法
对于父子类都有的非静态方法来说,编译阶段调用父类版本,运行阶段调用子类重写的版本(动态绑定)
对于父子类都有的静态方法来说,编译和运行阶段都调用父类的版本,即对于静态方法的调用只取决于变量类型
与指向什么的对象无关
引用数据类型之间转换的方式------------------------------
引用数据类型之间的转换方式有两种:自动类型转换和强制类型转换
自动类型转换主要指小类型向大类型的转换,也就是子类转为父类,也叫做向上转型
强制类型转换主要指大类型向小类型的转换,也就是父类转为子类,也叫做向下转型或显式类型转换
引用数据类型之间的转换必须发生在父子类之间,否则编译报错
若强转的目标类型并不是该引用真正指向的数据类型时,则编译通过,运行阶段发生类型转换错误
为避免上述错误的发生,应该在强转之前进行判断,格式如下:
if(引用变量 instanceof 数据类型)
判断引用变量指向的对象是否为后面的数据类型
对于引用的自动转换,与基本数据类型不同,基本数据类型实际上就是小到大自动转换,大到小强制转换
而引用类型在名称上是小到大自动转换,大到小强制转换,即子类自动转换为父类,父类必须要强制转换为子类
这是名称上的描述,具体情况请看下分析
//父类 fulei//子类 zilei//fulei fu = new fulei();//zilei zi = new zilei();//new fulei()会在堆区里,假设空间为1M//new zilei()由于继承了父类,那么自身的东西加上父类的东西,假设空间就分为1M+0.5M,其中0.5M是子类的//可以看成两个格子,父类一个,子类一个,父类格子在子类格子里面//看如下
fulei fu =newzilei();//由于new zilei()有两个格子,所以fu引用可以选择两个//但对于对象来说,类引用指向类的对象,那么他就会指向子类里的父类格子//即fu指向的是子类格子里的父类格子,即削弱版的zilei,因为他有父类的格子//所以相当于子类自动转换为父类--------------------------//再看如下
zilei zi =(zilei)fu
//由于对于对象来说,类引用指向类的对象,那么我们将fu的指向换个选择,即指向子类//因为我们已经指向了,要改指向,需要强制转换//所以相当于父类强制转换为子类-------------------------//当然无论怎么解释,最终都是规定好的,为了保证多态的-
packagecom.lagou.task09;/**
*
*/publicinterfaceInterfaceTest{//只有抽象方法(没方法体,弱化版的抽象类)和常量//接口主要用于抽象方法//由于类只可以单继承,虽然接口是弱化的抽象类,但可以让类多实现接口,由于抽象类被继承时,必须重写抽象方法,那么实现接口就必须重写所有的对应方法(因为都是抽象方法),而正是因为这样,所以导致他可以被多实现,因为基本都是使用自己的方法,而不是他的,所以这是一个特别的//int a = 0;//这里的a其实是常量,因为在接口里成员变量会变成常量//即默认加上了public static final//其中static和final可以互换位置//只不过他没有给你看到,隐式的变为常量了//public final int b = 0;//且必须要用final,因为必须要初始化//public final static int b = 0;//因为接口是抽象类的一种,比抽象类还要抽象//即接口是不能实例化,当我们需要用他的变量时,必须要用类名.的方式去使用//所以加上static//其中被static final修饰的变量称为常量//所以接口里面只能有常量//之所以抽象类没有这样,是因为他可以被继承,而接口只可被实现//所以接口必须要常量,而抽象类可以没有//private void show(){} //新特性:从jdk1.9(java9)开始允许接口出现私有方法//java8开始出现默认方法//也可以定义static方法//如static void fa(){}//如public default void fb(){}/*public abstract*/voidshow();//接口中的抽象方法不能有方法体//里面只能有抽象方法(新特性除外)//可以省略public和abstract但建议写上//protected和private不可修饰抽象方法,前者规定,后者也不可写(虽然需要方法体)//对于protected来说,可以被抽象方法修饰,但不可被接口的抽象方法修饰,这是规定的//对于private来说,因为使得他只可以在本类中使用,但接口要被实现,即被其他类使用//所以不可以用private修饰//具体情况也可以认为接口需要公开publicdefaultvoidfa(){System.out.println("换行");}publicdefaultvoidfa1(){//default默认方法,接口可以定义默认方法//用来调用私有方法的System.out.println("换行");bb();}privatevoidbb(){System.out.println("hh1");}publicstaticvoidfb(){System.out.println("换行");}publicstaticvoidfb1(){System.out.println("换行");cc();}privatestaticvoidcc(){System.out.println("hh1");}}