一、引入
1、语法
A extends B
A:子类/派生类
B:父类/基类/超类
2、作用:
对多个类的共性进行提取,达到代码的复用
如:Cat类和Dog类,都需要有名字属性,吃饭方法,就可以写一个Animal类,代码如下
写一个Animal类
class Animal{
String name;
public void eat(){
System.out.println(this.name+"正在吃饭");
}
}
写一个Cat类
class Cat extends Animal{//继承Animal的属性和方法
public void mew(){
System.out.println(this.name+"喵喵喵");//可以写自己的方法
}
}
写一个Dog类
class Dog extends Animal{//继承Animal的属性和方法
public void bark(){
System.out.println(this.name+"汪汪汪");//写自己的方法
}
}
二、子类继承了父类的成员属性/方法
1、访问方式
已经变成了子类自己的成员属性/方法,和子类访问自己的成员属性/方法一样,可以直接在方法中访问,也可以通过对象名.属性/对象名.方法来访问
2、代码演示
class A{
int a;
int b;
public void func1(){
System.out.println("父类的方法");
}
}
class B extends A{
int c;
{
a = 100; //访问继承的属性a
c =200;//访问自己的变量
}
}
public class TestDemo {
public static void main(String[] args) {
B b = new B();
System.out.println(b.a);//访问继承的属性a
b.func1();//访问继承下来的func1方法
}
}
三、当子类与父类的成员属性/方法名相同
1、访问顺序
当出现子类与父类的成员属性/方法名相同时,优先访问自己的,称为就近原则。
2、代码演示
class A{
int a = 100;
public void func(){
System.out.println("父类的方法");
}
}
class B extends A{
int c;
int a = 200; //与父类同名的属性a
public void func(){ //与父类同名的方法func()
System.out.println("子类的方法");
}
}
public class TestDemo {
public static void main(String[] args) {
B b = new B();
System.out.println(b.a);//访问同名的属性
b.func();//访问同名的方法
}
}
结果调用子类的a和子类的func()方法
四、super关键字
1、作用
当子类成员属性/方法名相同时,默认调用子类自己的,如果我们想调用父类的,就需要用到super关键字。
2、语法
super.data //调用父类的属性
super.func() //调用父类的方法
super() //调用父类的构造方法
3、代码演示
class A{
int a =100;
public void func(){
System.out.println("父类的方法");
}
}
class B extends A{
int c;
int a =200; //与父类同名的属性a
public void func(){ //与父类同名的方法func()
System.out.println("子类的方法");
}
public void method(){
System.out.println(super.a);//调用父类的成员属性
super.func(); //调用父类的成员方法
}
}
public class TestDemo {
public static void main(String[] args) {
B b = new B();
b.method();
}
}
4、注意
1、super关键字和this关键字一样,只能在非静态的方法中使用
2、super用来访问父类继承下来的方法和属性
3、this是非静态成员方法的一个隐藏参数,super不是隐藏的参数
五、构造方法
1、当父类写了一个无参数的构造方法
子类会默认生成一个构造方法
public 子类名 {
super();}
class Animal{
String name;
public void eat(){
System.out.println(this.name+"正在吃饭");
}
public Animal(){
System.out.println("父类的构造方法");
}
}
class Cat extends Animal{
public void mew(){
System.out.println(this.name+"喵喵喵");
}
// public Cat(){ //默认生成的
// super(); //调用父类的构造方法
// }
}
public class TestDemo {
public static void main(String[] args) {
Cat cat = new Cat(); //当实例化对象的时候,就会调用Cat类的构造方法
}
}
2、父类写了一个有参数的构造方法
当构造子类的时候,子类需要先帮父类构造,才能使得代码正常运行
解决办法:
写一个构造方法,在第一行调用父类的构造方法,注意super()一定要在第一行
class Cat extends Animal{
public Cat(){
super("咪咪"); //显示调用父类的构造方法,来初始化子类从父类继承过来的东西
}
}
六、再谈初始化
1、执行顺序
在之前讲过的代码块中,执行顺序是静态代码块 > 实例代码块 > 构造代码块
在继承关系中,执行顺序依然是静态代码块 > 实例代码块 > 构造代码块,但父类总是优先于子类
2、代码演示
class Person{
{
System.out.println("Person:实例代码块");
}
static {
System.out.println("Person:静态代码块");
}
public Person(){
System.out.println("Person:构造代码块");
}
}
class Student extends Person{
{
System.out.println("Student:实例代码块");
}
static {
System.out.println("Student:静态代码块");
}
public Student(){
System.out.println("Student:构造代码块");
}
}
public class Test {
public static void main(String[] args) {
Student student1 = new Student();
Student student2 = new Student();
}
}