Java中的final关键字
final关键字用于不同的上下文。首先, final是一个非访问修饰符,仅适用于变量、方法或类。以下是使用 final 的不同上下文。
最终变量
当一个变量用final 关键字声明时,它的值不能被修改,本质上是一个常量。这也意味着您必须初始化最终变量。如果最终变量是引用,这意味着该变量不能重新绑定以引用另一个对象,但该引用变量指向的对象的内部状态可以更改,即您可以在最终数组中添加或删除元素,或者最后的集合。用下划线分隔单词是一个很好的做法,用所有大写字母表示最终变量。
插图:
final int THRESHOLD = 5;
// Final variable
final int THRESHOLD;
// Blank final variable
static final double PI = 3.141592653589793;
// Final static variable PI
static final double PI;
// Blank final static variable
初始化最终变量
我们必须初始化一个 final 变量,否则编译器会抛出编译时错误。最终变量只能通过初始化程序或赋值语句初始化一次。初始化 final 变量的三种方法:
- 您可以在声明最终变量时对其进行初始化。这种方法是最常见的。如果最终变量在声明时未初始化,则称为空白最终变量。以下是初始化空白最终变量的两种方法。
- 一个空白的 final 变量可以在实例初始化块或构造函数中初始化。如果您的类中有多个构造函数,则必须在所有构造函数中对其进行初始化,否则将引发编译时错误。
- 可以在静态块内初始化一个空白的最终静态变量。
让我们看看这两种初始化最终变量的不同方式:
Java
// Java Program to demonstrate Different
// Ways of Initializing a final Variable
// Main class
class GFG {
// a final variable
// direct initialize
final int THRESHOLD = 5;
// a blank final variable
final int CAPACITY;
// another blank final variable
final int MINIMUM;
// a final static variable PI
// direct initialize
static final double PI = 3.141592653589793;
// a blank final static variable
static final double EULERCONSTANT;
// instance initializer block for
// initializing CAPACITY
{
CAPACITY = 25;
}
// static initializer block for
// initializing EULERCONSTANT
static{
EULERCONSTANT = 2.3;
}
// constructor for initializing MINIMUM
// Note that if there are more than one
// constructor, you must initialize MINIMUM
// in them also
public GFG()
{
MINIMUM = -1;
}
}
Java
// Java Program to demonstrate
// Reference of Final Variable
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Creating sn object of StringBuilder class
// Final reference variable
final StringBuilder sb = new StringBuilder("Geeks");
// Printing the element in StringBuilder object
System.out.println(sb);
// changing internal state of object reference by
// final reference variable sb
sb.append("ForGeeks");
// Again printing the element in StringBuilder
// object after appending above element in it
System.out.println(sb);
}
}
Java
// Java Program to Demonstrate Re-assigning
// Final Variable will throw Compile-time Error
// Main class
class GFG {
// Declaring and customly initializing
// static final variable
static final int CAPACITY = 4;
// Main driver method
public static void main(String args[])
{
// Re-assigning final variable
// will throw compile-time error
CAPACITY = 5;
}
}
Java
// Java program to demonstrate
// local final variable
// Main class
class GFG {
// Main driver method
public static void main(String args[])
{
// Declaring local final variable
final int i;
// Now initializing it with integer value
i = 20;
// Printing the value on console
System.out.println(i);
}
}
Java
// Java Program to demonstrate Final
// with for-each Statement
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring and initializing
// custom integer array
int arr[] = { 1, 2, 3 };
// final with for-each statement
// legal statement
for (final int i : arr)
System.out.print(i + " ");
}
}
Geeks 上面的代码中没有 main 方法,因为它只是为了说明目的,以便更好地理解以得出结论:
观察 1:何时使用最终变量?
普通变量和最终变量之间的唯一区别是我们可以将值重新分配给普通变量,但一旦分配,我们就无法更改最终变量的值。因此,最终变量必须仅用于我们希望在整个程序执行过程中保持不变的值。
观察 2:引用最终变量?
当最终变量是对对象的引用时,这个最终变量称为引用最终变量。例如,最终的 StringBuffer 变量如下定义:
final StringBuffer sb;
众所周知,最终变量不能重新分配。但是在引用最终变量的情况下,可以更改该引用变量指向的对象的内部状态。请注意,这不是重新分配。 final的这种性质称为非传递性。要了解对象的内部状态是什么意思,如下例所示:
示例 1:
Java
// Java Program to demonstrate
// Reference of Final Variable
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Creating sn object of StringBuilder class
// Final reference variable
final StringBuilder sb = new StringBuilder("Geeks");
// Printing the element in StringBuilder object
System.out.println(sb);
// changing internal state of object reference by
// final reference variable sb
sb.append("ForGeeks");
// Again printing the element in StringBuilder
// object after appending above element in it
System.out.println(sb);
}
}
Geeks
GeeksForGeeks
非传递性属性也适用于数组,因为数组是Java中的对象。带有final 关键字的数组也称为 final 数组。
Note: As discussed above, a final variable cannot be reassign, doing it will throw compile-time error.
示例 2:
Java
// Java Program to Demonstrate Re-assigning
// Final Variable will throw Compile-time Error
// Main class
class GFG {
// Declaring and customly initializing
// static final variable
static final int CAPACITY = 4;
// Main driver method
public static void main(String args[])
{
// Re-assigning final variable
// will throw compile-time error
CAPACITY = 5;
}
}
输出:
Remember: When a final variable is created inside a method/constructor/block, it is called local final variable, and it must initialize once where it is created. See below program for local final variable.
例子:
Java
// Java program to demonstrate
// local final variable
// Main class
class GFG {
// Main driver method
public static void main(String args[])
{
// Declaring local final variable
final int i;
// Now initializing it with integer value
i = 20;
// Printing the value on console
System.out.println(i);
}
}
20
在继续前进之前,请记住以下关键点,如下所示:
- 注意 C++ const变量和Java final变量之间的区别。 C++ 中的 const 变量在声明时必须赋值。对于Java中的 final 变量,正如我们在上面的示例中看到的那样,它不是必需的。最终变量可以稍后赋值,但只能赋值一次。
- final with foreach 循环:final with for-each 语句是合法的语句。
例子:
Java
// Java Program to demonstrate Final
// with for-each Statement
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring and initializing
// custom integer array
int arr[] = { 1, 2, 3 };
// final with for-each statement
// legal statement
for (final int i : arr)
System.out.print(i + " ");
}
}
1 2 3
输出解释:由于“ i”变量随着循环的每次迭代而超出范围,实际上每次迭代都是重新声明,允许使用相同的标记(即i)来表示多个变量。
期末班
当一个类用final关键字声明时,它被称为 final 类。最终类不能扩展(继承)。
final类有两种用途:
用法1:一个肯定是为了防止继承,因为最终类不能扩展。例如,Integer、Float 等所有 Wrapper 类都是 final 类。我们不能扩展它们。
final class A
{
// methods and fields
}
// The following class is illegal
class B extends A
{
// COMPILE-ERROR! Can't subclass A
}
用法 2: final 与类的另一个用途是创建一个不可变的类,如预定义的 String 类。如果不将其定为最终类,就无法使类不可变。
最终方法
当一个方法用final关键字声明时,它被称为 final 方法。 final 方法不能被覆盖。 Object 类就是这样做的——它的一些方法是最终的。我们必须使用 final 关键字声明方法,我们需要在所有派生类中遵循相同的实现。
插图:带有方法的最终关键字
class A
{
final void m1()
{
System.out.println("This is a final method.");
}
}
class B extends A
{
void m1()
{
// Compile-error! We can not override
System.out.println("Illegal!");
}
}
有关 final 方法和 final 类的更多示例和行为,请参阅将 final 用于继承。有关 final 和 abstract 之间的区别,请参阅Java文章中的摘要。
相关面试题(重要): Java中final、finally和finalize的区别