java中有一个关键字——
final
. 它可以应用于类、方法、变量(包括方法参数)。 对于一个类,这意味着该类不能有子类,即 禁止继承。这在创建(不可变)对象时非常有用immutable
,例如声明String
为final
.
public final class String{
}
class SubString extends String{ //Compilation error
}
还应该注意的是,修饰符不能应用于抽象类(带有关键字abstract
),final
因为 这些是相互排斥的概念。对于一个方法final
意味着它不能在子类中被重写。当我们希望原始实现不被覆盖时,这很有用。
public class SuperClass{
public final void printReport(){
System.out.println("Report");
}
}
class SubClass extends SuperClass{
public void printReport(){ //Compilation error
System.out.println("MyReport");
}
}
对于原始类型变量,这意味着一旦分配,值就不能更改。对于引用变量,这意味着一旦分配了对象,对该对象的引用就无法更改。这很重要!链接无法更改,但对象的状态可以更改。随着 java 8 出现了这个概念 - effectively final
. 它仅适用于变量(包括方法参数)。要点是,尽管明显缺少关键字final
,但变量的值在初始化后并没有改变。换句话说,您可以用一个单词替换此类变量,final
而不会出现编译错误。变量可以在本地类 ( )、匿名类 ( )、流 (Stream API) effectively final
中使用。Local Inner Classes
Anonymous Inner Classes
public void someMethod(){
// In the example below, both a and b are effectively final, since the values are set once:
int a = 1;
int b;
if (a == 2) b = 3;
else b = 4;
// c is NOT effectively final because value changes
int c = 10;
c++;
Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
}
现在我们来进行一下采访。毕竟,参加 JavaRush 课程的目标是成为一名 Java 开发人员并获得一份有趣且高薪的工作。 那么,让我们开始吧。
-
当数组被声明时你能说什么
final
? -
已知类
String
是immutable
,类被声明final
,字符串的值存储在数组中char
,数组用关键字标记final
。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
是否可以替换对象的值String
(而不更改对象的引用)?这些都是真实的面试问题。实践表明,许多人的回答都是错误的。了解关键字 的使用final
,特别是对于引用变量,非常重要。当您思考的时候,我们先暂时离开 JavaRush 团队。请在文本编辑器中添加一个块,该块允许您隐藏内容,并在单击它时显示该内容。答案:
-
因为 数组是一个对象,这
final
意味着给一个对象分配一个引用后,就不能再改变它了,但是可以改变该对象的状态。final int[] array = {1,2,3,4,5}; array[0] = 9; //ok, because change the contents of the array - {9,2,3,4,5} array = new int[5]; //compile error
-
是的你可以。关键是要理解带刺词与物体的用法
final
。使用ReflectionAPI来替换值。
import java.lang.reflect.Field;
class B {
public static void main(String[] args) throws Exception {
String value = "Old value";
System.out.println(value);
//Get the value field in the String class
Field field = value.getClass().getDeclaredField("value");
//Let's change it
field.setAccessible(true);
//Set new value
field.set(value, "JavaRush".toCharArray());
System.out.println(value);
/* Вывод:
* Old value
* JavaRush
*/
}
}
请注意,如果我们尝试以这种方式更改基本类型的最终变量,则不会有任何效果。我建议您说服自己这一点:例如,创建一个带有final int
字段的 Java 类,并尝试通过 Reflection API 更改其值。祝你们好运!
GO TO FULL VERSION