前言:继承从字面意思来说,也就是承接的意思,表示着它可以拥有被继承者的所有行为和属性,在java编程中,这种思想和面向对象中的继承意思大体相同,只要想搞清楚基本的概念,我想学起来也应该容易许多,然而多态对我们来讲就不是那么容易理解了,从字面意思来看,多态是多种状态的意思。例如,水可以是三种状态,液态,气态,固态。由此可以看出多态好像就是一对多,它是可以向外扩散的,然而又是它们的综合体,是不是很神奇,那咱们就在对它的学习中慢慢去发掘它。
必须要掌握的知识:继承的引入及用法
final关键字的引入及用法
多态的引用及理解
一.继承的引入及用法
继承的引入: 在编程的时候,我们通常会写很多类,往往会遇到两个类中有共同的内容,这样代码不仅看起来比较繁琐,而且占用了大量的内存空间,因此我们java就引出了一个关键字extends(继承),用来解决这种代码臃肿的问题。
继承的定义: 将多个类的共性内容,抽取为一个独立的类,只需要对这个独立的类和多个类产生一种关系:java提供继承
关键字:extands
格式: class 子类名 extends 父类名{
}
继承的基本框架:
class person{
private String name;
......
}
class Student extends person{
......
}
继承了父类所有的成员方法及属性(成员变量)
继承的好处:
1.提高了代码的复用性,简化了代码,让我们的代码不够臃肿
2.提高了代码的维护性
3.让类与类之间产生关系,是多态的前提,(多态的前提必须要有继承),要进行多态必须要有继承,没有继承何谈多态?
举例:
/*class Sudent{
public void study() {
System.out.println("学生喜欢学java");
}
}
class Teacher{
public void sleep() {
System.out.println("老师在讲java");
}
}
class Programmer{
public void work() {
System.out.println("程序员在敲代码");
}
}*/
/**以上的程序过于繁琐,所以我们运用继承来优化一下,运用继承的方法来实现代码的简化
* @author 田伟
*
*/
class person {
private String name;
public void study() {
System.out.println("学生在学习...");
}
public void sleep() {
System.out.println("老师在讲课");
}
public void work() {
System.out.println("程序员在codeing");
}
}
class Student extends person{
}
class programmer extends person{
}
class Teacher extends person{
}
public class ExtendsDome {
public static void main(String[] args) {
// 调用study方法,先创建对象,然后调用,其他以此类推
Student s=new Student();
s.study();
s.sleep();
s.work();
}
}
注释:类与类之间的关系: 类各类之间的关系:继承关系
类和接口之间的关系:实现关系(说到接口的时候就能够了解)
继承的特点: 1.子类继承父类,是继承了父类所有的东西(成元变量,成员方法,包括私有),但是子类不能使用私有的东西,只能通过间接的公共方法,让子类访问他
2.在java中,继承只支持单继承,不支持多继承(接口以同时实现多个接口,)但可以分层继承
当子类继承父类的时候,成员变量不一致的情况,分别输出就可以
子类不能继承父类的构造方法,但是可以通过super
注释:在这里提到super,让我们回想起以前学到的this,让我们对看它们的区别,进行了解
名称 | this | super |
代表 | 代表当前累的对象 | 代表父类空间标识,理解为父类的对象 |
成员变量 | this.成员变量 | super.成员变量 |
成员方法 | this.成员方法 | super.成员方法 |
构造方法 | this()/this(“..”) | super()/super("..") |
关于继承的问题:
重点: 子类继承父类,都会默认的访问父类的无参构造*******
原因: 假设数据没有被初始化完毕,所以应该让父类进行初始化,然后让子类初始化----》分层初始化
如果父类的无参构造没有提供,怎么办?三个方法解决: 1,在父类中建立一个无参构造
2,可以用super关键字去访问父类的带参结构、、、
3,还可以在子类中通过this访问本类中的无参参构造,接着在走一个super间接去访问父类带参结构。
注释:子类的构造方法必须有一个(有参构造/无参构造),让父类进行初始化,当子类成员方法名,和父类的成员方法名一样时,先在子类的成员位置找,在父类的成员位置找。、,否则报错
类名 对象名=new 类名();
这句话创建了对象,通过构造方法进行初始化(默认初始化,显示初始化)
注释:在继承中,如果子类有和父类一样的方法,但是不想进行继承,那么会引出方法重写,在这里我们会想到以前学过的方法重载,他们存在着什么关系,让我们进行一下对比。
方法重载(overload): 是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
方法重写(override): 子类定义一个类和父类一模一样的方法声明然后会将父类的方法覆盖掉
方法重载: 方法名一样,参数不同,和返回值没有关系
方法重写: 方法名一样,全修饰符一样,返回值一样
2参数类型不同
二. final关键字的引入及用法
final的引入: 有时候(具体需求)不需要子类重写父类的功能时,针对这种情况,java提供了关键字:final
final的作用: 表示最終的意思,他修饰一个类,该类不能被继承
还可以修饰一个方法,该方法不能被重写
还可以修饰成员变量,此时这个量为常量
final不仅可以修饰基本类型,还可以修饰引用类型
如果final修饰的是基本数据类型,基本数据的类型不能再改变了。。。
如果final修饰的是引用数据类型,引用类型的地址值不能再改变,但是堆内存中的成员变量的只可以改变
注释:切记必须在堆内存中才能够被改变。
举例:
/**
* 被final修饰的方法子类不能重写
* 被final修饰的变量,会变成一个常量
* 被final修饰的类,不能被继承
* @author 田伟
*
*/
class Fa{
int num1=10;
int num2=20;
public void method() {
System.out.println("父类方法");
}
// public final void show() {
// System.out.println("父类展示");
// }
public void fuction() {
num1=200;
System.out.println(num1);
}
}
class Son extends Fa{
public void show() {
System.out.println("我是你爸爸");
}
}
public class FinalDome {
public static void main(String[] args) {
Son s=new Son();
s.method();
s.show();
s.fuction();
}
}
现在总结一下继承: 感觉非常强大,既可以调用父类的也可以用自己的,而且节省了好多代码,美滋滋。
三.多态的引用及理解
多态:某一事物在同一时刻,体现出来的不同状态
*多态的一个前提*:1)必须有继承关系
2)必须有方法重写
3)必须要有父类的引用来指向对象(也叫向上转型)
多态中访问的特点 :
成员变量: 编译看左运行看左
成员方法: 编译看左运行看右
构造方法: 无论是子类还是父类都对方法进行初始化
静态方法: 编译看左运行看左
注释:前两点很重要。
多态的有点优点: 可以提高代码的复用性(继承保证)可以提高代码的扩展性(多态保证)
格式:父类对象的创建是通过子类在对新建了一个对象,由于子类又继承了父类,
Father f = new Son() ; 父类的引用指向子类对象 (向上转型);
可不可以将子类的引用指父类的引用呢? (向下转型)
将父类的引用强制转换子类的引用
son s=(son)f;(向下转型)
举例:
/**不同地方的饮食习惯问题
* @author 田伟
*
*/
class Person{
public void eat(){
System.out.println("吃饭");
}
}
//南方人
class South extends Person{
public void eat() {
System.out.println("南方人吃米饭");
}
public void playGome() {
System.out.println("南方人喜欢创造");
}
}
class North extends Person{
public void eat() {
System.out.println("北方人吃面条");
}
public void playGome() {
System.out.println("北方人喜欢钻研");
}
}
public class DuoTai {
public static void main(String[] args) {
Person p=new South();
p.eat();
South s=(South)p;
s.playGome();
}
}
注释:向下转型主要目的是编译出子类的特有功能;
父类的引用(初始化)通过子类新建 来进行的
多态的弊端:父类引用指向子类对象,通过父类的引用调用子类特有功能,不能调用....(不能访问子类特有功能)
解决方式: 使用强制转化父类的引用给子类
注释:不建议使用向下转型,因为这种方式容易出错,导致类转换异常,这里先不说异常的问题,我接下来会把见过的所有异常提取出来整理一下,我还是建议重新创建子类对象进行调用,或者使用子类匿名对象都可以(前者更好),除非你非常熟练。