目录
3.4 静态内部类(Static Inner Classes)
0.引言
在Java编程语言中,static
、final
和super
是三个具有特殊意义的关键字,各自在类的设计和继承机制中扮演着重要角色。
(1)static关键字
static
关键字用于声明类级别的成员,包括静态变量和静态方法。静态成员属于类本身,而不是类的任何单个实例,这意味着所有实例共享同一个静态成员。静态变量常用于定义类常量或管理全局状态,静态方法可以在不创建类实例的情况下调用,常用于工具方法。此外,还可以用static
定义静态代码块进行类变量初始化,以及静态内部类。
(2)final关键字
final
关键字提供了不同的使用场景,包括声明不可改变的常量、防止方法被重写,以及禁止类被继承。当final
用于变量时,这个变量成为常量,意味着一旦被赋值之后就不可以被更改。用于方法时,这个方法不能在子类中被重写。用于类时,表示这个类不能被继承。final
的使用增加了代码的安全性和清晰性,表明开发者的明确意图,避免了不必要的变更。
(3)super关键字
super
关键字用于子类中访问父类的成员(变量和方法)。它主要用于三个场景:调用父类的构造方法、访问父类的方法和变量。特别是在构造方法中,子类必须调用父类的构造方法来保证父类部分被正确初始化,如果没有显式调用父类的构造方法,编译器会自动插入对父类无参构造方法的调用(如果父类没有无参构造方法则会编译错误)。super
在处理多层继承时尤为重要,确保所有祖先类都被适当初始化。
(4)总结
static
、final
和super
关键字在Java中各有其用途和应用场景。static
使得变量和方法脱离于对象实例而存在,final
确保变量、方法或类的不可变性,而super
则是在子类中引用父类的成员的方式。恰当地使用这些关键字能够使得Java程序更加安全、高效和易于维护。了解它们的特性和使用场景对于编写高质量的Java代码至关重要。
1.super关键字
当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,Java提供了super关键字,super关键字可以在子类中调用父类的普通属性、方法以及构造方法。
在Java中,子类继承父类时,并不会继承父类的构造方法。但是,子类的构造过程中必须调用其父类的构造方法,以确保父类的成员变量和环境被正确初始化。这就是为什么在子类的构造方法中需要有super
调用的原因。
接下来详细讲解super关键字的具体用法。
(1)使用super关键字访问父类的成员变量和成员方法,具体格式如下:
super.成员变量
super.成员方法(参数1,参数2…)
接下来通过一个案例学习super关键字访问父类的成员变量和成员方法。
1 // 定义Animal类
2 class Animal {
3 String name = "牧羊犬";
4 //定义动物叫的方法
5 void shout() {
6 System.out.println("动物发出叫声");
7 }
8 }
9 // 定义Dog类继承动物类
10 class Dog extends Animal {
11 //重写父类Animal中的shout()方法,扩大了访问权限
12 public void shout() {
13 super.shout(); //调用父类中的shout()方法
14 System.out.println("汪汪汪……");
15 }
16 public void printName(){
17 System.out.println("名字:"+super.name); //调用父类中的name属性
18 }
19 }
20 // 定义测试类
21 public class Example05 {
22 public static void main(String[] args) {
23 Dog dog = new Dog(); // 创建Dog类的实例对象
24 dog.shout(); // 调用dog重写的shout()方法
25 dog.printName(); // 调用Dog类中的printName()方法
26 }
27 }
第2~8行代码定义了一个Animal类,并在Animal类中定义了name属性和shout()方法。
第10~19行代码定义了Dog类并继承了Animal类。在Dog类的shout()方法中使用“super.shout()”调用了父类被重写的shout()方法。在printName()方法中使用“super.name”访问父类的成员变量name。
运行结果中可以看出,子类通过super关键字可以成功地访问父类成员变量和成员方法。
通过super()调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次。
1.1 为什么需要super
-
初始化父类成分:在Java中,任何一个类的构造过程首先需要完成其父类的构造,保证父类成员的初始化。通过在子类构造方法中显式调用
super()
,可以调用父类的无参构造方法;如果父类没有无参构造方法,则必须显式调用父类的其他构造方法,并传递适当的参数。 -
构造方法不被继承:由于构造方法不同于普通方法,它们不会被子类继承,因此子类不能直接访问父类的构造方法。使用
super
是完成父类初始化的唯一方式。 -
顺序性:构造对象时,初始化的顺序非常重要。Java确保这一过程的顺序性和完整性,即先初始化父类,再初始化子类,以保证对象的完整性.
1.2 super
的使用方式
-
无参构造:如果父类有一个无参构造方法,子类的构造方法中可以不显式调用
super()
,因为Java编译器会自动插入对父类无参构造方法的调用。如果显式写出来,它必须是子类构造方法的第一条语句。 -
有参构造:如果父类仅有有参构造方法,子类的构造方法必须通过
super
关键字显式调用父类的构造方法,并且传递必要的参数。同样,这个调用必须是子类构造方法的第一条语句。
2.final关键字
2.1 定义
final的英文意思是“最终”。在Java中,可以使用final关键字声明类、属性、方法,在声明时需要注意以下几点:
(1)使用final修饰的类不能有子类。
(2)使用final修饰的方法不能被子类重写。
(3)使用final修饰的变量(成员变量和局部变量)是常量,常量不可修改。
修饰类:当一个类被声明为 final 时,意味着这个类是最终的,不能被继承。因此,final 类不能有子类,其方法也不能被子类重写。
修饰方法:当一个方法被声明为 final 时,意味着这个方法是最终的,不能被子类重写(覆盖)。
修饰变量:对于变量,final 表示这个变量的值只能被赋值一次,即它是一个常量。一旦赋予初始值,就不能再更改。
2.2 final关键字——编程体验
修饰类:设计一个 `final` 类 `Person`,包含 `name` 和 `age` 两个私有成员变量,以及构造方法、`getName()` 和 `getAge()` 方法。
要求:使用final关键字禁止继承 `Person` 类。
final class ClassName {
// 类的内容
}
修饰方法:设计一个 `final` 类 `Circle`,包含半径 `radius` 和 `final` 方法 `calculateArea()` 用于计算圆的面积。创建一个 `Main` 类,在其 `main` 方法中实例化 `Circle` 对象并调用 `calculateArea()` 方法。
class ClassName {
final returnType methodName(parameters) {
// 方法体
}
}
修饰变量:设计一个 `final` 类 `Constants`,包含 `final` 常量 `PI` 和 `E`,分别表示圆周率和自然对数的值。编写一个程序使用这些常量进行数学计算。
final dataType VARIABLE_NAME = value;
3.static关键字
在Java中,static
关键字是一个非常重要的元素,它可以用来声明类的成员变量和方法,使它们成为类的静态成分。使用static
声明的成员属于类本身,而不是类的某个对象。这意味着你可以在没有创建类实例的情况下访问这些成员。static
关键字主要用在四个地方:静态变量、静态方法、静态代码块和静态内部类。
3.1 静态变量(Static Variables)
静态变量也称为类变量,属于类本身,所有实例共享同一个静态变量。如果某个实例修改了静态变量的值,这个修改会影响到类的所有实例。
class MyClass {
static int staticVariable;
void method() {
staticVariable = 10; // 直接访问静态变量
}
}
3.2 静态方法(Static Methods)
静态方法属于类,而不是类的实例。这意味着你可以不创建对象就调用静态方法。静态方法只能直接访问所属类的其他静态成员,不能直接访问非静态成员。
class MyClass {
static void staticMethod() {
System.out.println("This is a static method.");
}
}
3.3 静态代码块(Static Blocks)
静态代码块用于初始化类的静态变量。静态代码块在类加载到JVM时自动执行一次。
class MyClass {
static int staticVariable;
static {
staticVariable = 10; // 初始化静态变量
System.out.println("Static block is executed.");
}
}
3.4 静态内部类(Static Inner Classes)
静态内部类是定义在另一个类内部的静态类。与非静态内部类不同,静态内部类不需要对外部类的实例的引用就可以被实例化,并且它只能访问外部类的静态成员。
class OuterClass {
static class StaticInnerClass {
void method() {
System.out.println("Method of static inner class.");
}
}
}
3.5注意事项
- 静态方法不能使用
this
关键字,因为this
引用当前对象,而静态方法在没有对象的情况下也能被调用。 - 静态成员被所有实例共享,因此在设计类时需要谨慎使用静态变量,以避免不希望的数据共享。
- 静态方法和变量可以通过类名直接访问,也可以通过对象访问(不推荐,容易引起误解)。
静态成员在某些情况下非常有用,比如当你需要一个全局变量或全局方法可以被所有实例共享时。然而,过度使用静态成员可能会导致代码难以理解和维护,特别是在大型项目中。