java继承
继承概念
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是
子类继承父类的特征和行为
,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
类的继承格式
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
class
父类
{
}
class
子类
extends
父类
{
}
为什么需要继承
接下来我们通过实例来说明这个需求。
开发动物类,其中动物分别为企鹅以及老鼠,要求如下:
- 企鹅:属性(姓名,id),方法(吃,睡,自我介绍)
- 老鼠:属性(姓名,id),方法(吃,睡,自我介绍)
企鹅类:
public
class
Penguin
{
private
String
name
; //创建私有项
private
int
id
;
public
Penguin
(
String
myName
,
int
myid
)
{
//创建Penguin构造函数
name
=
myName
;
id
=
myid
;
}
public
void
eat
(){
System
.
out
.
println
(
name
+
"
正在吃
"
)
;
}
public
void
sleep
(){
System
.
out
.
println
(
name
+
"
正在睡
"
)
;
}
public
void
introduction
()
{
System
.
out
.
println
(
"
大家好!我是
"
+
id
+
"
号
"
+
name
+
"
.
"
)
;
}
}
老鼠类:
public
class
Mouse
{
private
String
name
;
private
int
id
;
public
Mouse
(
String
myName
,
int
myid
)
{
name
=
myName
;
id
=
myid
;
}
public
void
eat
(){
System
.
out
.
println
(
name
+
"
正在吃
"
)
;
}
public
void
sleep
(){
System
.
out
.
println
(
name
+
"
正在睡
"
)
;
}
public
void
introduction
()
{
System
.
out
.
println
(
"
大家好!我是
"
+
id
+
"
号
"
+
name
+
"
.
"
)
;
}
}
从这两段代码可以看出来,代码存在重复了,导致后果就是代码量大且臃肿,而且维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错),所以
要从根本上解决这两段代码
重复
的问题,就需要继承,将两段代码中相同的部分提取出来组成 一个父类
:
公共父类:
public
class
Animal
{
private
String
name
;
private
int
id
;
public
Animal
(
String
myName
,
int
myid
)
{
name
=
myName
;
id
=
myid
;
}
public
void
eat
(){
System
.
out
.
println
(
name
+
"
正在吃
"
)
;
}
public
void
sleep
(){
System
.
out
.
println
(
name
+
"
正在睡
"
)
;
}
public
void
introduction
()
{
System
.
out
.
println
(
"
大家好!我是
"
+
id
+
"
号
"
+
name
+
"
.
"
)
;
}
}
这个Animal类就可以作为一个父类,然后企鹅类和老鼠类继承这个类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码) 继承之后的代码:
企鹅类:
public
class
Penguin
extends
Animal
{
public
Penguin
(
String
myName
,
int
myid
)
{
super
(
myName
,
myid
)
;
}
}
老鼠类:
public
class
Mouse
extends
Animal
{
public
Mouse
(
String
myName
,
int
myid
)
{
super
(
myName
,
myid
)
;
}
}
继承的特性
- 子类拥有父类非private的属性,方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展,这样减少了编程量。
- 子类可以用自己的方式实现父类的方法。
- Java的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这是java继承区别于C++继承的一个特性。
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
- 继承是多态的基础之一。
继承关键字
继承可以使用
extends
和
implements
这两个关键字来实现继承,而且所有的类都是继承于
java.lang.Object
,当一个类没有继承的两个关键字,则默认继承object(这个类在
java.lang
包中,所以不需要
import
)祖先类。
extends关键字
在 Java 中,类的继承是
单一继承
,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
extends 关键字
public
class
Animal
{
private
String
name
;
private
int
id
;
public
Animal
(
String
myName
,
String
myid
)
{
//初始化属性值
}
public
void
eat
()
{
//吃东西方法的具体实现
}
public
void
sleep
()
{
//睡觉方法的具体实现
}
}
public
class
Penguin
extends
Animal
{
}
implements关键字
使用 implements 关键字可以变相的使java具有
多继承
的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
implements 关键字
public
interface
A
{
public
void
eat
()
;
public
void
sleep
()
;
}
public
interface
B
{
public
void
show
()
;
}
public
class
C
implements
A
,
B
{
}
super 与 this 关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,
用来引用当前对象的父类
。
this关键字:
指向自己的引用
。
实例
class
Animal
{
void
eat
()
{
System
.
out
.
println
(
"
animal : eat
"
)
;
}
}
class
Dog
extends
Animal
{
void
eat
()
{
System
.
out
.
println
(
"
dog : eat
"
)
;
}
void
eatTest
()
{
this
.
eat
()
;
// this 调用自己的方法
super
.
eat
()
;
// super 调用父类方法
}
}
public
class
Test
{
public
static
void
main
(
String
[]
args
)
{
Animal
a
=
new
Animal
()
;
a
.
eat
()
;
Dog
d
=
new
Dog
()
;
d
.
eatTest
()
;
}
}
输出结果为:
animal : eatdog : eatanimal : eat
final关键字
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,
该方法不能被子类重写
:
- 声明类:
final class 类名 {//类体}
- 声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
注
:
实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final
访问修饰符
访问修饰符常用的关键字有三个:
private(私有)、
public(公共)、
protected(保护),还有一个就是默认的修饰符
default。他们既可以修饰属性,也可以修饰方法。
- private
只有该类可以访问
- protected
该类及其子类的成员可以访问,同一个包中的类也可以访问
- public
该类或非该类均可进行访问
- 默认
相同数据包中的类可以访问
构造器
子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过
super
关键字调用父类的构造器并配以适当的参数列表。
如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
实例
class
SuperClass
{
private
int
n
;
SuperClass
(){
System
.
out
.
println
(
"
SuperClass()
"
)
;
}
SuperClass
(
int
n
)
{
System
.
out
.
println
(
"
SuperClass(int n)
"
)
;
this
.
n
=
n
;
}
}
class
SubClass
extends
SuperClass
{
private
int
n
;
SubClass
(){
super
(
300
)
;
System
.
out
.
println
(
"
SubClass
"
)
;
}
public
SubClass
(
int
n
){
System
.
out
.
println
(
"
SubClass(int n):
"
+
n
)
;
this
.
n
=
n
;
}
}
public
class
TestSuperSub
{
public
static
void
main
(
String
args
[]){
SubClass
sc
=
new
SubClass
()
;
SubClass
sc2
=
new
SubClass
(
200
)
;
}
}
输出结果为:
SuperClass(int n)SubClassSuperClass()SubClass(int n):200
构造器的执行顺序?
每个类在构建对象时,都会调用父类构造器,先构建父类对象;
每个类在构建对象时,都会先调用父类构造器,构建父类对象,如果父类还有父类,那么会先调用爷爷类的构造器,,,一直到object。
查看代码块的执行顺序:
class Demo{
{
System.out.println("block-2");
}
Demo(){
System.out.println("Constructor");
}
{
System.out.println("block-1");
}
static{
System.out.println("static block-1");
}
static{
System.out.println("static block-2");
}
}
public class BlockDemo{
public static void main(String[] args){
Demo d1 = new Demo();
Demo d2 = new Demo();
}
}
代码块执行顺序:
static block-1
static block-2
block-2
block-1
Constructor
block-2
block-1
Constructor
在《Think in java》中有这样一句话:复用代码是Java众多引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情。在这句话中最引人注目的是“复用代码”,尽可能的复用代码使我们程序员一直在追求的,现在我来介绍一种复用代码的方式,也是java三大特性之一---继承。
继承
从这里我们可以看出,Wife、Husband两个类除了各自的husband、wife外其余部分全部相同,作为一个想最大限度实现复用代码的我们是不能够忍受这样的重复代码,如果再来一个小三、小四、小五……(扯远了
)我们是不是也要这样写呢?那么我们如何来实现这些类的可复用呢?
利用继承!!
首先我们先离开软件编程的世界,从常识中我们知道丈夫、妻子、小三、小四…,他们都是人,而且都有一些共性,有名字、年龄、性别、头等等,而且他们都能够吃东西、走路、说话等等共同的行为,所以从这里我们可以发现他们都拥有人的属性和行为,同时也是从人那里继承来的这些属性和行为的。
从上面我们就可以基本了解了继承的概念了,
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。
通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。
对于Wife、Husband使用继承后,除了代码量的减少我们还能够非常明显的看到他们的关系。
继承所描述的是“is-a”的关系,如果有两个对象A和B,若可以描述为“A是B”,则可以表示A继承B,其中B是被继承者称之为父类或者超类,A是继承者称之为子类或者派生类。
实际上继承者是被继承者的特殊化,它除了拥有被继承者的特性外,还拥有自己独有得特性。例如猫有抓老鼠、爬树等其他动物没有的特性。同时在继承关系中,继承者完全可以替换被继承者,反之则不可以,例如我们可以说猫是动物,但不能说动物是猫就是这个道理,其实对于这个我们将其称之为“向上转型”,
下面介绍
。
诚然,
继承定义了类如何相互关联,共享特性
。对于若干个相同或者相识的类,我们可以抽象出他们共有的行为或者属相并将其定义成一个父类或者超类,然后用这些类继承该父类,他们不仅可以拥有父类的属性、方法还可以定义自己独有的属性或者方法。
同时在使用继承时需要记住三句话:
1、子类拥有父类非private的属性和方法。
2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
3、子类可以用自己的方式实现父类的方法。
(
以后介绍
)。
综上所述,使用继承确实有许多的优点,除了将所有子类的共同属性放入父类,实现代码共享,避免重复外,还可以使得修改扩展继承而来的实现比较简单。
诚然,讲到继承一定少不了这三个东西:构造器、protected关键字、向上转型。
构造器
通过前面我们知道子类可以继承父类的属性和方法,除了那些private的外还有一样是子类继承不了的---构造器。对于
构造器而言,它只能够被调用,而不能被继承
。 调用父类的构造方法我们使用super()即可。
对于子类而已,其构造器的正确初始化是非常重要的,而且当且仅当只有一个方法可以保证这点:在构造器中调用父类构造器来完成初始化,而父类构造器具有执行父类初始化所需要的所有知识和能力。
public
class
Person {
protected
String name;
protected
int
age;
protected
String sex; Person(){ System.out.println("Person Constrctor..."); }}
public
class
Husband
extends
Person{
private
Wife wife; Husband(){ System.out.println("Husband Constructor..."); }
public
static
void
main(String[] args) { Husband husband =
new
Husband(); }}Output:Person Constrctor...Husband Constructor...