这里写自定义目录标题
第12章 继承
01 练习
02 继承
Java中通过继承一个类,来继承此类的所有功能。
Java中的每一个类都继承于Object,当创建一个类时,会自动的继承Object类的所有方法。
例一
package com.day10;
class Foo {
}
public class Day102 {
public static void main(String[] args) {
Foo f = new Foo();
//toSring方法继承于Object
System.out.println(f.toString());
System.out.println(f.hashCode());
}
}
tips:
Ctrl + Shift + T --> open type
Object:
按Ctrl + o
找到toString方法
hashCode
例二
instanceof关键字用于判断一个对象是否是这个类型
例三
package com.day10;
class Foo {
}
public class Day102 {
public static void main(String[] args) {
Foo f = new Foo();
//toSring方法继承于Object
System.out.println(f.toString());
System.out.println(f.hashCode());
// //instanceof关键字用于判断一个对象是否是这个类型
// if(f instanceof Object) {
// System.out.println("Foo 继承于Ojbect");
// }
//f是Object类的实例
System.out.println(f instanceof Object); //true
//f是Foo类的实例
System.out.println(f instanceof Foo); //true
}
}
-------Console--------------
com.day10.Foo@1db9742
31168322
true
true
例四
package com.day10;
class Actor {
public void act() {
System.out.println("act");
}
}
//Hero继承于Actor
class Hero extends Actor {
public void fight() {
System.out.println("fight");
}
}
public class Day103 {
public static void main(String[] args) {
Hero h = new Hero();
//act方法继承于Actor
h.act();
//fight方法继承于自己
h.fight();
}
}
-------Console--------
act
fight
例五
Object类位于java.lang包中,它定义和实现了所有类的通用功能。
例子:
package com.day10;
//演员
class Actor {
public void act() {
System.out.println("act");
}
}
//英雄
//Hero继承于Actor
class Hero extends Actor {
public void fight() {
System.out.println("fight");
}
}
//喜剧演员
class Comedian extends Actor {
public void performComedy(){
System.out.println("comedy");
}
}
public class Day103 {
public static void main(String[] args) {
Hero h = new Hero();
//act方法继承于Actor
h.act();
//fight方法继承于自己
h.fight();
System.out.println(h instanceof Hero); //true
System.out.println(h instanceof Actor); //true
System.out.println(h instanceof Object);//true
Comedian c = new Comedian();
//act方法继承于Actor
c.act();
c.performComedy();
System.out.println(c instanceof Comedian);//true
System.out.println(c instanceof Actor); //true
System.out.println(c instanceof Object); //true
}
}
------Console-----
act
fight
true
true
true
act
comedy
true
true
true
例六
一个子类可以继承超类的所有public和protected成员(非静态成员,静态成员不考虑继承问题),不管子类在哪个包。
如果子类和超类在同一包下,它还可以继承其超类默认访问权限的成员。
private成员不能被继承。
操作步骤,实验:
在同一个包下(如:com.day10)中,
创建Animal类,Dog类,Day104主类,
如下:
- Animal类
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
}
2) Dog类
package com.day10;
public class Dog extends Animal {
}
3) Day104主类
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog();
// System.out.println(d.privateV);//编译错误
System.out.println(d.protectedV);
System.out.println(d.publicV);
System.out.println(d.defaultV);
}
}
***测试:
新建一个包(com.day101),把Dog类移动到其内,
此时,d.defaultV 报错。
***tips;
复制一行
Ctrl + Alt + up/down
例七
子类可以声明和超类同名的字段,这将导致隐藏其超类的字段。可以使用super关键字来访问超类的字段。
(超类的字段并不是没有了,而是被隐藏了)
1)Animal类
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
}
}
2) Dog类
package com.day10;
public class Dog extends Animal {
public int publicV;
public Dog(int publicV) {
this.publicV = publicV;
System.out.println(this.publicV);// 10
System.out.println(super.publicV);// 0
}
}
- 主类
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog(10);
// System.out.println(d.publicV);
}
}
例八
子类可以声明和超类同名的字段,这将导致隐藏其超类的字段。可以使用super关键字来访问超类的字段。
注意:
(1)隐藏不是覆盖,隐藏只是藏起来了。
(2)简单理解,super就是指的超类的对象。
在创建一个子类的对象的时候,首先会创建一个超类的对象。即,没有父,哪有子呀。
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
}
2)
package com.day10;
public class Dog extends Animal {
public int publicV;
public Dog(int publicV) {
this.publicV = publicV;
// System.out.println(this.publicV);// 10
// System.out.println(super.publicV);// 0
}
}
3)
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog(10);
System.out.println(d.publicV); //10
}
}
例九
例9.1
接上代码继续
1)给Animal一个构造器
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
public Animal() {
System.out.println("Animal");
}
}
2) Dog.java, Day104.java 代码不变;运行。
结果:
首先调用超类的构造器。
例9.2
- Animal.java 不变
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
public Animal() {
System.out.println("Animal");
}
}
2)给Dog.java中添加代码:
Dog d = new Dog(10);
如下:
package com.day10;
public class Dog extends Animal {
public int publicV;
public Dog(int publicV) {
System.out.println("Dog");
this.publicV = publicV;
}
}
3 ) 主函数不变。运行。
Animal
Dog
10
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog(10); //调Dog的构造器
System.out.println(d.publicV); //10
}
}
例十
构造器不是类的成员,因此无法被继承,但是子类可以调用超类的构造器。
1) Animal.java
给一个带参的构造器
Alt + Shift + s --> Generate Constructor using Fields
删掉super();
再加一个无参的构造器
Alt + shift + s -->Generate Constructor from Superclass…
- 子类 Dog.java
例十一
构造器不是类的成员,因此无法被继承,但是子类可以调用超类的构造器。
例11.1
1) Animal.java
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
public Animal() {
System.out.println("Animal无参构造器");
}
public Animal(int privateV, int protectedV, int publicV, int defaultV) {
System.out.println("Animal有参构造器");
this.privateV = privateV;
this.protectedV = protectedV;
this.publicV = publicV;
this.defaultV = defaultV;
}
}
2) Dog.java
package com.day10;
public class Dog extends Animal {
public int publicV;
public Dog(int publicV) {
System.out.println("Dog");
this.publicV = publicV;
}
}
3) 主方法
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog(10); //调Dog的构造器
System.out.println(d.publicV); //10
}
}
例11.2
- Animal.java 代码不变
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
public Animal() {
System.out.println("Animal无参构造器");
}
public Animal(int privateV, int protectedV, int publicV, int defaultV) {
System.out.println("Animal有参构造器");
this.privateV = privateV;
this.protectedV = protectedV;
this.publicV = publicV;
this.defaultV = defaultV;
}
}
2 ) Dog.java
package com.day10;
public class Dog extends Animal {
public int publicV;
public Dog(int publicV) {
// super();//调用超类无参构造器
super(1,2,3,4); //调用超类有参构造器
System.out.println("Dog");
this.publicV = publicV;
}
}
- 主方法
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog(10); //调Dog的构造器
System.out.println(d.publicV); //10
}
}
例十二
子类并不会继承超类的私有成员,但是子类可以调用超类的public或protected方法来访问超类的私有成员。
1) Animal.java
package com.day10;
public class Animal {
private int privateV;
protected int protectedV;
public int publicV;
int defaultV;
public int getPrivateV() {
return privateV;
}
public void setPrivateV(int privateV) {
this.privateV = privateV;
}
public Animal() {
System.out.println("Animal无参构造器");
}
public Animal(int privateV, int protectedV, int publicV, int defaultV) {
System.out.println("Animal有参构造器");
this.privateV = privateV;
this.protectedV = protectedV;
this.publicV = publicV;
this.defaultV = defaultV;
}
}
- Dog.java
package com.day10;
public class Dog extends Animal {
public int publicV;
public Dog(int publicV) {
// super();//调用超类无参构造器
super(1,2,3,4); //调用超类有参构造器
System.out.println("Dog");
this.publicV = publicV;
System.out.println(super.getPrivateV()); //1
}
}
不能访问私有变量,可以通过访问公开的方法来访问私有变量。
- 主方法
package com.day10;
public class Day104 {
public static void main(String[] args) {
Dog d = new Dog(10); //调Dog的构造器
System.out.println(d.publicV); //10
}
}
例十三
父类型的变量可以引用子类型的对象
13.1
13.2
由于Object类是所有类的超类,因此Object类的变量可以引用任何类的实例。
例十四
Java不允许多继承。
小结
一个子类可以继承超类的所有public和protected成员(非静态成员,静态成员不考虑继承问题),不管子类在哪个包。
如果子类和超类在同一包下,它还可以继承其超类默认访问权限的成员。
private成员不能被继承。
子类可以声明和超类同名的字段,这将导致隐藏其超类的字段。可以使用superd键字来访问超类的字段。
构造器不是类的成员,因此无法被继承,但是子类可以调用超类的构造器。
子类并不会继承超类的私有成员,但是子类可以调用超类的public或protected方法来访问超类的私有成员。
父类型的变量可以引用子类型的对象
由于Object类是所有类的超类,因此Object类的变量可以引用任何类的实例。
Java不允许多继承。
03 方法重写
子类可以创建和超类拥(REH)有同样签名的方法(方法签名包括方法名和参数列表),这叫做方法重写。
03.1
例1:
package com.day101;
class Animal {
public String say() {
return "不知道";
}
}
class Cat extends Animal {
public String say() {
return "喵喵喵";
}
}
public class Day107 {
public static void main(String[] args) {
Cat c = new Cat();
System.out.println(c.say());//喵喵喵
}
}
例2:
package com.day101;
class Animal {
public String say() {
return "不知道";
}
}
class Cat extends Animal {
// public String say() {
// return "喵喵喵";
// }
}
public class Day107 {
public static void main(String[] args) {
Cat c = new Cat();
System.out.println(c.say());
}
}
例3.3
子类重写的方法不能比超类拥有更小的访问权限。
如:
03.2 方法重写的规则
方法重写的规则:
1.子类只能重写它可见的方法。
被标记为static和final的方法不能被重写。
final方法不允许被重写
- 在重写的方法中可以使用super关键字来调用其超类的方法。
package com.day101;
class Animal {
public String say() {
return "不知道";
}
}
class Cat extends Animal {
public String say() {
System.out.println(super.say());// 不知道
return "喵喵喵";
}
}
public class Day107 {
public static void main(String[] args) {
Cat c = new Cat();
System.out.println(c.say());//喵喵喵
}
}
- 重写的方法要比超类的返回值类型小
(1) 例一:
package com.day101;
class Animal {
public String say() {
return "不知道";
}
public int getAge(){
return 1;
}
}
class Cat extends Animal {
public String say() {
System.out.println(super.say());// 不知道
return "喵喵喵";
}
public int getAge() {
return 1;
}
}
public class Day107 {
public static void main(String[] args) {
Cat c = new Cat();//创建两个对象
System.out.println(c.say());//喵喵喵
Cat c1 = new Cat();//创建两个对象
}
}
( 2 ) 例二
(3)***思考:
使用short,也报错。