1. 基础语法
在Java中,使用extends
关键字来声明一个类继承自另一个类。例如,如果有一个Animal
类,并希望创建一个Dog
类作为其子类,语法如下:
public class Animal {
public void eat() {
System.out.println("动物正在进食");
}
}
// Dog类继承自Animal类
public class Dog extends Animal {
public void bark() {
System.out.println("狗在叫");
}
}
2. 方法继承与重写
子类自动获取父类的方法,但如果子类需要提供自己版本的方法实现,可以通过@Override
注解重写父类的方法:
public class Animal {
public void sound() {
System.out.println("动物发出声音");
}
}
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("狗发出的声音是汪汪!");
}
}
3. 访问限制与封装
子类无法访问父类中private
修饰的属性和方法,但可以访问public
, protected
以及默认访问级别的成员。若想要访问private
成员,可以通过父类提供的公有方法。
4. 构造函数与初始化
子类不能继承父类的构造函数,但可以通过super()
显式调用父类构造器来初始化继承的成员变量。
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 显式调用父类构造器
}
}
5. final修饰符
final
类不能被继承。final
方法不能被子类重写。
6. 多级继承
尽管Java不支持多重继承,但可以实现多级继承,即一个类可以继承另一个继承了某个类的类。
class Animal {}
class Mammal extends Animal {}
class Dog extends Mammal {}
7. Java继承的注意事项
在使用Java中的继承时,有几个关键点需要特别注意:
- 私有成员的继承:子类不能继承父类的私有成员(包括私有方法和私有变量)。私有成员只能在其父类的内部被访问和修改。
// 父类 public class Parent { private String secret = "秘密数据"; // 私有变量,子类无法直接访问 protected void displayProtectedData() { // 受保护的方法,子类可以访问 System.out.println("受保护的数据"); } } // 子类,尝试访问父类的私有成员 public class Child extends Parent { public void attemptToAccessSecret() { // 下面的行将导致编译错误,因为secret是私有的 // System.out.println(secret); // 错误: 'secret' has private access in 'Parent' this.displayProtectedData(); // 正确: 子类可以访问受保护的方法 } }
- 默认访问权限的继承:如果子类和父类不在同一个程序包中,子类无法继承父类中使用默认访问权限(即没有指定访问修饰符的成员)的成员。
// 父类,在com.parent包中 package com.parent; public class Parent { void displayDefaultData() { System.out.println("默认访问级别的数据"); } } // 子类,在com.child包中 package com.child; import com.parent.Parent; // 导入父类 public class Child extends Parent { public void attemptToAccessDefaultData() { // 下面的行将导致编译错误,因为默认访问权限的方法不在同一包内 // this.displayDefaultData(); // 错误: 'displayDefaultData()' has package access in 'com.parent.Parent' } }
- 构造方法的调用:子类的构造方法不会继承父类的构造方法,但在子类的构造方法中可以通过super关键字显式调用父类的构造方法。如果父类中没有无参构造方法,子类的构造方法中必须显式调用父类的有参构造方法。
// 父类Vehicle定义了一个车辆的基本属性:品牌 public class Vehicle { // 私有变量,用于存储车辆的品牌 private String brand; // 构造方法,初始化Vehicle对象的brand属性 public Vehicle(String brand) { // this关键字代表当前对象,此处用brand参数初始化brand属性 this.brand = brand; } } // 子类Car,继承自Vehicle,代表汽车,具有额外的属性:车门数量 public class Car extends Vehicle { // 私有变量,用于存储汽车的车门数量 private int numberOfDoors; // 构造方法,初始化Car对象的numberOfDoors属性,同时调用父类构造方法初始化brand属性 public Car(String brand, int numberOfDoors) { // super关键字用于调用父类Vehicle的构造方法,初始化brand属性 super(brand); // 初始化numberOfDoors属性 this.numberOfDoors = numberOfDoors; } }
- 方法重写:子类可以重写父类的方法,但重写的方法必须符合特定的规则,包括方法名、参数列表和返回类型必须与父类中被重写的方法相同。子类方法的访问权限不能低于父类被重写方法的访问权限。
// 父类Animal定义了一个所有动物共有的行为:发出声音 public class Animal { // 公有方法,表示动物发出声音 public void sound() { // 打印出动物发出声音的默认描述 System.out.println("动物发出声音"); } } // 子类Cat继承自Animal,代表猫,覆写sound方法以提供猫特有的行为 public class Cat extends Animal { // 使用@Override注解表明此方法是覆写父类的方法 @Override public void sound() { // 覆写父类Animal的sound方法,提供猫发出声音的描述 System.out.println("猫喵喵叫"); } }
- final方法的重写:不能重写父类中被声明为final的方法。
// 父类FinalExample定义了一个final方法,不可被覆写 public class FinalExample { // final修饰的方法不能在子类中被覆写 public final void finalMethod() { // 打印出final方法的描述 System.out.println("Final method from parent"); } } // 子类ChildOfFinalExample继承自FinalExample public class ChildOfFinalExample extends FinalExample { // 下面的代码尝试覆写父类的final方法,但是这将引起编译错误 // 编译错误: cannot override final methods // @Override // public void finalMethod() { // // 尝试改变final方法的行为,但这违反了Java的final方法规定 // System.out.println("Attempt to override final method"); // } }
- 构造方法中的super和this:在子类的构造方法中,super和this关键字不能同时出现,且super必须是构造方法中的第一条语句。
// 子类构造示例 public class Subclass { public Subclass() { super(); // 必须是第一条语句 this(); // 错误: this()和super()不能在同一构造方法中 } }
- 继承层次:Java不支持多重继承,即一个类只能继承自一个父类,但可以实现多个接口。
- 初始化顺序:在继承关系中,父类的静态成员和静态初始化块先于子类执行,然后是父类的实例成员和实例初始化块,最后是子类的静态成员、静态初始化块、实例成员和实例初始化块。
// 父类Base,定义了静态和实例初始化块 public class Base { // 静态初始化块,仅运行一次,在类加载时执行 static { // 打印消息,指示静态初始化块的执行 System.out.println("Base static block"); } // 实例初始化块,每次创建对象时都会执行 { // 打印消息,指示实例初始化块的执行 System.out.println("Base instance block"); } } // 子类Derived,继承自Base public class Derived extends Base { // 静态初始化块,仅运行一次,在类加载时执行 static { // 打印消息,指示静态初始化块的执行 System.out.println("Derived static block"); } // 实例初始化块,每次创建对象时都会执行 { // 打印消息,指示实例初始化块的执行 System.out.println("Derived instance block"); } }
- 避免过度继承:继承层次不宜过深,以免增加代码的复杂性和维护成本。
- 向上转型和向下转型:向上转型是安全的,但向下转型需要进行类型检查,否则可能会抛出ClassCastException异常。
// 基类Animal,表示所有动物 public class Animal { // Animal类的具体实现 } // 子类Cat,继承自Animal,表示猫 public class Cat extends Animal { // Cat类的具体实现 } // 向上转型:将Cat类型的对象赋值给Animal类型的引用 // 这是安全的,因为Cat是Animal的一种 Animal animal = new Cat(); // 向下转型:将Animal类型的引用强制转换为Cat类型 // 需要类型检查,确保animal确实是指向一个Cat实例 Cat cat = (Cat) animal;
- 使用组合代替继承:在某些情况下,使用组合(通过包含其他类的对象来实现功能)可能比继承更灵活和合适。
public class Engine {} public class Car { private Engine engine; }
- 父类和子类的修改:对父类的修改要非常谨慎,因为这可能会影响到所有继承自该父类的子类。
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Java中的继承
发表评论 取消回复