继承,字面意思就是继续、承接。在人类生活中,后代可以继承父代或者祖先留下来的遗产等,皇权的继承等。因此继承可以在一定程度上让我们一开始就拥有一些东西,同时呢,一个人也只有一个生父。因此在JAVA中,继承的关系也是如此。
继承的概念 | 继承的好处 | 结构 |
---|---|---|
继承是类与类的一种关系,是一种包含关系或者说是一种“is a”的关系。 在继承中被继承的类称为父类或者基类,继承而来的类称为子类。 在JAVA中存在一个Object类,这是所有类的父类。 JAVA中的继承属于单继承,只能继承一个父类 |
1.子类可以拥有父类所有的属性和方法(private修饰属性除外) 2.可以实现代码复用 |
class 子类 extends 父类 class A extends B{ …} |
注:JAVA中的继承是单继承
子类拥有父类的所有属性和方法(非private)实现代码复用
父类Animal.java
package com.template11;
public class Animal {
public int age;
public String name;
public void eat(){
System.out.println("动物具有吃东西的能力");
}
}
子类Dog.java
package com.template11;
public class Animal {
public int age;
public String name;
public void eat(){
System.out.println("动物具有吃东西的能力");
}
}
初始化Initial.java
package com.template11;
public class Initial {
public static void main(String[] args){
//创建dog对象并调用dog属性
//dog所有属性和方法都是从父类Animal继承而来
Dog dog = new Dog();
dog.age = 10;
dog.name = "Quanhao Guo";
//调用dog方法
dog.eat();
System.out.println(dog.age);
System.out.println(dog.name);
}
}
动物具有吃东西的能力
10
Quanhao Guo
方法的重写 | 继承的初始化顺序 |
---|---|
1.如果子类对继承父类的方法不满意,可以重写父类继承的方法,当调用方法时会优先调用子类的方法。 2.定义的方法中在返回值类型、方法名、参数类型及个数都要与父类继承的方法相同,才叫方法的重写。 3.调用方法时会优先调用子类的方法 |
初始化父类→初始化子类 执行初始化对象中属性→执行构造方法中的初始化 |
重写调用示例
Animal.java
package com.template11;
public class Animal {
public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
age = 100;
System.out.println("Animal类执行了");
}
}
Dog.java
package com.template11;
public class Dog extends Animal {
//重写eat()方法
public void eat(){
System.out.println("狗具有吃东西的能力");
}
}
狗具有吃东西的能力
10
Quanhao Guo
初始化顺序示例
Animal.java
package com.template11;
public class Animal {
public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
age = 100;
System.out.println("Animal类执行了");
}
}
Dog.java
package com.template11;
public class Dog extends Animal {
//重写eat()方法
public void eat(){
System.out.println("狗具有吃东西的能力");
}
//重写无参构造方法
public Dog(){
System.out.println("Dog类执行了");
}
}
Initial.java
package com.template11;
public class Initial {
public static void main(String[] args){
Animal animal = new Animal();
System.out.println("animal age:" + animal.age);
//创建dog对象并调用dog属性
//dog所有属性和方法都是从父类Animal继承而来
Dog dog = new Dog();
dog.age = 10;
dog.name = "Quanhao Guo";
//调用dog方法
dog.eat();
System.out.println(dog.age);
System.out.println(dog.name);
}
}
Animal类执行了
animal age:100
Animal类执行了
Dog类执行了
狗具有吃东西的能力
10
Quanhao Guo
final 关键字 |
---|
使用final关键字做标识符有”最终的“含义 |
final 可以修饰类、方法、属性和变量 |
final 修饰类,则该类不允许被继承 |
final 修饰方法,则该方法不允许被覆盖(重写) |
final 修饰属性,则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值(但只能选其一,因为不能多次赋值) |
final 修饰变量,则该变量的值只能赋一次值,即变为常量 |
使用final关键字修饰后的父类Animal不能被继承示例
Animal.java
package com.template12;
final public class Animal {
public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
age = 100;
System.out.println("Animal类执行了");
}
}
被final修饰的的方法不能被重写示例
Animal.java
package com.template12;
public class Animal {
public int age = 10;
public String name;
final public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
age = 100;
System.out.println("Animal类执行了");
}
}
Animal.java
package com.template12;
public class Animal {
final public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
age = 100;
System.out.println("Animal类执行了");
}
}
final修饰的属性如果未被初始化(包括构造函数内也未初始化)系统不会自动帮我们初始化(即不会默认初始化为0)
Animal.java
package com.template12;
public class Animal {
final public int age;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
System.out.println("Animal类执行了");
}
}
因此使用final修饰的属性必须初始化,要么在属性初始化,要么在构造函数进行初始化
对于final修饰局部变量(例如在方法中定义),那么局部变量成为一个常量,不允许被修改。
Animal.java
package com.template12;
public class Animal {
final public int age = 10;
public String name;
public void eat() {
final int constant = 10;//不允许被再次修改
constant = 100;
System.out.println("动物具有吃东西的能力");
}
public Animal(){
System.out.println("Animal类执行了");
}
}
super 关键字 |
---|
在对象的内部使用,可以代表父类对象 |
1.访问父类对象的属性 super.age 2.访问父类的方法 super.eat() |
子类的构造过程当中必须调用其父类的构造方法 |
如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类的无参构造方法 |
如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参构造方法,则编译出错 |
如果子类显示的调用构造方法,必须在子类的构造方法的第一行 |
Animal.java
package com.template12;
public class Animal {
public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
System.out.println("Animal类执行了");
}
}
Dog.java
package com.template12;
public class Dog extends Animal {
public int age = 20;
//重写eat()方法
public void eat(){
System.out.println("狗具有吃骨头的能力");
}
//重写无参构造方法
public Dog(){
//这里隐式的调用了父类的构造方法,类似于增加了一行super(),如下
//super();如果写了这一行那么这一行必须位于首行
System.out.println("Dog类执行了");
}
//定义method方法
public void method(){
System.out.println("调用父类的eat()方法");
super.eat();
System.out.println("调用子类的eat()方法");
eat();
System.out.println("调用父类属性age:" + super.age);
System.out.println("调用子类(本身)属性age:" + age);
}
}
Initial.java
package com.template12;
public class Initial {
public static void main(String[] args){
Animal animal = new Animal();
System.out.println("animal age:" + animal.age);
//创建dog对象并调用dog属性
//dog所有属性和方法都是从父类Animal继承而来
Dog dog = new Dog();
dog.name = "Quanhao Guo";
dog.method();
}
}
Animal类执行了
animal age:10
Animal类执行了
Dog类执行了
调用父类的eat()方法
动物具有吃东西的能力
调用子类的eat()方法
狗具有吃骨头的能力
调用父类属性age:10
调用子类(本身)属性age:20
object 类 与 toString()方法
object 类是所有类的父类,如果一个类没有使用extends
关键字明确标识继承另外一个类,那么这个类默认继承 Object 类,Object 类中的方法,适合所有子类。在 Object 类里面定义 toString() 方法的时候返回的对象哈希code(对象地址字符串),可以通过重写 toString() 方法表示出对象的属性。
关系示例 | toString() 示例 |
---|---|
< |
Animal.java
package com.template13;
public class Animal extends Object{
public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
System.out.println("Animal类执行了");
}
}
Dog.java
package com.template13;
public class Animal extends Object{
public int age = 10;
public String name;
public void eat() {
System.out.println("动物具有吃东西的能力");
}
public Animal(){
System.out.println("Animal类执行了");
}
}
Initial.java
package com.template13;
public class Initial {
public static void main(String[] args){
Dog dog = new Dog();
System.out.println(dog);
}
}
Animal类执行了
Dog类执行了
Dog{age=20}
equals()方法
比较的是对象的引用是否指向同一块内存地址
Transport.java
package com.template15;
public class Transport {
public int seats;
public int speed;
public float price;
public void setSpeed(int speed) {
this.speed = speed;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Transport transport = (Transport) o;
return seats == transport.seats &&
speed == transport.speed &&
Float.compare(transport.price, price) == 0;
}
public Transport(int seats, int speed, float price){
this.seats = seats;
setSpeed(speed);
setPrice(price);
}
}
Initial.java
package com.template15;
public class Initial {
public static void main(String[] args){
Bus bus_1 = new Bus(100, 200, 300);
Bus bus_2 = new Bus(100, 200, 300);
System.out.println("bus_1 parameters:");
System.out.println(bus_1.seats +" " + bus_1.speed + " " + bus_1.price);
System.out.println("bus_2 parameters:");
System.out.println(bus_2.seats +" " + bus_2.speed + " " + bus_2.price);
if(bus_1.equals(bus_2)){
System.out.println("两者相等");
}
else{
System.out.println("两者不等");
}
}
}
Bus.java
package com.template15;
public class Bus extends Transport {
public Bus(int seats, int speed, float price) {
super(seats, speed, price);
}
}
bus_1 parameters:
100 200 300.0
bus_2 parameters:
100 200 300.0
两者相等