java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立父子关系。子类能继承父类的非私有成员,子类对象是由父类子类共同完成的(子类对象包含父类成员,但无法调用非私有成员)。

public class A {
    public int i;
    public void print1(){
        System.out.println("===print1===");
    }
}
public class B extends A {
    //子类可以继承父类的私有成员
    public void print3(){
        System.out.println(i);
        print1();
    }
}
public class Test {
    public static void main(String[] args) {
        B b = new B();//b对象是由AB两个设计图共同创建的
        System.out.println(b.i);
        b.print1();
    }
}

权限修饰符

修饰符 在本类 同一个包的其他类里 任意包下的子类里 任意包下的任意类型
private
缺省
protected
public
  • protected可以在任意包下的子类A里访问,但不能在非子类B中通过A类的对象访问

单继承

一个类只能继承一个父类,Java中的类不支持多继承,但支持多层继承。

class A {};//extends Object{},Object类是所有类的祖宗类
class B extends A {};
class C extends B {};

方法重写

当子类觉得父类某个方法不管用,子类可以重新写一个参数一样的方法,子类可以重写一个参数列表一样的方法,称为方法重写。重写后方法的访问遵循就近原则。

  • 重写小技巧:使用Override重写,可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。
  • 子类重写父类方法时,访问权限必须大于等于父类该方法的权限(public>protected>缺省)
  • 重写方法返回值类型,必须与被重写方法返回值一样,或者范围更小。
  • 私有方法,静态方法不能被重写,如果重写会报错的。
public class A {
    public void print1(){
        System.out.println("111");
    }
    public void print2(int a,int b){
        System.out.println("111111");
    }
}
public class B extends A{
    @Override
    public void print1(){
        System.out.println("666");
    }
    @Override
    public void print2(int a,int b){
        System.out.println("666666");
    }
}

常见应用场景

子类重写Object中的类方法,以便返回对象的内容。

//object类中的toString()方法
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

创建实体类Student

public class Student {
    private int age;
    private String name;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    ······
    @Override
    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
}
public class Test {
    public static void main(String[] args) {
        Student s=new Student("播妞",19);
        System.out.println(s);//Student [age=19, name=播妞]
    }
}

子类中访问其他成员的特点

在子类方法中访问成员遵循就近原则,如果在子父类中出现了重名的成员,会优先选择子类的;如果此时一定要在子类中使用父类成员需要使用super关键字。

public class F {
    String name="父类名称";
    public void print1(){
        System.out.println("==父类的print方法执行==");
    }
}
public class Z extends F{
    String name="子类名称";
    public void showname() {
        String name="局部名称";
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
    public void print1(){
        System.out.println("==子类的print方法执行==");
    }
    public void showMethod(){
        print1();
        super.print1();
    }

}
public class Test {
    public static void main(String[] args) {
        Z z=new Z();
        z.showname();
        /*局部名称
          子类名称
          父类名称*/
        z.showMethod();
        /*==子类的print方法执行==
          ==父类的print方法执行==*/
    }
}

子类构造器

子类的全部构造器都会先调用父类的构造器,再执行自己的。

public class F {
    public F() {
        System.out.println("父类的无参构造器执行了");
    }
}

子类的所有构造器都会调用父类的无参构造器,如果父类没有无参构造器会报错。或者在子类构造器里第一行用super(...)调用父类的有参构造器。

public class Z extends F{
    public Z() {
        super();//默认存在
        System.out.println("子类的无参构造器执行了");
    }
    public Z(String name) {
        super();//默认存在
        System.out.println("子类的有参构造器执行了");
    }
}
public class Test {
    public static void main(String[] args) {
        Z z=new Z();
       /* 父类的无参构造器执行了
          子类的无参构造器执行了*/
        Z z2=new Z("wasd");
        /*父类的无参构造器执行了
          子类的有参构造器执行了*/
    }
}

常见应用案例:

public class Test2 {
    public static void main(String[] args) {
        Teacher t = new Teacher("李四",36,"Java");

    }
}
class Teacher extends People{
    private String skill;

    public Teacher(String name, int age, String skill) {
        super(age, name);
        this.skill = skill;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
}
class People{
    private String name;
    private int age;

    public People() {
    }

    public People(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

兄弟构造器

在任意类的构造器中,可以用this(...)调用兄弟构造器。this(...)和super(...)不能同时写,且this(...)也要写在第一行。

public class Test3 {
    Student s1=new Student("李四",24);
}
class Student{
    private String name;
    private int age;
    private String schoolname;

    public Student() {
    }
    public Student(String name, int age) {
       this(name, age, "WASD");
    }

    public Student(String name, int age, String schoolname) {
        this.name = name;
        this.age = age;
        this.schoolname = schoolname;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSchoolname() {
        return schoolname;
    }

    public void setSchoolname(String schoolname) {
        this.schoolname = schoolname;
    }
}