#このチュートリアルの動作環境: Windows7 システム、Java8 バージョン、DELL G3 コンピューター。Java では、final を使用してクラス、メソッド、変数を変更できます。最終的に変更されたクラスは、そのクラスが他のクラスに継承できないことを意味します。つまり、このクラスは継承ツリーのリーフ クラスであり、このクラスの設計は完璧であると考えられており、変更または拡張する必要はありません。最終的に変更されたクラスのメソッドは、そのクラスが他のクラスに継承できず、オーバーライドできないことを意味します。つまり、継承されたクラスが変更できないようにメソッドがロックされています。 Final はクラス内の変数を変更し、変数が初期化されると変更できないことを示します。
1. Final を使用して変更できる構造: クラス、メソッド、変数
2. Final はクラスを変更するために使用されます。このクラスは他のクラスに継承できません。
クラスが継承されないようにする必要がある場合は、最終変更を使用できますが、次の点に注意してください:最終クラスのすべてのメンバー メソッドは暗黙的に最終メソッドとして定義されます 。
例: String クラス、System クラス、StringBuffer クラス3. Final はメソッドの変更に使用されます: このメソッドをオーバーライドできないことを示します
4.final を使用して変数を変更します。変数は定数と同等です。
5.final キーワードを使用してクラス、変数、メソッドを宣言する場合は、次の点に注意する必要があります。 ##final を変数の前に付けると、変数の値を変更できないことを意味し、この場合、その変数を定数と呼ぶことができます。
#final で変更された変数
final で変更された変数は定数となり、値を 1 回だけ割り当てることができます。ただし、final で変更された変数はローカル変数とメンバー変数には違いがあります。 最終的に変更されたローカル変数は、使用する前に値を割り当てる必要があります。
public class FinalDemo { void doSomething() { // 没有在声明的同时赋值 final int e; // 只能赋值一次 e = 100; System.out.print(e); // 声明的同时赋值 final int f = 200; } // 实例常量 final int a = 5; // 直接赋值 final int b; // 空白final变量 // 静态常量 final static int c = 12;// 直接赋值 final static int d; // 空白final变量 // 静态代码块 static { // 初始化静态变量 d = 32; } // 构造方法 FinalDemo() { // 初始化实例变量 b = 3; // 第二次赋值,会发生编译错误 // b = 4; } }
上記のコードの行 4 と 6 は、ローカル定数を宣言しています。行 4 は、割り当てがないことを宣言しているだけですが、使用する前に割り当てる必要があります (コードの行 6 を参照)。実際には、ローカル定数は宣言と同時に初期化されるのが最適です。コードの 13、14、16、17 行目はすべてメンバー定数を宣言しています。コードの 13 行目と 14 行目はインスタンス定数で、最終変数が空の場合 (コード 14 行目参照)、コンストラクターで初期化する必要があります (コード 27 行目参照)。コードの行 16 と 17 は静的定数です。最終変数が空の場合 (コードの 17 行を参照)、静的コード ブロックで初期化する必要があります (コードの 21 行を参照)。
当使用 final 修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。 但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。
下面程序示范了 final 修饰数组和 Person 对象的情形。
import java.util.Arrays; class Person { private int age; public Person() { } // 有参数的构造器 public Person(int age) { this.age = age; } // 省略age的setter和getter方法 // age 的 setter 和 getter 方法 } public class FinalReferenceTest { public static void main(String[] args) { // final修饰数组变量,iArr是一个引用变量 final int[] iArr = { 5, 6, 12, 9 }; System.out.println(Arrays.toString(iArr)); // 对数组元素进行排序,合法 Arrays.sort(iArr); System.out.println(Arrays.toString(iArr)); // 对数组元素赋值,合法 iArr[2] = -8; System.out.println(Arrays.toString(iArr)); // 下面语句对iArr重新赋值,非法 // iArr = null; // final修饰Person变量,p是一个引用变量 final Person p = new Person(45); // 改变Person对象的age实例变量,合法 p.setAge(23); System.out.println(p.getAge()); // 下面语句对P重新赋值,非法 // p = null; } }
从上面程序中可以看出,使用 final 修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。例如上面 iArr 变量所引用的数组对象,final 修饰后的 iArr 变量不能被重新赋值,但 iArr 所引用数组的数组元素可以被改变。与此类似的是,p 变量也使用了 final 修饰,表明 p 变量不能被重新赋值,但 p 变量所引用 Person 对象的成员变量的值可以被改变。
注意:在使用 final 声明变量时,要求全部的字母大写,如 SEX,这点在开发中是非常重要的。
如果一个程序中的变量使用 public static final 声明,则此变量将称为全局变量,如下面的代码:
public static final String SEX= "女";
final修饰方法
final 修饰的方法不可被重写,如果出于某些原因,不希望子类重写父类的某个方法,则可以使用 final 修饰该方法。
Java 提供的 Object 类里就有一个 final 方法 getClass(),因为 Java 不希望任何类重写这个方法,所以使用 final 把这个方法密封起来。但对于该类提供的 toString() 和 equals() 方法,都允许子类重写,因此没有使用 final 修饰它们。
下面程序试图重写 final 方法,将会引发编译错误。
public class FinalMethodTest { public final void test() { } } class Sub extends FinalMethodTest { // 下面方法定义将出现编译错误,不能重写final方法 public void test() { } }
上面程序中父类是 FinalMethodTest,该类里定义的 test() 方法是一个 final 方法,如果其子类试图重写该方法,将会引发编译错误。
对于一个 private 方法,因为它仅在当前类中可见,其子类无法访问该方法,所以子类无法重写该方法——如果子类中定义一个与父类 private 方法有相同方法名、相同形参列表、相同返回值类型的方法,也不是方法重写,只是重新定义了一个新方法。因此,即使使用 final 修饰一个 private 访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名、相同形参列表、相同返回值类型的方法。
下面程序示范了如何在子类中“重写”父类的 private final 方法。
public class PrivateFinalMethodTest { private final void test() { } } class Sub extends PrivateFinalMethodTest { // 下面的方法定义不会出现问题 public void test() { } }
上面程序没有任何问题,虽然子类和父类同样包含了同名的 void test() 方法,但子类并不是重写父类的方法,因此即使父类的 void test() 方法使用了 final 修饰,子类中依然可以定义 void test() 方法。
final 修饰的方法仅仅是不能被重写,并不是不能被重载,因此下面程序完全没有问题。
public class FinalOverload { // final 修饰的方法只是不能被重写,完全可以被重载 public final void test(){} public final void test(String arg){} }
final修饰类
final 修饰的类不能被继承。当子类继承父类时,将可以访问到父类内部数据,并可通过重写父类方法来改变父类方法的实现细节,这可能导致一些不安全的因素。为了保证某个类不可被继承,则可以使用 final 修饰这个类。
下面代码示范了 final 修饰的类不可被继承。
final class SuperClass { } class SubClass extends SuperClass { //编译错误 }
因为 SuperClass 类是一个 final 类,而 SubClass 试图继承 SuperClass 类,这将会引起编译错误。
final 修饰符使用总结
1. final 修饰类中的变量
表示该变量一旦被初始化便不可改变,这里不可改变的意思对基本类型变量来说是其值不可变,而对对象引用类型变量来说其引用不可再变。其初始化可以在两个地方:一是其定义处,也就是说在 final 变量定义时直接给其赋值;二是在构造方法中。这两个地方只能选其一,要么在定义时给值,要么在构造方法中给值,不能同时既在定义时赋值,又在构造方法中赋予另外的值。
2. final 修饰类中的方法
说明这种方法提供的功能已经满足当前要求,不需要进行扩展,并且也不允许任何从此类继承的类来重写这种方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。在声明类中,一个 final 方法只被实现一次。
3. final 修饰类
表示该类是无法被任何其他类继承的,意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。
final クラスのメンバーについては、final として定義するかどうかを定義できます。メソッドに関しては、所属するクラスがfinalなので当然finalになります。また、final メソッドを最終クラスに明示的に追加することもできますが、これは明らかに無意味です。
推奨チュートリアル:「java チュートリアル」
以上がJavaのfinalキーワードの機能は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。