赞
踩
大家好,我是栗筝i,从 2022 年 10 月份开始,我便开始致力于对 Java 技术栈进行全面而细致的梳理。这一过程,不仅是对我个人学习历程的回顾和总结,更是希望能够为各位提供一份参考。因此得到了很多读者的正面反馈。
而在 2023 年 10 月份开始,我将推出 Java 面试题/知识点系列内容,期望对大家有所助益,让我们一起提升。
今天与您分享的,是 Java 基础知识面试题系列的总结篇(上篇),我诚挚地希望它能为您带来启发,并在您的职业生涯中起到助益作用。衷心感谢每一位朋友的关注与支持。
解答:
Java 是一种高级、面向对象的编程语言,由 Sun Microsystems(现在的 Oracle Corporation)在 1995 年发布。它最初被设计用于小型、网络环境下的应用程序开发,但随着时间的推移,Java 发展成为了一个功能强大的全面编程语言,广泛应用于开发桌面、网站、服务端应用、移动应用和嵌入式系统。
以下是 Java 的一些核心特性:
总之,Java 以其强大的功能、稳定的跨平台性能和广泛的应用领域,成为了当今世界上最流行的编程语言之一。
解答:
Java 平台是一个广泛的技术框架,它提供了开发和运行 Java 编程语言应用程序的环境。Java 平台不仅包括编程语言本身,还包括一系列的执行环境、API 和相关的技术标准。这个平台的核心组件可以分为以下几个部分:
Java 语言:Java 语言是一种面向对象、类似 C++ 的编程语言,但设计上更简洁、更安全。
Java 虚拟机(JVM):JVM 是一个抽象的计算机,它运行编译后的 Java 程序字节码,并且能够在不同的硬件和操作系统平台之间提供一致的运行环境。这就是 Java 平台实现“一次编写,到处运行”(Write Once, Run Anywhere)特性的关键。
Java API:Java 提供了一组丰富的标准类库(API),覆盖从基本数据结构到网络通信的各个方面。
Java 开发工具包(JDK):JDK 包括 JVM、编译器、调试器以及其他工具,这些工具被用于开发 Java 应用程序。
Java 平台通常可以分为以下几个不同的版本,以满足不同类型的设备和应用需求:
Java Standard Edition (Java SE):这是最常用的 Java 平台版本,用于开发和部署桌面、服务器和嵌入式应用程序。它包括 JVM 标准实现和核心 API 库。
Java Enterprise Edition (Java EE):在 Java SE 的基础上,Java EE 添加了支持企业级应用程序的 API,这些 API 包括网络服务、Web 服务和事务管理等。
Java Micro Edition (Java ME):Java ME 针对嵌入式和移动设备提供了一个优化的运行时环境,支持更小的内存和处理能力。
JavaFX:用于创建丰富的客户端用户界面的库和工具,现在通常被包括在 Java SE 中。
Java 平台的这些组件协同工作,提供了一个完整、稳定、跨平台的开发环境,使得 Java 成为了开发各种应用程序的流行选择。
解答:
在 Java 中,基本数据类型(也称为原始数据类型)是最基础的数据类型,它们不是对象,也不属于任何类。这些类型代表了简单的数值和字符。Java 定义了八种基本数据类型,分为四类:
整型:byte
:占用 1 字节,范围从 -128 到 127。short
:占用 2 字节,范围从 -32,768 到 32,767。int
:占用 4 字节,范围从 -231 到 231-1。在 Java 中,int
是默认的整数类型。long
:占用 8 字节,范围从 -263 到 263-1。
浮点型:float
:占用 4 字节,范围覆盖大约 ±3.40282347E+38F(有效位数为 6~7 位十进制数)。double
:占用 8 字节,范围覆盖大约 ±1.79769313486231570E+308(有效位数为 15 位十进制数)。
字符型:char
:占用 2 字节,用于表示单个 Unicode 字符,范围从 ‘\u0000’(即为 0)到 ‘\uffff’(即为 65,535)。
布尔型:boolean
:Java 语言规范中没有明确指定 boolean
类型的大小,但是它只有两个可能的值:true
和 false
。
每种基本数据类型都有其对应的包装类,使得可以将这些基本类型当作对象来处理。例如,int
类型的包装类是 Integer
,double
类型的包装类是 Double
,依此类推。包装类提供了一些有用的方法和属性,也允许基本数据类型在需要对象的地方使用,如在集合类中。
解答:
在 Java 中,自动装箱(Autoboxing)和拆箱(Unboxing)是自 Java 5 开始引入的特性,它们允许基本数据类型和它们对应的对象包装类型之间自动转换。
自动装箱 是指将基本数据类型自动转换为对应的包装类对象的过程。例如,当你将一个 int
类型的值赋给一个 Integer
类的对象时,Java 编译器会自动将 int
值转换为 Integer
对象。这样做的好处是简化了代码,使得开发者不需要显式地进行转换。
Integer iObj = 10; // 自动装箱,编译器会转换为 Integer iObj = Integer.valueOf(10);
拆箱 是指将包装类对象转换回基本数据类型的过程。例如,当你从一个 Integer
类的对象中取出基本 int
类型的值时,Java 编译器会自动进行转换。
int i = iObj; // 自动拆箱,编译器会转换为 int i = iObj.intValue();
这两个过程大大简化了编程,因为在很多情况下,你不需要显式地进行对象的包装和拆包。然而,需要注意的是,在某些情况下,自动装箱和拆箱可能会引入不必要的对象创建,从而影响性能。此外,拆箱操作可能会抛出 NullPointerException
,如果尝试拆箱的包装对象是 null
的话。
例如,下面这段代码就会引发异常:
Integer nullInteger = null;
int i = nullInteger; // 会抛出 NullPointerException
因此,虽然自动装箱和拆箱提供了便利,开发者还是需要留意潜在的性能问题和空指针异常的风险。
解答:
在 Java 中,类型转换主要有两种形式:自动类型转换(也称为隐式转换)和强制类型转换(显式转换)。
自动类型转换:当两种不同的数据类型进行运算时,如果数据类型大小不一致,那么较小的数据类型会自动转换为较大的数据类型,这个过程叫做自动类型转换。自动类型转换遵循一定的规则,通常发生在有明确转换规则且不会导致信息损失的场景中。例如,int
可以自动转换为 long
,float
可以自动转换为 double
。示例:
int i = 100;
long l = i; // 自动类型转换,int 转换为 long
float f = l; // 自动类型转换,long 转换为 float
强制类型转换:当需要将一个数据类型强制转换为另一个较小的数据类型时,需要使用强制类型转换。这是显式的转换,可能会导致信息丢失或精度降低。强制类型转换需要在值前加上希望转换到的类型。示例:
double d = 100.04;
long l = (long) d; // 强制类型转换,double 转换为 long,可能丢失小数部分
int i = (int) l; // 强制类型转换,long 转换为 int
在使用强制类型转换时,开发者需要意识到可能存在的数据丢失风险,并在必要时进行相应的处理。
解答:
Java 的编译和执行过程涉及几个关键步骤,具体如下:
编写源代码:开发者使用文本编辑器或集成开发环境(IDE)编写以 .java
为扩展名的源代码文件。
编译源代码:使用 Java 编译器 javac
将 .java
文件编译成 Java 字节码(.class
文件)。字节码是一种中间代码,它不同于机器码,是一种平台无关的代码。
javac FileName.java
加载字节码:当运行程序时,Java 虚拟机(JVM)的类加载器负责将 .class
文件加载到内存中。
字节码验证:加载到 JVM 的字节码会经过验证器检查,确保字节码安全并符合 Java 语言规范,防止运行时出现安全风险。
执行字节码:经过验证的字节码被送到执行引擎。JVM 中的执行引擎可以采用解释执行(逐条解释字节码),也可以通过即时编译器(JIT)将字节码编译成本地机器码提高效率。
java FileName
运行时处理:在程序执行过程中,JVM 会进行内存管理、垃圾回收以及其他与运行时环境相关的操作。
整个过程中,JVM 的作用至关重要,它不仅能够执行字节码,还提供了与操作系统无关的运行环境,使 Java 程序具有跨平台性,即"一次编写,到处运行"(Write Once, Run Anywhere)。
要注意的是,这个过程可能稍有不同,比如当使用即时编译(JIT)的时候,执行过程会涉及把字节码转换为机器码,这通常在程序运行时动态进行。还有一些情况下,可以将字节码预先编译成本地代码来提高性能,这通常是通过 Java 的 Ahead-Of-Time (AOT) 编译器来实现的。
解答:
在 Java 中,包(package
)是用来组织类和接口的一种机制。使用包可以将功能相似或相关的类和接口组织在一起,这样做不仅有助于代码的模块化,还能避免类名冲突。包在物理上对应于文件系统的目录。用途:
命名空间管理:包为类和接口提供了命名空间,可以防止命名冲突。不同包中可以有同名的类或接口。
访问控制:包可以用来控制类和接口的访问权限。Java 有一种默认的访问级别(默认访问级别),如果类或类成员没有明确的访问级别指定,它们只能被同一包内的类访问。
可重用性:包可以包含多个类和接口,可以被不同的程序和模块重用。
易于维护:包提供了一种将代码逻辑上组织为独立模块的方式,这使得代码更易于理解和维护。
声明包:在 Java 源文件中,通过在文件顶部使用 package
关键字来声明包。例如:
package com.example.myapp;
这行代码声明了一个包名为 com.example.myapp
的包。这个包可以包含多个类和接口。
使用包中的类:如果要在某个类中使用其他包中的类或接口,需要使用 import
关键字导入相应的包。例如:
import com.example.myapp.SomeClass;
这行代码导入了 com.example.myapp
包中的 SomeClass
类。
如果导入同一包中的所有类和接口,可以使用星号(*
)作为通配符:
import com.example.myapp.*;
包结构通常反映了企业的域名,反向写出,以确保全球唯一性,从而避免命名冲突。例如,一个名为 MyApp
的应用,由 example.com
域的企业开发,可能会有一个基础包名 com.example.myapp
。
解答:
在 Java 中,一个类是定义对象属性和行为的蓝图或原型。定义一个类涉及声明类的名称、属性(也称为字段或成员变量)和方法。以下是一个简单的 Java 类的定义示例:
public class Car {
// 成员变量(属性)
private String color;
private String brand;
private int year;
// 构造器
public Car(String color, String brand, int year) {
this.color = color;
this.brand = brand;
this.year = year;
}
// 方法
public void startEngine() {
System.out.println("引擎启动了!");
}
// 更多的方法和逻辑可以在这里定义...
// Getter 和 Setter 方法
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
// 对于 brand 和 year 同样可以定义 Getter 和 Setter 方法
}
这个类有以下组成部分:
类声明:public class Car { ... }
中 public
是一个访问修饰符,表示这个类是公开的,可以被其他类访问。Car
是类名,Java 中类名通常采用大驼峰命名规则。
成员变量:color
, brand
, 和 year
是类的属性,定义了汽车的几个基本特征。这些变量被声明为 private
,这意味着它们仅在类内部访问,以保证封装性。
构造器:构造器是一种特殊的方法,名称与类名相同。它在创建类的实例时被调用,用于初始化对象。
方法:startEngine
是一个定义类行为的方法。你可以定义更多的方法来提供类的功能。
Getter 和 Setter 方法:提供了获取(get
)和设置(set
)成员变量值的方法。这些方法是公共的(public
),允许从类的外部访问和修改私有变量的值,同时仍然保持封装性。
通过定义类,你可以创建具有特定状态和行为的对象。在 Java 中创建 Car
类的实例,你可以这样做:
Car myCar = new Car("红色", "丰田", 2020);
myCar.startEngine();
以上代码创建了一个 Car
对象,并调用了其 startEngine
方法。
解答:
在 Java 中,创建对象的过程通常涉及以下两个步骤:
new
关键字来创建一个类的实例。这里是一个创建对象的示例,假设我们有一个 Car
类:
// 假设已经定义了一个Car类
public class Car {
private String color;
// 构造器
public Car(String carColor) {
// 初始化颜色属性
color = carColor;
}
// 定义其他方法和逻辑
}
// 在另一个类中或者同一个类的方法中创建Car对象
public class Main {
public static void main(String[] args) {
// 声明并实例化Car类的对象
Car myCar = new Car("Blue");
// 使用myCar对象的引用来调用方法或访问其属性等...
}
}
在这个例子中:
Car myCar
声明了一个类型为 Car
的变量 myCar
,这个变量用来引用 Car
类型的对象。new Car("Blue")
通过调用 Car
类的构造器 Car(String carColor)
来创建一个新的 Car
对象实例,并将其内存地址赋值给 myCar
变量。此时,对象的 color
属性被初始化为字符串 "Blue"
。myCar
变量,你可以调用 Car
对象的任何公共方法和变量。实际使用中,你可能需要根据类的构造器传入相应的参数来创建对象,上述示例中传入的 "Blue"
就是在创建 Car
对象时设置的颜色属性。
解答:
面向对象编程(Object-Oriented Programming,简称 OOP)是一种编程范式,它使用 “对象” 来设计软件和创建可重用的代码。
在 OOP 中,每个对象都是一个特定类的实例。类定义了对象的属性(也称为数据成员或字段)和方法(也称为成员函数或行为)。对象的属性是用来存储数据的,而方法则是用来执行任务的。
OOP 主要有以下四个基本特性:
封装:封装是将对象的状态(属性)和行为(方法)包装在一起的过程。封装可以隐藏对象的内部实现细节,只暴露出需要的信息。
继承:继承是从已有的类派生出新的类的过程。新的类(子类)可以继承父类的属性和方法,并可以添加新的属性和方法,也可以重写父类的方法。
多态:多态是指允许一个接口使用多种实际类型的能力。多态可以使得代码更加灵活和可扩展。
抽象:抽象是将复杂的系统简化的过程。我们可以通过创建抽象类或接口来定义对象的通用结构。
面向对象编程的主要目标是提高软件的可重用性、灵活性和可维护性。
解答:
封装是面向对象编程(OOP)的一个核心概念,它指的是将对象的状态(属性)和行为(方法)组合到一个高度组织的对象中,并对对象的内部实现进行隐藏,仅对外公开一个清晰定义的接口。
封装的主要优点包括:
在 Java 中,封装可以通过以下方式实现:
通过访问修饰符控制访问级别:使用 private
, protected
, public
等访问修饰符来定义类成员的可见性。通常,属性被设置为 private
,这意味着它们只能被类的方法访问和修改,而不是直接从类外部访问。
提供公共的 getter 和 setter 方法:如果需要从类外部读取或修改私有属性,则可以通过定义公共的 getter 方法来访问属性值,以及通过 setter 方法来修改属性值。这些方法提供了对属性的受控访问,你可以在这些方法内部添加逻辑,例如验证数据,或者在属性值变化时执行某些操作。
下面是一个简单的 Java 类来演示封装:
public class Person {
private String name; // 私有属性,外部无法直接访问
private int age; // 私有属性,外部无法直接访问
// 构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// name 的 getter 方法
public String getName() {
return name;
}
// name 的 setter 方法
public void setName(String name) {
this.name = name;
}
// age 的 getter 方法
public int getAge() {
return age;
}
// age 的 setter 方法
public void setAge(int age) {
if (age > 0) {
this.age = age;
}
}
}
在这个 Person
类中,name
和 age
属性是私有的,外部代码不能直接访问它们。但是,通过公共的 getter 和 setter 方法,外部代码可以在对象授权的情况下读取和修改这些属性的值。这种方式加强了属性的安全性,并提供了灵活的属性管理机制。
解答:
继承是面向对象编程(OOP)的另一个基本概念,允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。继承提供了以下几个主要优点:
在 Java 中,继承是通过使用 extends
关键字来实现的。例如:
public class Vehicle {
// 父类的属性和方法
}
public class Car extends Vehicle {
// Car 类继承了 Vehicle 类的属性和方法
}
这里,Car
类就继承了 Vehicle
类的所有公有(public)和保护(protected)成员。私有成员(private)虽然也被继承,但是不可直接访问,只能通过父类提供的公有或保护方法来访问。
关于多重继承:Java 不支持通过类的方式进行多重继承,即一个类不能有多个直接父类。这是因为多重继承可能会导致复杂性显著增加,特别是当多个父类有相同的方法时,子类可能不明确应该继承哪个父类的方法。
为了解决这个问题,Java 提供了接口(Interface)的概念。一个类可以实现(implements)多个接口,并且必须实现接口中所有的抽象方法。接口允许 Java 以不同的方式实现多继承的部分特征。
public interface Flyable {
void fly();
}
public interface Floatable {
void floatOnWater();
}
public class Seaplane extends Vehicle implements Flyable, Floatable {
public void fly() {
// 实现飞行的代码
}
public void floatOnWater() {
// 实现在水面漂浮的代码
}
}
在这个例子中,Seaplane
类继承自 Vehicle
类,并且实现了 Flyable
和 Floatable
两个接口,从而在单继承的限制下实现了多继承的效果。
解答:
多态是面向对象编程中的一个基本概念,指的是同一个行为具有多个不同表现形式或状态。在 Java 中,多态表现为以下两种形式:
编译时多态(或静态多态):这种多态是通过方法重载(Overloading)实现的。重载发生在同一个类中,当有多个方法名相同但参数列表不同时,编译器根据方法签名在编译期就决定了会调用哪个方法。这种多态是在编译时确定的,因此称为静态多态。
class Demo {
void display(int a) {
System.out.println("Integer: " + a);
}
void display(int a, int b) {
System.out.println("Two Integers: " + a + " and " + b);
}
void display(String a) {
System.out.println("String: " + a);
}
}
// 使用
Demo d = new Demo();
d.display(1); // 调用第一个方法
d.display(1, 2); // 调用第二个方法
d.display("Hello"); // 调用第三个方法
运行时多态(或动态多态):这种多态是通过方法重写(Overriding)实现的。当子类提供与父类具有相同名称和参数列表的方法时,子类的方法会覆盖父类的方法。运行时,根据对象的实际类型来决定调用哪个方法,这就需要动态绑定。
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
// 使用
Animal animal = new Dog();
animal.sound(); // 输出 "Dog barks" 而不是 "Animal makes a sound"
在这个例子中,尽管 animal
的编译类型是 Animal
,但它的运行时类型是 Dog
,因此调用的是 Dog
类中重写的 sound
方法。
在 Java 中,所有的类都是继承自 java.lang.Object
。因为多态的存在,任何时候我们都可以将子类的实例赋值给父类类型的变量,这种向上转型(Upcasting)是自动的。向下转型(Downcasting)则需要显式地进行类型转换,但它是不安全的,因为它要求我们必须确保实例确实属于目标类型。
多态的存在让 Java 程序设计更加灵活和可扩展,我们可以通过抽象类和接口来设计方法和类,这样就可以在不同的实现之间切换,而不用修改大量代码。
解答:
访问修饰符(Access Modifiers)在 Java 中定义了类、变量、方法和构造器的访问控制。它们决定了一个成员(例如字段或方法)的可访问性。Java 提供了四种访问级别:
private - 私有的访问级别,被标记为 private 的成员只能在声明它的类中被访问。
public class ClassA {
private int privateVariable = 5;
}
default (又称为 package-private) - 如果没有指定访问修饰符,则默认使用 default 访问级别。这样的成员只能在同一个包内的类中被访问。
class ClassB {
int defaultVariable = 10;
}
protected - 被 protected 修饰的成员可以被同一个包内的类以及其他包中的子类访问。
public class ClassC {
protected int protectedVariable = 15;
}
public - 公共的访问级别,被 public 修饰的成员可以在任何地方被访问。
public class ClassD {
public int publicVariable = 20;
}
每个级别都提供了不同的访问控制,使得程序员可以在封装和继承中做出合适的选择,以便保护数据并提供接口。在设计 Java 类时,合理使用这些访问修饰符是面向对象设计原则的一个重要方面。
解答:
在 Java 中,this
和 super
关键字用于引用对象的当前实例和当前实例的父类上下文。
this 关键字,this
关键字在 Java 中用于:
以下是 this
关键字用法的例子:
public class MyClass {
int variable;
MyClass(int variable) {
// 引用当前实例的成员变量
this.variable = variable;
}
void myMethod() {
// 将当前对象作为参数传递
someMethod(this);
}
void someMethod(MyClass instance) {
// 处理 instance
}
MyClass() {
// 调用另一个构造函数
this(0);
}
}
super 关键字,super
关键字在 Java 中用于:
以下是 super
关键字用法的例子:
class ParentClass {
int variable = 5;
}
class ChildClass extends ParentClass {
int variable = 10;
void show() {
// 访问当前类的成员变量
System.out.println(variable);
// 访问父类的成员变量
System.out.println(super.variable);
}
ChildClass() {
// 调用父类的构造器
super();
}
@Override
void parentMethod() {
// 调用父类的方法
super.parentMethod();
}
}
在执行子类与父类有相同成员时,super
可以明确指出是调用父类的成员。在构造子类的实例时,如果想调用父类的构造函数(无论是默认的还是带参数的),可以使用 super()
来实现。通常,如果子类的构造器没有显式调用 super()
,编译器会插入一个无参的 super()
调用。
解答:
方法重载和方法重写是 Java 中两种重要的特性。
方法重载(Overloading):在同一个类中,如果有多个方法的名称相同,但参数列表不同(参数的数量、类型或顺序不同),那么这些方法就被称为重载方法。方法重载允许我们使用同一个方法名执行不同的操作。
方法重写(Overriding):在子类中,如果有一个方法与父类的某个方法的名称、参数列表和返回类型都相同,那么这个方法就被称为重写方法。方法重写允许我们在子类中改变父类的行为。
方法重载和方法重写的主要区别如下:
总的来说,方法重载是静态的,它在编译时就已经确定了具体调用哪个方法;而方法重写是动态的,它在运行时才确定具体调用哪个方法。
解答:
接口(Interface)和抽象类(Abstract Class)都是面向对象编程中的高级特性,它们都不能直接实例化,需要通过子类或实现类来实例化。
接口:接口是一种完全抽象的类,它只包含抽象方法(在 Java 8 之后,接口也可以包含默认方法和静态方法)。一个类可以实现多个接口,实现接口的类必须实现接口中的所有方法。
抽象类:抽象类是一种特殊的类,它可以包含抽象方法和非抽象方法。抽象方法是没有实现的方法,需要子类来提供实现。一个类只能继承一个抽象类。
接口和抽象类的主要区别如下:
总的来说,接口更多地被用来定义行为(即方法),而抽象类既可以定义行为,也可以定义状态(即属性)。在设计类的层次结构时,我们通常会使用抽象类,而在定义一组相关的行为时,我们通常会使用接口。
解答:
构造函数是一种特殊的方法,用于初始化新创建的对象。在 Java 中,构造函数的名称必须与类名相同,并且没有返回类型。
构造函数与普通方法的主要区别如下:
名称:构造函数的名称必须与类名相同,而普通方法可以有任何有效的标识符作为名称。
返回类型:构造函数没有返回类型,而普通方法必须有返回类型。
调用方式:构造函数在创建对象时自动调用,无需手动调用。而普通方法需要手动调用。
用途:构造函数主要用于初始化对象的状态(即设置属性的初始值)。而普通方法用于描述对象的行为。
例如,以下是一个简单的类,其中包含一个构造函数和一个普通方法:
public class MyClass {
private int value;
// 构造函数
public MyClass(int value) {
this.value = value;
}
// 普通方法
public void displayValue() {
System.out.println("Value: " + value);
}
}
在这个例子中,MyClass
的构造函数接受一个参数 value
,并将其赋值给对象的 value
属性。displayValue
是一个普通方法,用于打印对象的 value
属性。
解答:
static
是 Java 中的一个关键字,它可以用来修饰类的成员(成员变量和成员方法),也可以用来创建静态代码块。
static
关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static
变量。static
关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。static
关键字还可以形成静态代码块以优化程序性能。static
代码块在类加载的时候就运行了,而且只运行一次,同时运行时机是在构造函数之前。总的来说,static
关键字主要有以下几个作用:
解答:
在 Java 中,final
是一个关键字,它可以用来修饰类、方法和变量。
final
类:如果一个类被声明为 final
,那么它不能被继承。这意味着没有其他类可以是这个类的子类。final
类通常表示最终的、不可改变的实体,例如 String
类和 Integer
类都是 final
类。
final
方法:如果一个方法被声明为 final
,那么它不能被子类重写。但是,子类可以继承 final
方法。
final
变量:如果一个变量被声明为 final
,那么它的值就不能被修改,它就成为了一个常量。我们必须在声明 final
变量时或在构造函数中初始化它。
final
关键字提供了一种方式,可以明确表示某个实体不应该被改变。这对于创建不可变的对象和防止意外修改非常有用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。