Java随笔-继承

1. 实现继承关系

继承需要使用extends关键字。

  • 创建父类
/**
 * 父类
 */
public class Father {
}

被继承类可称为超类、基类、父类。

  • 创建子类,并继承父类
/**
 * 子类
 */
public class Son extends Father{
}

继承类成为子类、派生类、孩子类。

继承的作用:子类可以使用父类中的一些成员变量和方法,从而提高代码的重用性,提高开发效率。
父类并非高于子类,恰恰相反,子类往往比父类更加丰富,除了可以调用父类的一些成员变量和方法外,还有自己独有的属性和方法。

2. 子类调用父类的一些成员变量和方法

  • 父类
/**
 * 父类
 */
public class Father {
    // 共有属性
    public String name;
    // 受保护属性
    protected String power;
    // 私有属性
    private int age;
    // 默认属性
    boolean tall;

    // 共有方法
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
    // 私有方法
    private void salary(){
    }

    // 保护方法
    protected String getPower(){
        power = "父类的权益";
        return power;
    }

    // 默认方法
    void testDefaultMethod(){
    }
}
  • 子类
/**
 * 子类
 */
public class Son extends Father{

    /**
     * 调用父类的一些成员变量或方法
     */
    public void test01(){
        // 调用父类共有的属性和方法
        name = "父类" + getName();

        // 调用父类受保护的属性和方法
        String powerStr = power + getPower();

        // 调用父类私有的属性和方法
        // 'age' has private access in 'Father'
        // age;
        // 'salary()' has private access in 'Father'
        // salary();

        // 调用父类默认权限的属性和方法
        boolean tall = super.tall;
        testDefaultMethod();
    }
}
之所以说子类可以调用父类的一些成员变量和方法,是只能调用父类的public、protected、default(没有权限修饰)的成员变量和方法,父类私有(private修饰)的就不能调用。
protected:只可以被本类,子类,同一个包中可以访问。如果是多层继承的话,若是修改protected修饰的属性和方法会很麻烦。

3. 方法重写

当子类重写父类的方法时会使用 @Override关键字标记。

  • 子类
    @Override
    public String getName() {
        // todosomething
        return super.getName();
    }

一般重写父类方法是为了自定义属性。去掉关键字其实就是子类的普通方法,若是还想在该方法中方位父类方法,需要使用super关键字,否则无法区分调用的是哪一个类中的方法,可能出现死循环问题。

   public String getName() {
        return "子类" + super.getName();
    }

方法重写有一定的规则:

  • 重写的方法参数要完全相同。
  • 返回类型可以一样,也可以是父类返回值的子类,其他的都不可以。
  • 访问权限不能比父类低,如果父类是protected,子类只能是public或protected,不能是其他的。
  • 重写的方法抛出的异常只是父类抛出的异常的子类或本身,不能是其他的。
  • 构造方法不能被重写。
  • final和private方法不能被重写,当然也写不到。
  • 子类只能重写父类的方法,显而易见的,这是重写的前提,也算是废话。

4. 构造方法

  • 父类构造
    public Father() {
        System.out.println("这是父类的构造");
    }
  • 子类构造
    public Son() {
        System.out.println("这是子类的构造");
    }
  • 测试
    public static void main(String[] args) {
        Son son = new Son();
    }
  • 结果
S:\JDK16\bin\java.exe "-javaagent:S:\IntelliJIDEA\IntelliJ IDEA 2021.3.3\lib\idea_rt.jar=49229:S:\IntelliJIDEA\IntelliJ IDEA 2021.3.3\bin" -Dfile.encoding=UTF-8 -classpath F:\java\extend\out\production\extend Test
这是父类的构造
这是子类的构造

如果子类构造没有显式调用父类的构造方法,则会自动调用父类的无参构造。

  • 父类
public class Father {
//    public Father() {
//        System.out.println("这是父类的构造");
//    }
    public Father(String name) {
        System.out.println("这是父类的有参构造");
    }
 }
  • 子类
public class Son extends Father{
    public Son() {
        Father father = new Father("father");
        System.out.println("这是子类的构造");
    }
}
  • 编译
    在这里插入图片描述
    如果父类中没有无参构造,并且在子类中又显式调用父类的其他构造,则编译报错。但是如果使用super关键字就没有问题。
    public Son() {
//        Father father = new Father("father");
        super("father");
        System.out.println("这是子类的构造");
    }
  • 编译
