【JavaSE】Java入门五(面向对象 2——继承)

目录

继承

1. 什么是继承

2.子类中访问父类成员的一些注意事项

3. 在继承关系中各种代码块的执行顺序

4.类与类之间的继承规则

5. final关键字

6.组合与继承


继承

前面我们知道Java中用类来对现实世界中的实体进行描述,类经过实例化后产生的对象可以用来表示现实中的对象,但是现实生活中事物之间可能存在一些关联,比如动物和猫,狗,为了更好的设计程序,面相对象中用继承来处理不同类之间的联系。

1. 什么是继承

继承机制:是面相对象程序设计实现代码复用最重要的手段,它允许程序员在保持原有结构特性的基础上进行扩展,增加新功能,从而产生新的类(派生类)。

Java中通过接口,抽象类和类来实现继承关系,本章主要介绍类与类之间的继承关系。

下面是类之间的继承语法:

修饰符 class 子类 extends 父类 {
// ...
}

下面是猫,狗继承动物类的代码实例:

// Animal.java
public class Animal{
String name;
int age;
public void eat(){
System.out.println(name + "正在吃饭");
}
public void sleep(){
System.out.println(name + "正在睡觉");
}
}
// Dog.java
public class Dog extends Animal{
void bark(){
System.out.println(name + "汪汪汪~~~");
}
}
// Cat.Java
public class Cat extends Animal{
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}
// TestExtend.java
public class TestExtend {
public static void main(String[] args) {
Dog dog = new Dog();
// dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
System.out.println(dog.name);
System.out.println(dog.age);
// dog访问的eat()和sleep()方法也是从Animal中继承下来的
dog.eat();
dog.sleep();
dog.bark();
}
}

子类完全继承父类的变量和方法,所以在子类实例化出的对象中也能使用父类的方法。

2.子类中访问父类成员的一些注意事项

  1. 父类中成员变量或成员方法的访问限定等级在protected及以上是可以直接被子类使用的。
  2. 子类的成员变量或者成员方法相同,则在使用时会优先使用子类的,如果子类没有在从父类中寻找。
  3. 如果子类变量跟父类变量相同还想访问父类变量可以使用super关键字,它的作用是在子类方法中访问父类的成员。

在上述代码中我们引入super可以写成:

// Dog.java
public class Dog extends Animal{
String name=super.name;
void bark(){
System.out.println(name + "汪汪汪~~~");
}
}
// Cat.Java
public class Cat extends Animal{
String name=super.name;
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}

super的使用我们需要注意:

1. 只能在非静态方法中使用

2. 在子类方法中,访问父类的成员变量和方法

3.必须是构造方法中的第一条并且不能和this同时存在。

3. 在继承关系中各种代码块的执行顺序

在上一篇文章中我们介绍了四种代码块,其中有一个经典问题就是比较在类里静态代码块,实例代码块,和构造方法在实例化时的执行顺序,其中静态代码块只在实例化第一个对象时执行,也是最先执行的,然后是实例代码块,最后在执行构造方法。

下面我们来看看在继承关系下这三种代码块的执行顺序:

class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person:构造方法执行");
}
{
System.out.println("Person:实例代码块执行");
}
static {
System.out.println("Person:静态代码块执行");
}
}
class Student extends Person{
public Student(String name,int age) {
super(name,age);
System.out.println("Student:构造方法执行");
}
{
System.out.println("Student:实例代码块执行");
}
static {
System.out.println("Student:静态代码块执行");
}
}
public class TestDemo4 {
public static void main(String[] args) {
Student student1 = new Student("张三",19);
System.out.println("===========================");
Student student2 = new Student("李四",20);
}
public static void main1(String[] args) {
Person person1 = new Person("张三",10);
System.out.println("============================");
Person person2 = new Person("李四",20);
}
}

执行结果如下:【JavaSE】Java入门五(面向对象 2——继承)_第1张图片

我们能发现依然是静态代码块先执行,从中我们还可以发现子类在实例化对象时,不仅子类构造方法会加载,父类构造方法也会被加载。 

4.类与类之间的继承规则

类与类之间的继承只有这三种关系:

不能一个类继承多个类

【JavaSE】Java入门五(面向对象 2——继承)_第2张图片

5. final关键字

final可以修饰变量,成员方法,和类

  1. 修饰变量,则此变量后续不能修改。
  2. 修饰方法,该方法不能被重写
  3. 修饰类,此类不能被继承。

什么是重写?

重写其实就是在子类中把父类本身有的方法重新写一遍。在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。为了方便辨认是否发生了重写,重写方法前要加上@Override以进行标识。

面试题:

重载与重写的区别?

答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。

6.组合与继承

 组合和继承都是Java中进行代码复用的一种表现形式,我们在进行程序设计时更鼓励使用组合的形式。

举一个例子来区分组合和继承:

我们需要定义一个奔驰类,继承的思维就是先定义一个汽车类,让奔驰继承汽车类,而组合的思维则是将汽车类更加细化,在定义多个零部件类,这些部件类就不仅仅可以被汽车类使用,还能在日后被手机类,飞机类等使用,提高了代码的复用性和维护性。

// 轮胎类
class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}
// 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}

你可能感兴趣的:(java,开发语言)