细品java封装继承多态
目录:
1.封装
2.继承
3.多态
1.封装
封装的作用:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
说成大白话就是防止别人更改你的变量
(2)访问修饰符:
一般修饰类的话只能是默认的default和public
1.private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类外部类(可以修饰内部类)
2.default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象类、接口、变量、方法。
3.protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类外部类(可以修饰内部类)
4.public : 对所有类可见。使用对象:类、接口、变量、方法
2.继承
(1)继承的定义
继承:就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
这里再声明一点,父类又称为超类或者基类。而子类又称为派生类,而且java只支持单继承不支持多继承这点很重要
(2)继承的优点:
1.提高代码的复用性。
2.类与类之间产生关系,为多态做了完美的铺垫
(3)继承格式
class A extends B{ }(4)继承后的成员变量重名问题
可以使用super和this来分别调用
如图:
这里注意一点不要在主函数里边直接用super.+方法名可能会报错,因为main是静态方法
(5)成员方法重名
方法重名大体也可以分两种情况:
1、方法名相同返回值类型、参数列表却不相同(优先在子类查找,没找到就去父类)
2、方法名、返回值类型、参数列表都相同,没错这就是重写(Override)
这里注意方法名相同不一定就是重写
重写的意义:
1、方法重写时, 方法名与形参列表必须一致。
2、子类方法覆盖父类方法时,必须要保证子类权限 >= 父类权限。
3、方法重写时,子类的返回值类型必须要 <= 父类的返回值类型。
4、方法重写时,子类抛出的异常类型要 <= 父类抛出的异常类型。
(6)继承之后的构造函数
构造方法的名字是与类名一致的,所以子类是无法继承父类构造方法的。
构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认会在第一句代码中添加super(),表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
当然我已经强调很多遍了 super() 不写也默认存在,而且只能是在第一句代码中,不在第一句代码中行不行,答案是当然不行
(7)继承后关于super和this
了解他们的用法之前必须明确一点的是父类空间优先于子类对象产在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构 造方法调用时,一定先调用父类的构造方法。
(7)类的每个构造方法中均有 默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
3.多态
(1)多态定义:
高级定义:
程序中定义的引用变量所指向具体的类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,就叫多态
简单定义:
多态指同一行为具有多种不同的表现形式
(2)多态三个前提:
继承或者实现【二选一】
1.方法的重写【意义体现:不重写,无意义】,子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
2.父类引用指向子类对象(也可以说向上转型)【体现在格式上】
(3)多态的体现:
多态体现的格式:
父类/父接口类型 变量名 = new 子类对象; 变量名.方法名()
当使用多态调用方法的时候首先检查父类中是否有该方法,如果没有则编译错误,如果有执行的是子类重写后的方法(重中之重)
子类单独定义方法丢失问题:
再来细品这一句话:
当使用多态调用方法的时候首先检查父类中是否有该方法,如果没有则编译错误,如果有执行的是子类重写后的方法
来看一道题:
这应该会打印什么:
有些聪明机智的童鞋已经想到了,那些边看博客边走神的童鞋还在那想
一部分童鞋已经饥渴难耐,迫不及待的回答这还不简单肯定打印“我要走回学校”
博主此时亮出来答案:
此时很多童鞋想垃圾博主写的什么垃圾结论还让我们看两遍
好了你们别嘀咕了且听我慢慢扯来:
首先这是爷子辈的引用指向子类对象,当爷子辈的引用调用方法的时候会先找自己的子类,其实子类B里边没有定义任何东西,所以那么这就是你们觉得是调用爷子辈fly的原因了吧
but别忘了继承啊,此时B里边是有fly方法的,从你爷爷那继承过来的,然后你爸爸还要找找自己的子类,发现你是它失散多年的儿子,它看看你有没有fly你要是有的话就调用你的(由于你连女朋友都没有所以你没有后代),如果你没有,你就继承你爸爸的一份,然后再调用你的,懂了伐。。。。。
(4).静态、动态绑定本质区别:
1、静态绑定是发生在编译阶段;而动态绑定是在运行阶段;
2、静态绑定使用的是类信息,而动态绑定使用的是对象信息
先看一个例子:
此时聪明的童鞋们都异口同声地回答这不就是简单多态吗,肯定会输出“我要飞回学校啊”
此时博主已经急了,感觉打断你们地思路悄悄地放出来答案
垃圾博主不看了,走走走兄弟们
哎哎哎再给我一次机会童鞋们
诶呀那么猴急干嘛,这不是给你们讲静态绑定呢吗,细看代码会发现父类和子类地方法中带了static这就是所谓地静态绑定,而以前不加地时候是动态绑定,再细细品味两者地区别,你就会发现其实静态绑定就是一开始就已经知道我要调用哪一个,因为程序还没运行,所以系统就默认只要是父类地引用就调用父类的方法,但是动态绑定就不一样了,动态绑定是在运行阶段绑定,运行到父类引用调用方法时会动态的去搜索子类有没有重写这个方法,然后决定执行哪一个这就是多态
还有一个地方需要补充:
重载是静态绑定,重写是静态绑定
(5)虚方法:
这垃圾博主有扯无大聊的(就是没有用的)
不不不这与多态息息相关
可以把java中被重写的方法称为虚方法
(6)向上向下转型(子类对象强制转换成父类对象时并没有丢失他原有的内存空间只是暂时不可以访问了所以可以再转回成子对象)
向上转型就是父类引用指向子类对象这个好理解
到这里,我们讲解一下为什么要向下转型,上面已经讲到过当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的麻烦。所以,想要调用子类特有的方法,必须做向下转型。
这个时候我们的向下转型就闪亮登场了
这样func()就可以被调用了
注意只能存在继承关系才能相互转型,如果是不同的两个类继承了同一个类那么这两个类是不能相互转型的。还有一种向下转型也不可取,就是一个父类的对象被强制转换成一个子类的时候(当然也转不成功),子类的引用是不能指向这个对象的,即子类引用不能指向父类对象
(7)instanceof的使用:
instanceof 运算符进行判断,左边是对象右边是类,当对象是类或者子类创建的对象时,返回true,否则返回false;
注意这里的的instanceof的格式,两边必须有继承关系,这是格式问题,如果左边的对象和右边的类毛线关系都没有那么编译器就会报错,也就是说只有左边是父类的对象右边是类的时候才会返回false
(8)多态与构造器之间的妙用
看段代码猜运行结果(又来这招垃圾博主打死不猜了,反正也猜不对)
好吧,博主就不卖关子了:
童鞋:就知道不按套路出牌,这垃圾博主
咳咳咳!!
好了别议论了
原因其实很简单,因为在创建子类对象时,会先去调用父类的构造器,而父类构造器中==又调用了被子类覆盖的多态方法==,
由于父类并不清楚子类对象中的属性值是什么(先初始化父类的时候还没开始初始化子类),
于是把String类型的属性暂时初始化为默认值null,
然后再调用子类的构造器(这个时子类构造器已经初始Weight属性,所以子类构造器知道熊孩子的体重Weight是250)。
好了我有点累了先休息一下
总结
以上是生活随笔为你收集整理的细品java封装继承多态的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 小朋友你是否对java中的static满
- 下一篇: java的final也并不是那么高冷