@Tean
2016-03-02T12:44:48.000000Z
字数 3982
阅读 1472
Java
- 重点掌握继承
- 重点掌握super关键字
- 重点掌握访问权限
- 重点掌握方法重写
案例:Person类具有age和name属性,Student类也具有age和name属性,此外还具有sno属性。他们有共同的属性age和name,这种情况下如果把相同的属性在Student中重写一遍就是一种代码重复。
public class Person {private String name;private int age;}public class Student {private String name;private int age;private int sno; // 学生编号}
继承是java面向对象的三大特征(
继承、封装、多态)之一,是软件复用的重要手段之一。上述案例情况就可以用继承解决。
- 一个类继承另一个类。实现继承的类称为
子类也叫派生类,而被继承的类称为父类,也叫超类或基类。- 通过“继承”一个现有的类,可以在子类中使用被继承的的类(父类)中的属性和方法。
- 类的方法和属性可以被继承,但是类的构造器(构造方法)不能被继承。
- 假如两个类有相同的属性和方法,那么就可以创建一个具有他们共同属性和方法的类作为父类,让子类来实现该父类,根据实际业务需求来添加新的属性和方法。
Java中实现继承用关键字
extends
[修饰符] class 子类 extends 父类 {// 类中代码}
在Java中一个类只能有一个直接父类,即:java只支持单继承(亲爹只能有一个。干爹可以有多个,学习接口时会学到),不支持多继承。
- 子类可以访问父类中
非私有的成员变量和方法。- Java只支持单继承不支持多继承:一个类最多只能有一个直接父类。
public class Sub extends Super { // OK的}public class Sub extends Super1, Super2 { // 错误的,不支持多继承}
- Java支持多层继承(继承体系)。B继承A,C可以再继承B,例如:
public class A { }public class B extends A { }public class C extends B { }
- 一个子类只能有一个亲爹。一个类可以有多个子类。
使用super可以调用父类的成分:父类的成员变量、父类的方法、父类的构造方法。
注意:使用super关键字和this关键字,均不能用在静态方法中,只能用在普通方法(实例方法)中。
语法格式:
super.父类变量名
public class Parent {public int age = 23;}public class Son extends Parent {public void test() {System.out.println(super.age); // 调用父类age}}
注意:不能调用父类私有(private修饰的)的变量。
语法格式:
super.父类方法名()
public class Parent {public void haha() {System.out.println("Parent");}}public class Son extends Parent {public void test() {super.haha() // 调用父类haha()方法}}
注意:不能调用父类私有(private修饰的)的方法
- 两者均不能在static修饰的方法中使用。
- 在用在构造方法中的时候,两者均需要放在构造方法的第一行,所以二者不可同时使用。
| No. | 比较点 | this | super |
|---|---|---|---|
| 1 | 访问属性 | 首先在子类中查找,如果没有就在 父类中查找 | 直接查找父类 |
| 2 | 访问方法 | 先在子类在中找,如果没有就去父类中查找 | 直接访问父类中方法 |
| 3 | 调用构造方法 | 调用本类中的其他构造方法 | 调用父类的构造方法 |
| 4 | 特殊 | 指自身的对象 | 没有概念 |
| 5 | 作为参数 | 可以作为参数 | 没有此用法 |
- 由于子类和父类的类名(包括包名)肯定不同,而构造方法的名字必须和类名一致,所以构造方法不能继承。
- 创建子类对象时,子类会继承父类的一些元素,所以子类会先访问父类的构造方法。
- 当new子类对象时会先调用父类的构造方法,再调用自己的构造方法。
public class Test {public static void main(String[] args) {B b = new B();}}class A {public A() {System.out.prinltn("父类构造方法");}}class B extends A {public B() {System.out.println("子类构造方法");}}
上述输出结果为:
父类构造方法子类构造方法
子类实例化时,必须首先调用父类的构造方法,然后才是子类的构造方法。若子类中没有显示的调用父类构造方法,则默认情况调用的为父类的无参构造方法。若此时父类没有无参构造方法,则程序编译出错, 如下列程序:
class A {public A(int num) {System.out.prinltn("父类有参构造方法");}}class B extends A {public B() {System.out.println("子类构造方法");}}
- 有时,需要在子类的构造方法中来调用父类的某个特定的构造方法。
- 语法:
super(实参);
- super()调用父类构造方法时,必须是子类该构造方法的第一行代码。
- super();只能出现在子类的构造方法中。
- 实参可以为空,当实参为空时表示调用的是父类的无参构造方法,此时与省略super()效果相同.
Java中共四种权限修饰符:
private、protected、default(什么都不写,也叫friendly或package)、public。

- public:任何包中的类都可以访问该类
- 默认值:同一个包中的类可以访问该类
- public:对一切类可见
- 默认值:对同一包中的类可见
- protected:对所有子类和同一包中的类可见
- private:只对本身类可见
注意:访问成员的前提是首先能访问成员所属的类。
由于父类中的方法功能过于简单,或者不适用于子类,这种情况需要对父类方法在子类中重写。
例如:Animal中speak方法,输出为“我是一个动物”, Cat是Animal的子类,这时如果直接调用父类的方法就有点不太合适,就需要在子类中重写speak方法。
public class Animal {public void speak() {System.out.println("我是一个动物");}}public class Cat extends Animal {@Overridepublic void speak() {System.out.println("我是一只猫");}}
- 方法覆写遵循规则:两同两小一大
- 两同: 方法名相同、参数列表相同
- 两小:
- 被重写的方法在子类中的返回值类型的范围比父类小或者与父类相同。
- 被覆盖的方法在子类中抛出的异常范围比父类小或者与父类相同(异常后续会讲)
- 一大:被覆盖的方法在子类中访问控制权限比父类的大或者相等。
提示:
1. 可以在方法上加@Override测试是否是重写的方法,如果不是,加了@Override后编译会出错
2. 在Eclipse中可以观察方法前面是否是绿色三角箭头,如果有代表是重写的方法。
| No. | 比较点 | 重载 | 重写 |
|---|---|---|---|
| 1 | 单词 | Overload | Override |
| 2 | 方法的声明 | 方法名相同,参数列表不同 | 方法名相同,参数列表相同 |
| 3 | 返回值 | 没有要求 | 返回值必须相同或者子类 |
| 4 | 访问权限 | 没有要求 | 子类不能比父类更加严格 |
| 5 | 范围 | 同一个类中 | 继承关系中 |
在有些情况下,我们不希望我们的定义的某个类被子类继承,或者某个类中某个方法不希望在子类中被覆写,就需要用到
final关键字如果final修饰某个类,则该类变成”终类”,不能被任何类继承,如:
public final class Cat { // 则该类不能被任何类继承}
如果用final修饰某个方法,则该方法不能被重写。
public class Cat{public final void speak() { //则该方法不能在子类中被重写}}
另外:final也可以修饰变量。当final修饰变量时,则该变量只能被赋一次,则该变量就变成常量。
public class MyMath {public final double PI = 3.1415926; // 该变量的值不能改变。}
- 创建父类Animal,拥有属性name,age,创建子类Dog,子类Cat,并实例化子类。
- 创建具有继承结构的两个类,在子类中使用super调用父类中的非构造函数的成员函数。
- 创建具有继承结构的两个类,父类中有一个拥有1个参数的构造函数,在子类中的无参数构造函数中使用super调用父类中的构造函数,并判断两个构造函数运行的先后顺序。
- 创建拥有继承结构的两个类,两个类拥有相同定义的display()方法,但是方法体中的内容不同,分别创建一个父类对象和子类对象,分别调用display()方法,观察结果。
- 定义一个人类,包括属性:姓名、性别、年龄、国籍;包括方法:吃饭、睡觉、工作。
- 根据人类,派生一个学生类,增加属性:学校、学号;重写工作方法(学生的工作是学习)。
- 根据人类,派生一个工人类,增加属性:单位、工龄;重写工作方法(工人的工作是...自己想吧)。
- 根据学生类,派生出学生干部类,增加属性:职务;增加方法:开会。
- 创建Test测试类,编写主函数,分别对上述3类具体任务进行测试。