读者可订阅专栏:Java开发指南 |【CSDN@秋说】
Java继承
当两个Java文件存在大量重复的内容时,代码会显得冗长、臃肿,且维护起来不够高效。为了解决这个问题,可以考虑通过继承的方式,将这些重复的部分提取出来,组成一个父类。
首先,我们可以创建一个父类,其中包含两个Java文件中共享的方法或属性。然后,让这两个Java文件分别继承这个父类。这样一来,就可以避免代码的重复,并且提高了代码的可维护性和可扩展性。
类的继承格式
class 父类 {
}
class 子类 extends 父类 {
}
继承类型
需要注意的是 Java 不支持多继承,但支持多重继承。
继承的特性
1、子类拥有父类非私有的属性和方法: 子类可以访问并继承父类中非私有的属性和方法,这使得代码的复用性更高。
2、子类可以拥有自己的属性和方法: 子类可以在继承父类的基础上添加新的属性和方法,从而实现对父类的扩展。
3、子类可以重写父类的方法: 子类可以对父类中的方法进行重写(覆盖),以实现自己的功能需求。这种多态性的特性提供了灵活性和可定制性。
4、Java的单继承和多重继承: Java只支持单继承,即一个子类只能继承一个父类。但通过接口可以实现多重继承的效果,因为一个类可以实现多个接口。
5、提高了类之间的耦合性: 继承确实会增加类之间的耦合性,因为子类与父类之间存在依赖关系。高耦合度可能导致代码的独立性降低,但适当的继承设计可以降低耦合度,例如通过合理的抽象和接口设计来实现松耦合。
如何继承
在Java中,要实现继承,需要使用关键字
extends关键字
我们常用extends
关键字实现继承。在Java中,类的继承是单一继承,也就是说,一个子类只能继承一个父类,因此使用extends
关键字只能继承一个类。
示例如下:
class Animal
{
void makeSound()
{
System.out.println("It makes a sound.");
}
}
class Dog extends Animal{
}
public class Ice{
public static void main(String[] args)
{
Dog dog=new Dog();
dog.makeSound();
}
}
implements关键字
在Java中,使用implements
关键字可以实现类与接口之间的关系,这样类就可以间接具有多重继承的特性。
当一个类实现了某个接口时,它必须实现该接口中声明的所有方法。
一个类可以实现多个接口,接口之间用逗号分隔。
// 定义一个接口A
interface A {
void methodA();
}
// 定义另一个接口B
interface B {
void methodB();
}
// 定义一个类,实现接口A和接口B
class III implements A, B {
// 实现接口A中的方法
public void methodA() {
System.out.println("Method A implementation");
}
// 实现接口B中的方法
public void methodB() {
System.out.println("Method B implementation");
}
}
// 测试类
public class Ice {
public static void main(String[] args) {
// 创建III对象
III ice = new III();
// 调用实现的方法
ice.methodA();
ice.methodB();
}
}
super 与 this 关键字
super关键字: 在子类中,可以使用super
关键字来引用父类的成员(方法、字段),以便在子类中重写父类的方法或访问父类的构造方法。
this关键字: 在Java中,this
关键字表示对当前对象的引用。它可以用于访问当前对象的字段、方法或者调用当前类的构造方法。
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // 使用this调用Dog类的eat方法
super.eat(); // 使用super调用Animal类的eat方法
}
}
public class Ice {
public static void main(String[] args) {
Animal a = new Animal();
a.eat(); // 输出 "animal : eat"
Dog d = new Dog();
d.eatTest(); // 输出 "dog : eat" 和 "animal : eat"
}
}
final 关键字
final
关键字可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
当 final
关键字用于类时,它将该类定义为最终类,意味着它不能被继承。同样地,当 final
用于方法时,它将该方法定义为最终方法,不能被子类重写。
声明类:
final class 类名 {
//类体
}
声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){
//方法体
}
注: final 定义的类,其中的属性、方法不是 final 的。
示例,Cat
类继承自 Dog
类,但是 Dog
类被声明为 final
,意味着它不能被继承。这会导致编译错误:
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
final class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
}
class Cat extends Dog{
void eat() {
System.out.println("cat : eat");
}
}
public class Ice {
public static void main(String[] args) {
Animal a = new Animal();
a.eat(); // 输出 "animal : eat"
Dog d = new Dog();
d.eat(); // 输出 "dog : eat"
Cat c = new Cat();
c.eat();
}
}
构造器
继承中常用的是构造器。
在继承时,子类不继承父类的构造器(构造方法或者构造函数),而是通过调用(隐式或显式)来使用它们。
1、如果父类的构造器带有参数,则必须在子类的构造器中显式地使用 super
关键字调用父类的构造器,并传递适当的参数列表。
2、如果父类的构造器没有参数,则在子类的构造器中不需要使用 super
关键字调用父类的构造器,系统会自动调用父类的无参构造器。
class superclass{
private int n;
superclass(){
System.out.println("1");
}
superclass(int n){
System.out.println(n);
}
}
//继承
class super1 extends superclass{
private int n;
super1(){// 自动调用父类的无参数构造器,输出1
System.out.println("2");//输出2
}
public super1(int n)
{
super(n);// 显式调用父类的有参数构造器
}
}
public class Ice{
public static void main(String args[])
{
super1 iii = new super1();
super1 ccc = new super1(100);//显式调用了父类的有参数构造函数 super(n),输出100
}
}