Java 中继承(inherit)

本文详细介绍了Java中类的继承关键字`extends`的使用,包括单继承特性及访问权限。同时,讨论了方法重写(Override)的概念,展示了如何在子类中调用父类的方法和属性。在属性同名的情况下,调用过程遵循就近原则。最后,通过实例代码解释了方法和属性的调用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Java中实现继承的关键字extends

         extends 本意为拓展、扩展、扩大;在java 中作为关键字,表示继承的意思。可以理解为在父类的基础上进一步完善,进一步发扬光大。编程世界里的继承和现实世界的继承非常相似,编程世界里的继承不能继承父类的私有属性和方法,同样的现实世界里我们能够继承父母的财富,但不能继承他们的私有之物,比如生活用品……

1.1 关键字使用语法

语法1:访问修饰符   class   子类名 extends 父类名{

            注意:1.此处的修饰符只能是public或默认的(即不写修饰符)

                      2.java类的继承只有单继承,类不存在多继承

                      3.同包中,子类中能使用父类中除了private修饰的所有属性和方法,不同包时,能够使用protected和public修饰的方法和属性,具体可以看Java中访问权限修饰符

                     4.除了Object类以外,任何类至少有一个父类,即Object类。一个类没有明确extends方式继承一个类时,编译器会自动给该类添加一个Object类。如果明确指定一个继承父类,则通过父类间接继承Object类。

             //属性

            //方法

}

1.1.1 代码实例  

父类的代码如下:

public class Parent {
    //父类中存在的属性
    private String name = "父类属性";

    public String getName() {
        return name;
    }
}

子类代码如下:

public class Child extends Parent {
    //子类中存在与父类中的同名属性
    public String name= "child的属性";

    @Override
    public String getName() {
        return super.getName();
    }
}

语法2:权限访问修饰符    interface  接口名 extends 父接口1,父接口2……{

           注意:java中类不存在多继承,但是接口是存在多继承的,可以通过关键字extends实现多继承。

}

 1.1.2 代码实例

父接口:

//父接口1
public interface ParentInterface1 {
    //抽象方法定义
}

//父接口2
public interface ParentInterface2 {
    //抽象方法定义
}

子接口:

//子接口定义
public interface ChildInterface extends ParentInterface1 , ParentInterface2 {
    //内部接口定义
}

2 继承中属性和方法的调用过程

   在上文已经介绍过,Java中的继承是继承了父类除了private属性修饰以外的所有属性和方法。那如果父类的属性和方法与子类的属性和方法重名之后,应该调用哪一个呢?下面将分别进行分析:

2.1 方法同名

       聊继承,必然会谈重写(Override),何为重写?重写就是将父类的方法,无论是普通方法还是抽象方法都在子类中重写实现,实现的代码根据自己业务需求进行。  

2.1.1 父类有方法和属性,子类无方法和属性

父类代码:

public class Parent {
    /*
    此处为方便调用使用public修饰
    测试属性
     */
    public String name = "父类的名称Parent";
    /*
    测试方法
     */
    public void testMethod(){
        System.out.println("父类的测试方法");
    }

}

子类代码:

public class Child extends Parent {
    
}

测试代码:

public class Test {
    public static void main(String[] args) {
        /*
       第一种:测试子类是否真正实现了父类的所有属性和方法
         */
        Child child = new Child();
        //子类是否继承父类属性
        System.out.println(child.name);
        //子类是否继承父类方法
        child.testMethod();
    }
}

运行结果:

可以看出,子类是继承了父类的所有方法和属性。

2.1.2 父类有方法和属性,子类有相同方法

子类代码:

public class Child extends Parent {
    /**
     * 重写父类的方法
     * 如果@Override去掉之后,不叫方法重写,只是在子类中定义了一个和父类方法同名的方法,参数也相同而已。当我们通常也会认为此方法是重写方法。
     * @Override是告诉编译器此方法是重写父类的方法,如果方法的名和参数列表修改会报编译时异常
     * 返回权限必须大于或等于父类的访问权限
     * 返回值类型必须小于或等于父类的访问权限
     * 
     */
    @Override
    public void testMethod() {
        //这是在调用父类的同名方法
        //super.testMethod();
        System.out.println("子类的方法");
    }
}

执行结果:

public class Test {
    public static void main(String[] args) {
        /*
       第二种:测试子类是调用父类还是自身的方法
         */
        Child child = new Child();
        child.testMethod();//结果:子类的方法
    }
}

从执行结果来看,子类执行的是子类自身的方法,而没有执行父类的方法。其内部到底如何调用的呢?

2.1.3 代码底层执行过程

下图是执行代码的真实过程:

从上图可知,子类对象先在自己的空间查找是否有此方法或属性,如果没有才到父类对象的存储空间查找,而且JVM采用的是就近原则查找,因此最终结果是调用的是子类对象的方法。

2.2 属性同名

父类代码:

public class Parent {
    //父类中存在的属性
    private String name = "父类属性";

    public String getName() {
        return name;
    }
}

子类代码:

public class Child extends Parent {
    //子类中存在与父类中的同名属性
    public String name= "child的属性";

    @Override
    public String getName() {
        return super.getName();
    }
}

测试代码:

public class TestInherit {
    public static void main(String[] args) {
        /**
         * 当父类和子类属性同名时,父类提供访问父类属性的方法,而子类未重写该方法时,通过多态的方式调用的是父类的属性
         * 本质:父类方法在调用父类属性语法是:this.父类属性,而非子类属性,子类属性在父类中是无法获取到的
         */
        Parent p = new Child();
        System.out.println(p.getName());//父类属性
        /**
         * 父类和子类属性同名时,父类提供访问父类属性的方法,而子类重写该方法时,通过多态的方式调用的是子类的属性
         *子类重写该方法时,两种情况:
         * 1.子类直接调用自己的属性
         * 2.子类通过super关键字调用父类的属性,这些属性依然遵守访问权限修饰符的约束
         */
        //第一种情况
        System.out.println(p.getName());//child的属性
        //第二种情况
        System.out.println(p.getName());//父类属性
        /**
         * 当父类拥有属性,子类没有该属性,当重写了父类方法
         */
        System.out.println(p.getName());//父类属性
    }
}

3.总结:

     属性同名的调用过程和调用方法的过程基本相同,都是先在子类存储空间中查找是否有该属性,如果有,直接返回,不在继续寻找,如果没有才会继续查找父类,直到所有父类都没找到的时候,才会报异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值