网站首页 > java教程 正文
什么是继承
继承是面向对象的三大特征之一,是实现代码复用的重要手段。

Java的继承通过extends关键字实现,实现继承的类称为子类,被继承的类称为父类(或者基类、父类)。
继承的语法如下:
访问修饰符 class SubClass extends SuperClass{
//类定义部分
}
子类继承了父类,将获得父类的全部成员变量和方法,但是不能获得父类的构造器。
下面程序演示子类继承父类。
先定义一个父类:
/**
* Person类,作为父类
*/
public class Person {
?
String name;
?
int age;
?
public void eat() {
System.out.println("吃饭");
}
?
}
再定义一个子类,继承自上面已经定义好的父类:
/**
* Man子类,继承Person父类
*/
public class Man extends Person {
}
再定义一个测试类:
public class Test {
?
public static void main(String[] args) {
Man man = new Man();
?
// Man类本身并未定义name和age属性,但可以访问,说明Man继承了来自其父类的man和age属性
man.name = "Java";
man.age = 18;
?
// eat方法也继承自其父类
man.eat();
}
?
}
上面代码说明:当一个子类继承了一个父类,将获得父类的全部成员变量和方法。
做为子类,也可以有自己单独的成员变量和方法,其和父类构成了一般和特殊的关系。如,可以在上面的Man类添加自己的属性和方法:
/**
* Man子类,继承Person父类
* 添加自己的属性和方法,这样一样,这个类的对象就拥有了父类的成员变量、方法和自己类中的成员变量、方法
*/
public class Man extends Person {
boolean isRich;
?
public void earnMoney() {
System.out.printf("男人要赚钱");
}
}
Java的继承特点
在Java语言中,每个类只有一个直接父类,是单继承的。例如下面代码编译会报错:
class SubClass extends SuperClass1, SuperClass2,SuperClass3...
但是,可以有多个间接父类,如:
public class Man extends Person{...}
public class Person extends Creature{...}
上面代码中,Creature是Person的直接父类,是Man的间接父类。
如果定义一个类时,没有显式地声明其直接父类,则这个类默认继承自java.lang,Object类。Object类是所有类的父类,要么是直接父类,要么是间接父类。
方法的重写
子类扩展了父类,是父类的一个特殊实现。当从父类继承来的方法不满足子类时,可以重写父类的方法。
下面程序先定义了一个Bird父类如下:
/**
* Person类,作为父类
*/
public class Person {
public void eat() {
System.out.println("人吃饭");
}
?
}
下面再定义一个Man类,这个类扩展了Person类,重写了Person类的eat()方法。
/**
* Man子类,继承Person父类
*/
public class Man extends Person {
// 子类重写了父类的eat()方法
@Override
public void eat() {
System.out.println("男人要吃很多饭");
}
?
}
再写一个测试类:
public class Test {
?
public static void main(String[] args) {
Man man = new Man();
// 输出为:男人要吃很多饭
man.eat();
}
?
}
可以看到,程序执行的是Man类中的eat()方法,而不是Person类的eat()方法。
像上面这种子类和父类包含有相同名称、相同参数列表的现象被称为方法的重写(Override),也被称为方法的覆盖。可以说子类重写了父类的方法,也可以说父类的方法被子类覆盖了。
方法的重写要遵循”两同两小一大“规则,即:
- ”两同“:方法名相同,参数列表相同
- “两小”:子类方法返回值类型应比父类方法返回值类型小或相等,子类方法声明抛出的异常应比父类小或相等
- ”一大“:子类方法的访问权限应比父类的大或相等。
super关键字
前文提到,子类可以重写父类的方法。当子类覆盖了父类方法后,子类对象将无法访问父类被重写的方法,但可以通过super关键字在子类对象的方法中访问父类被重写的方法。
代码是这样的:
/**
* Man子类,继承Person父类
*/
public class Man extends Person {
?
@Override
public void eat() {
// 可以在子类的方法中调用父类被覆盖的方法
super.eat();
System.out.println("男人要吃很多饭");
}
?
}
?
如果子类定义了和父类同名的实例变量,则在子类实例方法中将无法访问父类的该变量,这是因为被子类实例同名的实例变量隐藏了,这时候可以通过super关键字来访问。如下代码所示。
class BaseClass{
public int a = 5;
}
?
public class SubClasss extends BaseClass{
public int a = 7;
public void accessSubVar() {
System.out.println(a);
}
public void accessBaseVar() {
System.out.print(super.a);
}
public static void main(String[] args) {
SubClasss s = new SubClasss();
s.accessSubVar(); // 输出7
s.accessBaseVar(); // 输出5
}
}
当程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为它从父类继承来的所有实例变量分配内存,即使子类定义了和父类同名的实例变量。也就是说,当系统创建一个Java对象时,如果该Java类有两个父类(一个直接父类A,一个间接父类B),假设A类中定义了2个实例变量,B类中定义了3个实例变量,自己子类中定义了2个实例变量,那么这个Java对象共有2+3+2个实例变量。
此外,super关键字还可以用来调用父类构造器。
class Base {
public double size;
public String name;
public Base(double size, String name) {
this.size = size;
this.name = name;
}
}
?
public class Sub extends Base {
public String color;
public Sub(double size, String name, String color) {
// 使用super关键字显式调用父类构造器
super(size, name);
this.color = color;
}
}
如果我们在子类构造器中未显式调用父类构造器,则会隐式调用父类无参数的构造器。
class Person {
?
public Person() {
System.out.println("父类构造器执行。。。");
}
?
}
?
public class Man extends Person {
?
public Man() {
System.out.println("子类构造器执行。。。");
}
public static void main(String[] args) {
// 执行Man类的构造器时,会先执行其父类的构造器
// 所以输出结果为:父类构造器执行。。。子类构造器执行。。。
Man man = new Man();
}
?
}
所以,调用子类构造器时,总是会先调用其父类的构造器,如果父类还继承自别的间接父类,则会依次往上追溯执行构造器。Object是所有类的父类,所以,构造任何Java对象时,总会先执行Object类的构造器。
猜你喜欢
- 2024-10-03 Java中的继承关系(java中的继承关系是)
- 2024-10-03 Java面向对象之继承(java面向对象继承例题)
- 2024-10-03 「Java入门」十八 面向对象的三大特征之一-继承
- 2024-10-03 [Java基础]09.继承(java基础案例教程第二版)
- 2024-10-03 Java中的继承、封装、多态 #Java开发
- 2024-10-03 Java中的继承与组合(java中继承的概念以及使用继承的好处)
- 2024-10-03 《极简Java新手编程之道》8.1.1 Java语言中实现继承
- 2024-10-03 Java:类与继承(java类与继承抽象类)
- 2024-10-03 Java基础——面对对象-继承(面对对象的特征有哪些方面java基本数据类型有哪些)
- 2024-10-03 你真的熟悉Java中的继承与多态?给你几分钟能回答上来?
欢迎 你 发表评论:
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)

本文暂时没有评论,来添加一个吧(●'◡'●)