文章目录
代码块
概述
代码块是指由一对大括号 {}
包围的代码段。根据代码块所在的位置和用途不同,它们在程序中的执行时机和作用也有所不同。常见的代码块类型包括:
- 局部代码块
- 构造代码块
- 静态代码块
- 同步代码块(多线程)
局部代码块
-
格式:由一对大括号
{}
包围的代码段。 -
位置:位于方法内部。
-
作用:
- 限定变量的生命周期,其作用域仅限于代码块内部。
- 在局部代码块中声明的变量,只能在该代码块内使用,出了代码块就无法访问。
- 当变量的作用范围结束后,内存会被释放,节省空间。
-
注意事项:
- 局部代码块声明的变量,生命周期较短,一旦超出作用范围就无法访问。
- 局部代码块内可以修改外部变量,修改后的值在代码块结束后依然生效。
代码示例:
public static void main(String[] args) {
int i = 10;
{
System.out.println(i); // 输出: 10
i = 20;
int j = 100;
System.out.println(j); // 输出: 100
}
System.out.println(i); // 输出: 20
// System.out.println(j); // 编译错误:无法访问局部代码块中的变量 j
}
构造代码块
-
格式:由一对大括号
{}
包围的代码段。 -
位置:位于类中方法之外。
-
作用:用于初始化成员变量。
-
执行顺序:
- 在创建对象时执行,由 JVM 自动调用。
- 在构造方法执行之前执行。
- 每次调用构造方法前都会执行一次。
- 如果多个构造方法中有公共的初始化逻辑,可以提取到构造代码块中。
静态代码块【常用】
-
格式:
static { // 静态代码块的内容 }
-
位置:位于类中方法之外。
-
作用:
- 用于初始化静态成员变量。
- 适合执行只需要执行一次的代码,如驱动加载。
-
执行特点:
- 随着类的加载而执行。
- 类只加载一次,静态代码块只执行一次。
- 执行时机早于对象实例化和
main
方法的执行。
继承
继承的概述
- 概念:继承是面向对象编程中子类继承父类属性和方法的机制,使得类与类之间产生继承关系。
- 关键字:
extends
,表示扩展和继承。 - 父类和子类:
- 父类:被继承的类,称为超类或基类。
- 子类:继承父类的类,称为派生类。
代码示例:
-
未使用继承:
// 示例代码省略
-
使用继承:
// 示例代码省略
继承的优缺点
-
优点:
- 提高代码的复用性。
- 提高代码的可维护性。
- 是实现多态的基础。
-
缺点:
- 提高了代码的耦合性。
-
开发原则:
- 高内聚:一个对象应尽可能完成自身的所有任务。
- 低耦合:减少与其他代码的依赖,提高代码的独立性。
继承的注意事项
- 私有成员不能被继承。
- 父类中的私有成员在子类中无法直接访问。
- 构造方法不能被继承。
- 因为构造方法与类名绑定,不同类名的构造方法不兼容。
- 继承设计时应避免仅为部分功能定义继承关系。
继承中成员变量的关系
- 子类和父类中定义不同名称的成员变量时,子类可以访问两者。
- 子类和父类中定义同名成员变量时,访问遵循就近原则。
代码示例:
public class Test01 {
public static void main(String[] args) {
Fu f = new Fu();
System.out.println(f.a); // 输出: 10
Zi z = new Zi();
System.out.println(z.a); // 输出: 100
System.out.println(z.b); // 输出: 20
z.test();
}
}
class Fu {
int a = 10;
int c = 10;
}
class Zi extends Fu {
int b = 20;
int a = 100;
public void test() {
System.out.println(a); // 输出: 100
}
public void test2() {
System.out.println(c); // 输出: 10
}
}
关键字 this
和 super
的详细解释
this
:表示当前对象的引用。super
:表示当前对象父类的引用。
this
和 super
的使用总结
this
表示当前对象的引用。哪个对象调用了方法,this
就指向哪个对象。super
表示当前对象的父类引用。哪个对象调用了方法,super
就指向该对象的父类部分。
继承中构造方法的关系
- 在初始化子类数据之前,必须先完成父类数据的初始化。
- 如果子类构造方法中没有显式调用父类或本类的其他构造方法,系统会默认调用父类的无参构造方法。
- 如果手动调用父类或本类构造方法,系统不会再自动添加构造方法调用。
- 构造方法不能递归调用。
总结
- 子类构造方法必须首先调用父类构造方法。
this
和super
语句必须在构造方法的第一行,不能同时存在。this
和super
不能在非构造方法的非静态成员方法中使用。
方法重写
- 子类可以直接调用父类的方法,也可以重写父类的方法。
- 重写发生在子类和父类中有同名方法的情况下,子类可以改变父类方法的实现。
- 方法重载与重写的区别:
- 重载:同一个类中方法名相同,参数列表不同。
- 重写:子类与父类中方法名相同,参数列表相同。
重写的注意事项
- 私有方法不能被重写。
- 方法在重写时,访问权限不能变得更小。
Java 中继承的特点
- 单继承:Java 支持单继承,不支持多继承,但支持多层继承。
- 多层继承:通过逐层继承,子类可以继承多个祖先类的属性和方法。
final
关键字
final
表示不可更改的含义。final
可修饰类、方法、变量。- 修饰类:表示该类不能被继承。
- 修饰方法:表示该方法不能被重写。
- 修饰变量:表示变量为常量,只能赋值一次。
final
关键字的详细解析
final
关键字在 Java 中有多种应用场景,通过修饰类、方法、或变量,final
能够限制继承、重写或重新赋值,从而增强代码的稳定性和安全性。
1. final
修饰类
当一个类被 final
修饰时,表示该类不能被继承。也就是说,没有其他类能够从这个类派生出子类。
特点:
- 这种设计通常用于保证类的实现不会被改变,常用于工具类或关键的业务类。
代码示例:
public final class UtilityClass {
public static void doSomething() {
System.out.println("Doing something...");
}
}
- 上述代码中,
UtilityClass
类被final
修饰,因此无法被继承。
2. final
修饰方法
当一个方法被 final
修饰时,表示该方法不能被子类重写。
特点:
- 这种设计用于保护方法的实现,防止子类改变方法的行为,确保父类的逻辑一致性。
代码示例:
class Parent {
public final void show() {
System.out.println("This is a final method.");
}
}
class Child extends Parent {
// 下面的代码将会报错,因为父类的 show() 方法是 final 类型,无法被重写
// public void show() {
// System.out.println("Trying to override the final method.");
// }
}
- 上述代码中,
show
方法在父类Parent
中被final
修饰,因此子类Child
无法重写它。
3. final
修饰变量
final
关键字也可以用来修饰变量。修饰后的变量称为常量,只能被赋值一次,且在赋值之后不可再更改。
特点:
- 常用于定义常量值,以确保变量的值在程序运行过程中不会被改变。
代码示例:
public class Constants {
public static final double PI = 3.14159;
public static void main(String[] args) {
// PI = 3.15; // 编译错误,final 变量不能被重新赋值
System.out.println("The value of PI is: " + PI);
}
}
- 上述代码中,
PI
是一个final
变量,因此在赋值后不能被修改。
4. final
修饰引用类型
当 final
修饰的是一个引用类型(例如对象、数组等),表示引用本身不可更改,也就是该引用变量在被赋值之后不能再指向其他对象。但引用所指向的对象的内部状态是可以改变的。
代码示例:
public class FinalReferenceExample {
public static void main(String[] args) {
final int[] numbers = {1, 2, 3};
numbers[0] = 10; // 允许:可以修改数组的内容
// numbers = new int[]{4, 5, 6}; // 编译错误:不能更改 final 引用的指向
for (int num : numbers) {
System.out.println(num);
}
}
}
- 上述代码中,
numbers
数组引用是final
类型,因此无法指向其他数组,但可以修改其内容。
final
关键字的使用场景
-
定义常量:
final
常用于定义不可修改的常量,通常与static
一起使用。
代码示例:
public static final String COMPANY_NAME = "OpenAI";
-
防止类被继承:
- 当一个类不希望被其他类继承时,可以将其声明为
final
。
- 当一个类不希望被其他类继承时,可以将其声明为
-
确保方法不被重写:
- 在一些重要或核心的方法上使用
final
,防止子类破坏父类的逻辑。
- 在一些重要或核心的方法上使用
-
确保变量只赋值一次:
- 在某些情况下,为确保变量不会被意外修改,可以使用
final
来限制其只能被赋值一次。
- 在某些情况下,为确保变量不会被意外修改,可以使用
final
和不变性
通过结合 final
关键字和适当的设计模式,可以创建不可变类,即一旦创建,其状态就无法改变的对象。不可变类在多线程环境中尤其有用,因为它们本质上是线程安全的。
代码示例:
public final class ImmutableClass {
private final String name;
private final int age;
public ImmutableClass(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
- 上述代码中,
ImmutableClass
类是不可变的,因为它的状态在对象创建后无法改变。所有成员变量都是final
,并且没有提供修改它们的方法。
结论
final
关键字在 Java 编程中非常重要,通过合理使用 final
,可以有效地控制类的继承、方法的重写以及变量的赋值,从而增强代码的稳定性、可读性和安全性。在开发过程中,理解并适当地应用 final
,是编写高质量代码的关键步骤之一。