S:\JDK16\bin\java.exe "-javaagent:S:\IntelliJIDEA\IntelliJ IDEA 2021.3.3\lib\idea_rt.jar=52386:S:\IntelliJIDEA\IntelliJ IDEA 2021.3.3\bin" -Dfile.encoding=UTF-8 -classpath F:\java\extend\out\production\extend Test
这是父类的有参构造
这是子类的构造

5. 继承层次

Java中支持多层继承,但不支持多继承。

  • 多层继承
public class Son extends Father{}

public class Grandson extends Son{
}

Grandson继承Son,Son继承Father。若是多继承则会报错。
在这里插入图片描述
Java类不支持多继承,但接口可以多继承。

public interface Interface01 {
}
...
public interface Interface02 {
}
...
// 接口多继承
public class Test implements Interface01, Interface02 {
...
}
...

6. 多态

父类引用指向子类对象称为多态。

        // 多态
        Father father = new Son();

置换法则:程序中任何出现父类对象的地方都可以用子类对象替换。

        Father[] fathers = new Father[10];
        fathers[0] = new Son();
        fathers = new Son[10];

即使父类数组被全部置换,但申明的还是父类,所以获取的对象还是父类,无法访问子类对象特有的属性和方法,也不能赋值给子类变量。

        // 置换法则
        Father[] fathers = new Father[10];
        fathers[0] = new Son();
        // 无需强转
        fathers = new Son[10];
        // 得到的只能是父类,不是子类
        Father father1 = fathers[0];
        // 非法
        Son son1 = fathers[0];
        // 强转
        Son son2 = (Son) fathers[0];

强转会忽略对象实际类型,使用对象的全部功能,所以强转之前最好判断一下类型。

        Father[] fathers = new Father[10];
        fathers[0] = new Son();
        // 类型判断
        if(fathers[0] instanceof Son){
            Son son1 = (Son) fathers[0];
        }

7. 方法重载

重载就是在一个类中,方法名相同,参数不同,返回值可以不同,也可以相同,多用于构造函数。

    public Father() {
        System.out.println("这是父类的构造");
    }

    public Father(String name) {
        System.out.println("这是父类的有一个参的构造");
    }

    public Father(String name, String power) {
        this.name = name;
        this.power = power;
        System.out.println("这是父类的有两个参的构造");
    }

    public Father(String name, String power, int age) {
        this.name = name;
        this.power = power;
        this.age = age;
        System.out.println("这是父类的有三个参的构造");
    }

    // 无参
    private void test(){

    }

    // int 参
    private int test(int a){
        return -1;
    }

    // 参数名相同,类型不同
    private int test(boolean a){
        return -1;
    }
    
    private String test(String str,int a){
        return str;
    }

    // 改变参数位置
    private String test(int a,String str){
        return str;
    }

    // 只改变返回值类型,不能算重载
//    private int test(String str,int a){
//        return a;
//    }

8. final

使用final类和方法,可以阻止继承。

public final class FinalTest {
    void test() {
    }
}

尝试继承final类。
在这里插入图片描述
final方法也是不能被重写的。

public  class FinalTest {
    final void test() {
    }
}

尝试重写final方法。
在这里插入图片描述
Java中基本数据类型和String都是final类,为了防止被继承。
在这里插入图片描述
在这里插入图片描述

总结

  1. 继承时将公共方法和属性放在父类。
  2. 不要过度使用protected。同一个包中所有类都可以访问protected,不管是不是其子类,此时使用protected作用不大。其次,任何一个类都可能是某一个类的子类,都能直接访问protected,破环了封装性。
  3. 继承不要滥用,尽量在”is-a“的关系中使用继承。
  4. 如果不是继承的所有的方法都有意义,就不要使用继承。
  5. 对于类型信息的判断,要是有继承关系,尽量的使用多态。
  6. 反射不要滥用,因为反射只有运行时才会报错,很难发现错误。
  7. 重写的方法不要改变其原有作用,就是重写后的作用要和重写之前的作用差不多,若是相差太多还不如新写新的方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值