一、继承
在Java中,继承是一种重要的面向对象编程概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。这意味着子类可以使用父类的成员变量和方法,并且可以添加自己的新功能或覆盖父类的方法。
以下是关于Java中继承的一些重要概念:
-
extends关键字: 在Java中,通过使用关键字extends来实现继承。例如:
javaclass SubClass extends SuperClass { // 子类的代码 }
-
构造方法
-
父类构造方法:
- 父类构造方法用于初始化父类的实例变量。
- 如果子类没有显式地调用父类构造方法,Java会自动调用父类的无参构造方法(如果存在),以确保父类的初始化。
- 如果父类没有无参构造方法,而子类又没有显式地调用父类其他构造方法,则编译器会报错。
- 子类可以使用super关键字显式地调用父类的构造方法,以初始化父类的实例变量。
-
子类构造方法:
- 子类构造方法用于初始化子类的实例变量。
- 子类构造方法可以选择调用父类的构造方法,或者不调用。如果不调用父类构造方法,则会默认调用父类的无参构造方法。
- 子类构造方法可以重载父类的构造方法,但是在子类构造方法中调用父类构造方法的语句必须放在子类构造方法的第一行。
-
使用super关键字调用父类构造方法:
- 子类可以使用super关键字显式地调用父类的构造方法。
- 使用super()调用父类的无参构造方法。
-
使用super(...)调用父类的特定构造方法,传递参数给父类构造方法。
javaclass Parent { private int parentValue; public Parent() { this.parentValue = 0; System.out.println("Parent's default constructor"); } public Parent(int value) { this.parentValue = value; System.out.println("Parent's constructor with parameter"); } } class Child extends Parent { private int childValue; public Child() { super(); // 调用父类的无参构造方法 this.childValue = 0; System.out.println("Child's default constructor"); } public Child(int parentValue, int childValue) { super(parentValue); // 调用父类的有参构造方法 this.childValue = childValue; System.out.println("Child's constructor with parameter"); } } public class Main { public static void main(String[] args) { Child child1 = new Child(); // 默认调用父类的无参构造方法,然后调用子类的无参构造方法 Child child2 = new Child(10, 20); // 调用父类的有参构造方法,然后调用子类的有参构造方法 } }
在上面的示例中,父类Parent有两个构造方法:一个是无参构造方法,另一个是带参数的构造方法。子类Child重写了这两个构造方法,并且在子类构造方法中使用super关键字来调用父类的构造方法。通过这样的方式,我们可以灵活地初始化父类和子类的实例变量
-
-
子类调用父类方法与属性
在Java中,子类可以调用父类的方法和属性,以便在子类中重用父类的功能或访问父类的状态。这种调用通常通过super关键字来实现。
- 调用父类方法:
-
子类可以使用super关键字调用父类的方法。
-
通过super.methodName()来调用父类的方法。
-
如果子类重写了父类的方法,使用super关键字可以在子类中调用父类的原始方法。
javaclass Parent { public void parentMethod() { System.out.println("Parent method"); } } class Child extends Parent { public void childMethod() { super.parentMethod(); // 调用父类方法 System.out.println("Child method"); } } public class Main { public static void main(String[] args) { Child child = new Child(); child.childMethod(); // 输出: Parent method\nChild method } }
访问父类属性:
-
子类可以通过super关键字访问父类的属性。
-
使用super.fieldName来访问父类的属性。
javaclass Parent { public int parentValue = 10; } class Child extends Parent { public void printParentValue() { System.out.println("Parent value: " + super.parentValue); // 访问父类属性 } } public class Main { public static void main(String[] args) { Child child = new Child(); child.printParentValue(); // 输出: Parent value: 10 } }
在Java中,成员属性的空间是在对象被创建时开辟的,而对象的创建通常在构造方法被调用时完成。因此,在构造方法被调用之前,成员属性的空间已经被分配了。
具体地说,当使用new关键字创建一个对象时,Java会为该对象分配内存空间,并在内存中创建对象的实例。在这个过程中,对象的成员属性的内存空间也会被分配,并根据其类型进行初始化(对于基本数据类型,会使用默认值;对于引用类型,会被初始化为null)。
然后,构造方法会被调用,构造方法的主要任务是对对象进行初始化,这包括对成员属性的初始化、执行必要的设置操作等。
所以,成员属性的空间开辟是在对象创建的过程中完成的,而构造方法通常是在这个过程中被调用的,因此在构造方法调用之前,成员属性的空间已经被分配了。
-
- 调用父类方法:
-
重写
方法重写(Method Overriding)是面向对象编程中的一个重要概念,它允许子类重新定义父类中已经定义的方法。通过方法重写,子类可以根据自身的需求修改或扩展父类的方法,从而实现多态性。
-
方法重写的条件如下:
-
子类方法的名称、参数列表和返回类型必须与父类中被重写的方法完全相同。
-
子类方法不能缩小父类方法的访问权限。也就是说,如果父类方法是public,则子类方法也必须是public或者更宽松的访问权限。
-
子类方法不能抛出比父类方法更多的异常。
-
当子类重写父类的方法后,如果在子类的实例上调用该方法,则会执行子类中的方法,而不是父类中的方法。这种调用称为动态绑定或者后期绑定。这是Java中实现多态性的一种方式。
下面是一个简单的例子来说明方法重写的概念:
javaclass Animal { public void makeSound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void makeSound() { // 重写父类方法 System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal animal = new Animal(); animal.makeSound(); // 输出: Animal makes a sound Dog dog = new Dog(); dog.makeSound(); // 输出: Dog barks } }
在上面的例子中,Animal类有一个makeSound方法,而Dog类继承了Animal类并重写了makeSound方法。当创建一个Animal对象并调用makeSound方法时,执行的是Animal类中的makeSound方法;而当创建一个Dog对象并调用makeSound方法时,执行的是Dog类中重写的makeSound方法。这显示了方法重写在Java中的实际应用,实现了多态性的概念。
-
二、多态
多态(Polymorphism)是面向对象编程中的一个重要概念,它使得代码更加灵活、可扩展和易于维护。多态性允许使用基类的引用变量来引用子类的对象,从而在运行时选择正确的方法执行。
多态的意义:
-
灵活性: 多态性允许使用统一的接口来操作不同的对象,从而使得代码更加灵活,可以适应不同类型的对象。
-
可扩展性: 当新增加一个子类时,不需要修改已有的代码,只需要保证新子类实现了相应的接口或继承了父类,就可以使用多态性来操作该子类对象。
-
易于维护: 多态性提高了代码的可读性和可维护性,因为不同的对象可以使用相同的接口来进行操作,降低了代码的复杂度。
实现条件:
-
继承: 多态性的实现依赖于继承关系,子类必须继承自父类或者实现相同的接口。
-
方法重写: 子类必须重写(Override)父类的方法,使得父类引用可以在运行时调用到子类的方法。
-
父类引用指向子类对象: 多态性的关键在于父类引用可以指向子类对象,即父类类型的引用变量可以引用子类类型的对象。
java// 父类 class Animal { public void makeSound() { System.out.println("Animal makes a sound"); } } // 子类 class Dog extends Animal { @Override public void makeSound() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal animal = new Dog(); // 父类引用指向子类对象 animal.makeSound(); // 输出: Dog barks } }
在上面的例子中,Animal是父类,Dog是子类,Dog类重写了Animal类的makeSound方法。在Main类中,创建了一个Animal类型的引用animal,并将其指向一个Dog类型的对象。然后调用animal.makeSound(),由于多态性的作用,实际上调用的是Dog类中重写的makeSound方法。这就是多态性的实现。