ホームページ  >  記事  >  Java  >  Javaのfinalキーワードの機能は何ですか

Javaのfinalキーワードの機能は何ですか

青灯夜游
青灯夜游オリジナル
2022-11-25 16:26:2624574ブラウズ

Java では、final を使用してクラス、メソッド、変数を変更できます。最終的に変更されたクラスは、そのクラスが他のクラスに継承できないことを意味します。つまり、このクラスは継承ツリーのリーフ クラスであり、このクラスの設計は完璧であると考えられており、変更または拡張する必要はありません。最終的に変更されたクラスのメソッドは、そのクラスが他のクラスに継承できず、オーバーライドできないことを意味します。つまり、継承されたクラスが変更できないようにメソッドがロックされています。 Final はクラス内の変数を変更し、変数が初期化されると変更できないことを示します。

Javaのfinalキーワードの機能は何ですか

#このチュートリアルの動作環境: Windows7 システム、Java8 バージョン、DELL G3 コンピューター。

最後のキーワードは何ですか?

1. Final を使用して変更できる構造: クラス、メソッド、変数

2. Final はクラスを変更するために使用されます。このクラスは他のクラスに継承できません。

クラスが継承されないようにする必要がある場合は、最終変更を使用できますが、次の点に注意してください:

最終クラスのすべてのメンバー メソッドは暗黙的に最終メソッドとして定義されます

例: String クラス、System クラス、StringBuffer クラス

3. Final はメソッドの変更に使用されます: このメソッドをオーバーライドできないことを示します

    Function
  • (1) メソッドをロックして、継承されたクラスがメソッドを変更できないようにします。

    (2) 効率性。初期の Java バージョンでは、最終メソッドはインライン呼び出しに変換されます。ただし、メソッドが大きすぎる場合、パフォーマンスがあまり向上しない可能性があります。したがって、最近のバージョンでは、これらの最適化に Final メソッドは必要なくなりました。

    final メソッドは「最後の、最後の」という意味で、このメソッドはオーバーライドできません。

  • 例: Object クラスの getClass( )

4.final を使用して変数を変更します。変数は定数と同等です。

  • final は属性を変更するために使用されます。代入に考慮される場所は次のとおりです: 明示的な初期化、コード ブロックでの初期化、コンストラクターでの初期化

  • final 変更ローカル変数: 特に、final を使用して仮パラメータを変更する場合、それは仮パラメータが定数であることを示します。このメソッドを呼び出すときは、実パラメータを定数パラメータに割り当てます。一度割り当てられると、このパラメータの値はメソッド本体でのみ使用でき、再割り当てすることはできません。

  • final が参照型を変更する場合、それを初期化した後、その参照型は他のオブジェクトを指すことも、そのアドレスを変更することもできません (参照の値がアドレスであるため、final には値、つまりアドレスの値は変わりません)、参照が指すオブジェクトの内容は変わる可能性があります。本質的には同じことです。

5.final キーワードを使用してクラス、変数、メソッドを宣言する場合は、次の点に注意する必要があります。 ##final を変数の前に付けると、変数の値を変更できないことを意味し、この場合、その変数を定数と呼ぶことができます。

  • final は、メソッドの前で使用され、メソッドをオーバーライドできないことを示します (サブクラスが同じ名前、同じ戻り値の型、同じパラメーターを持つメソッドを作成する場合) list を親クラスとして)、メソッド本体の実装のみが異なり、親クラスとは異なる機能を実現します。この方法はメソッドの書き換えと呼ばれ、メソッドの上書きとも呼ばれます。ここでは理解するだけで、後で説明します詳細についてはチュートリアルで後述します)。

  • final は、クラスがサブクラスを持つことができないこと、つまりクラスが継承できないことを示すためにクラスの前で使用されます。

  • #final で変更された変数

final で変更された変数は定数となり、値を 1 回だけ割り当てることができます。ただし、final で変更された変数はローカル変数とメンバー変数には違いがあります。 最終的に変更されたローカル変数は、使用する前に値を割り当てる必要があります。

    宣言時に値が割り当てられていない最終的に変更されたメンバー変数は、「空白の最終変数」と呼ばれます。空の最終変数は、コンストラクターまたは静的コード ブロックで初期化する必要があります。
  • 注: Final で変更された変数に値を代入できないというのは間違いです。厳密に言えば、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 行を参照)。

  • また、どのような定数であっても、代入できるのは 1 回だけです。b 定数の代入についてはコードの 29 行目を参照してください。b は以前に 1 回代入されているため、ここでコンパイル エラーが発生します。

最終的に変更された基本型変数と参照型変数の違い

当使用 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。