JavaSE个人学习心得(九)
继承
让类与类之间产生关系(字符类关系),子类就可以使用父类中[非私有成员]
怎样产生继承
通过 extends 关键字
public class 子类 extends 父类 {}
public class Zi extends Fu {}
Zi : 子类(派生类)
Fu : 父类(基类, 超类)
- 好处:
1.提高了代码的复用性
2.提高了代码的维护性
3.是多态的前提 - 弊端:
耦合性增强了(即类与类之间的关系太紧密了)
什么时候使用继承?
当发现多个类之间存在共性内容, 并且还产生了一种 is…a 的关系, 就可以考虑使用继承来优化代码is…a : 谁是谁的一种
学生, 老师 —> 人
苹果, 香蕉 —> 水果
程序员, 项目经理 --> 员工
继承中成员访问特点 - 成员变量
- 问题 : 当字符父中,出现了重名的成员变量,在使用的时候,优先使用?
根据就近原则,优先使用子类的成员变量
- 问题 : 如何调用父类中的成员变量
使用super关键字来调用
例
class Fu {
String name = "建麟";
}
class Zi extends Fu {
String name = "四葱";
public void method(){
String name = "五葱";
System.out.println(name); // 五葱
System.out.println(this.name); // 四葱
System.out.println(super.name); // 建麟
}
}
继承中成员访问特点 - 成员方法
- 问题 : 子类继承父类之后,子类是否可以自己继续定义新方法
可以
- 子父类中,出现了重名的成员方法,在调用的时候使用的是谁的方法
子类,若要使用父类的,使用super关键字
- 方法重写
介绍: 在继承体系中, 出现了方法声明一模一样的方法(方法名, 参数列表, 返回值类型) 不同的只有内部逻辑
- 子类重写父类中方法时需要注意些什么
父类中private修饰的方法,不能重写
子类重写父类方法时,访问权限需要大于父类的访问权限
权限修饰符
- private : 同一个类中
- (default) : 同一个类中, 同一个包中
- protected : 同一个类中, 同一个包中, 不同包下的子类
- public : 任意位置
继承中成员的访问特点 - 构造方法
- 问题 :子类是否可以继承到父类中的构造方法
不能继承, 因为构造方法要求方法名, 必须跟类名保持一致, 如果子类继承到父类的方法, 就无法保证一致了
class Fu {
public Fu(){}
}class Zi extends Fu {
public Fu(){ // 名字无法保持一致}
}结论: 构造方法, 不能被继承, 子类需要自己手动编写
- 问题 : 子类在初始化之前,是否需要先完成父类的初始化
需要先完成父类初始化
原因: 因为子类在初始化的时候, 很有可能使用到父类中的数据, 如果父类没有提前完成初始化, 子类将无法使用数据.
class Fu {
int num = 10;
}class Zi extends Fu {
public Zi(){
System.out.println(super.num);
}
}
- 问题:子类是如何完成父类的初始化
细节问题: 初始化一个对象, 要执行什么方法?
回答: 构造方法!
线索: 子类只要有办法访问到父类的构造方法, 就能够完成父类数据的初始化操作.在所有子类的构造方法中, 都默认隐藏了一句话 super();
通过这句话去访问父类的空参数构造方法.
- 问题:如果父类没有空参构造方法,怎么办
父类没有空参构造方法, 肯定有带参构造方法
只需要手动指挥 super(10); 访问父类的带参构造即可
class Person {
String name;
int age;
public Person(){}
public Person(String name, int age){
this.name = name;
this.age = age;
}
...
}
class Student extends Pereon {
int score;
public Student(){
super();
}
public Student(String name, int age, int score){
// 前两个数据, 父类有, 交给父类初始化
super(name, age);
// 第三个数据, 父类没有, 自己有, 自己完成初始化
this.score = score;
}
}
Student stu = new Student("张三", 23, 100);
继承的特点
Java只支持单继承,不支持多继承,但支持多层继承
多层继承:
class A {}
class B extends A {}
class C extends B {}
final关键字
- final 是一个修饰符, 表示最终的意思, 可以修饰 (方法, 类, 变量)
- 方法 : 被final修饰的方法, 不能被重写
- 类 : 被final修饰的类, 不能被继承 (不能有子类, 但是可以有父类)
- 变量 : 只能被赋值一次
- 基本数据类型 : 数据值不可改变
- 引用数据类型 : 地址值不可改变
- 成员变量 :
- 要么在定义的时候, 直接赋值
- 要么在构造方法结束之前, 完成赋值
- 建议 :
- final 修饰的变量, 就变成了常量, 常量有自己的命名规范
- 如果是一个单词 : 所有字母大写 NUM PI
- 如果是多个单词 : 所有字母大写, 中间使用_分割 MAX_VALUE MIN_VALUE
- final 修饰的变量, 就变成了常量, 常量有自己的命名规范
抽象类
- 什么是抽象类
抽象类就是一个特殊的父类, 跟普通父类的不同之处, 在于可以定义抽象方法.
- 什么是抽象方法
将共性的行为(方法), 抽取到父类之后, 发现这个行为在父类中无法给出具体明确(描述不清了)
这种方法, 就可以定义为抽象方法
特点: 强制要求子类重写!
- 抽象类和抽象方法的定义格式
抽象方法 :
public abstract void eat();
抽象类:
public abstract class Animal{}
抽象类的注意事项
- 抽象类不能实例化 (不能创建对象)
- 抽象类中可以没有抽象方法, 但是有抽象方法的类, 一定是抽象类
- 抽象类中有构造方法
- 抽象类的子类
- 要么重写所有抽象方法 (推荐)
- 要么将自己变成抽象类 (不太推荐)
abstract关键字的冲突问题
final : abstract修饰的方法, 强制要求子类重写, final修饰的方法, 子类不能重写
private : abstract修饰的方法, 强制要求子类重写, privae 修饰的方法, 子类不能重写
接口
接口体现的就是对规则的声明
如果发现一个类中, 所有的方法, 都是抽象方法, 那么这个类的唯一价值, 就只是在声明规则.
对于这种类, 通常会改写为 Java 中的接口
public interface A {
public abstract void method1();
public abstract void method2();
}
定义格式:
public interface 接口名 {}
-
使用接口的细节
1.接口不能实力化(不能创建对象)
接口既然不能创建对象,注意力就要集中到接口的实现类(子类) -
类实现接口
-
public 类名 implements 接口名 {}
public AImpl implements A {
public void method1(){
}
public void method2(){
}
}
接口的实现类 :
* 重写所有的抽象方法
* 要么将实现类变成抽象类 (不推荐)
接口中成员特点
- 成员变量 :
- 只能是常量, 因为默认被三个关键字修饰
- public static final
- 这三个关键字, 没有顺序关系
- 成员方法 :
- 只能是抽象方法, 因为默认被两个关键字修饰
- public abstract
- 构造方法 :
- 没有
接口和类之间的各种关系
- 类与类 : 继承关系
- 只支持单继承, 不支持多继承, 但是可以多层继承
- 类和接口 : 实现关系
- 可以单实现, 也可以多实现, 还可以在继承一个类的同时, 实现多个接口
- 接口和接口 : 继承关系
- 可以单继承, 也可多继承