static

公開日: 2026-07-29 08:41 更新日: 2026-07-29 08:41 2103文字 11 min read ... ページビュー

本文はJavaのいくつかのコアキーワードの使用シーンと原理を体系的に紹介した:静的修飾の静的メンバーはクラス自身に属し、共有され、クラスロード時に初期化される;インスタンスと静的初期化ブロックは特定の順序で実行され、オブジェクト作成プロセスに影響を与える;シングルケースパターンは空腹と怠け者によって共有インスタンスを実現する;抽象クラスとメソッドを定義するために使用され、抽象クラスはインスタンス化できないが抽象メソッドを含むことができ、サブクラスは抽象メソッドを実現する必要がある; finalは継承、オーバーライド、複数の代入を禁止するために使用され、定数宣言によく使用されます。内部クラスはメンバ、ローカル、静的、匿名クラスに分かれ、それぞれにスコープとアクセス制限があり、さまざまなシナリオのコードカプセル化に適しています。

静的(static)

静的キーワード

staticでは、メンバー変数、メンバーメソッド、コードブロック、ネストされたクラスを修飾できます。staticに修飾されたメンバはクラス自体に属し,いずれかの具体的オブジェクトにも属さない.

静的メンバ変数

静的メンバ変数は、同じクラスのすべてのオブジェクト間で共有され、通常はクラス名でアクセスされます。

public class Person {
    private String name;
    private static int count;

    public Person(String name) {
        this.name = name;
        count++;
    }

    public static int getCount() {
        return count;
    }

    public static void main(String[] args) {
        new Person("Tom");
        new Person("Jerry");
        System.out.println(Person.getCount());
    }
}

クラスが初めてアクティブに使用されると、JVMはクラスのロード、接続、初期化を完了します。静的フィールドの明示的代入文と静的コードブロックは、クラス初期化フェーズで書かれた順序で実行されます。

静的メンバメソッド

静的メソッドはクラス名から直接呼び出すことができる。

public class Person {
    public static void evolve() {
        System.out.println("人类的进化");
    }

    public static void main(String[] args) {
        Person.evolve();
    }
}

静的メソッドには現在のオブジェクトがないため、thisまたはsuperは使用できず、インスタンスメンバに直接アクセスすることもできません。インスタンスメンバーにアクセスする必要がある場合は、オブジェクト参照を最初に取得する必要があります。

インスタンスの初期化ブロック

メソッド名を持たずにクラス内に直接記述される通常のコードブロックは、インスタンス初期化ブロックと呼ばれ、しばしばコンストラクションブロックと呼ばれます。オブジェクトが作成されるたびに、コンストラクタ本体の前に実行されます。

public class Person {
    {
        System.out.println("执行实例初始化块");
    }

    public Person() {
        System.out.println("执行无参构造器");
    }

    public Person(String name) {
        System.out.println("执行有参构造器:" + name);
    }
}

インスタンス初期化ブロックは、複数のコンストラクタが実行する必要がある初期化コードに適しています。コンパイラーはこれをコンストラクタにマージし、親クラスコンストラクタが最初に実行され、現在のクラスインスタンス初期化コードが実行されるようにします。

スタティック初期化ブロック

静的初期化ブロックはstatic修飾を使用してクラス初期化時に実行され、各クラスローダは通常 1 回だけ実行されます。

public class Person {
    static {
        System.out.println("执行静态初始化块");
    }
}

サブクラスオブジェクトを作成する場合の一般的な初期化順序は次のとおりです。

  1. 親クラスの静的フィールドと静的初期化ブロック。

  2. 静的フィールドと静的初期化ブロックのサブクラス。

  3. 親クラスのインスタンスフィールドとインスタンス初期化ブロック。

  4. 親クラスコンストラクタ。

  5. サブクラスインスタンスフィールドとインスタンス初期化ブロック。

  6. サブクラスのコンストラクタ。

同じクラス内のフィールド初期化文と初期化ブロックは、ソースコード内の順序で実行されます。

シングルトンデザインパターン

シングルトンパターンは、クラスが1つの共有インスタンスのみを提供し、統一アクセスを提供するために使用されます。

ハングリー·スタイル

空腹はクラス初期化時にオブジェクトを作成し、クラス初期化段階のシンプルで自然なスレッドセーフを実現します。

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

実装ポイントは以下の通り。

  1. コンストラクタはプライベートで、外部から直接オブジェクトを作成できません。

  2. 静的フィールドを使用して、一意のインスタンスを保存します。

  3. 静的メソッドでインスタンスを返します。

怠け者のスタイル

最も単純な怠け者は、マルチスレッド環境で複数のオブジェクトを作成する可能性があるため、同時シナリオでは直接使用できません。

public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

synchronizedを使用すると、正確性は保証されますが、呼び出しごとに同期メソッドに入る必要があります。実際のプロジェクトでは、静的な内部クラスや列挙を使用してシングルトンを実装することもできます。

抽象 Abstract #アブストラクト#

abstractはクラスとメソッドを修飾することができる。

抽象クラスの概要

抽象クラスは直接インスタンス化することはできず、フィールド、コンストラクタ、プレーンメソッド、抽象メソッドを含むことができる。クラス内に抽象メソッドが存在する限り、そのクラスは抽象クラスとして宣言する必要があります。抽象クラスは抽象メソッドを含まなくてもかまいません。

Abstractメソッド

抽象メソッドはメソッド宣言を持ち、メソッド本体はありません。具体的なサブクラスは継承された抽象メソッドを実装するか、抽象クラスとして宣言する必要がある。

public abstract class TestAbstract {
    private String name;
    private int age;

    public TestAbstract() {
    }

    public TestAbstract(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public abstract void method();
}
public class TestSub extends TestAbstract {
    @Override
    public void method() {
        System.out.println("实现抽象方法");
    }
}

抽象クラスはパブリックプロセスを定義し、サブクラスが決定しなければならないステップを抽象メソッドとして宣言することができる。

public abstract class Shape {
    public abstract double area();

    public static double areaSum(Shape[] shapes) {
        double sum = 0;
        for (Shape shape : shapes) {
            sum += shape.area();
        }
        return sum;
    }
}

finalキーワード

finalはクラス、メソッド、変数を修飾できます。

ファイナルクラス

finalで修飾されたクラスは継承できません。

public final class Utility {
}

finalメソッド

finalで修飾されたメソッドはサブクラスで上書きできません。

final 変数

finalで修飾された変数には1 回だけ代入できます。

final int age = 18;

finalが参照変数を修飾した場合、その変数を別のオブジェクトにリダイレクトすることはできませんが、元のオブジェクトの内部可変プロパティを変更することはできます。

final StringBuilder builder = new StringBuilder("Java");
builder.append(" SE");
// builder = new StringBuilder(); // 编译错误

宣言で代入されていないインスタンスfinalフィールドは空のfinalフィールドと呼ばれ、インスタンス初期化ブロックまたは各コンストラクタで代入を完了する必要があります。

public class Person {
    private final int age;

    public Person() {
        age = 0;
    }

    public Person(int age) {
        this.age = age;
    }
}

定数は通常、public static final修飾を使用し、名前には大文字とアンダースコアが使用されます。

public class Person {
    public static final String BIRTH_PLACE = "中国";
}

内部クラスの

他のクラスの内部で定義されたクラスは、内部クラスまたはネストされたクラスと呼ばれます。通常は外部クラスのみを提供する補助ロジックをカプセル化するために使用されます。

メンバーの内部クラス

メンバ内部クラスは外部クラスオブジェクトに属し、外部クラスのインスタンスメンバに直接アクセスできます。

public class TestOuter {
    private String outerName;

    class TestInner {
        public void test() {
            outerName = "test";
        }
    }
}

外部クラスの外部にメンバ内部クラスオブジェクトを作成する場合は、外部クラスオブジェクトを作成する必要があります。

TestOuter outer = new TestOuter();
TestOuter.TestInner inner = outer.new TestInner();

ローカルクラス内部クラス

メソッドやその他のローカルスコープで定義されたクラスはローカル内部クラスと呼ばれ、そのスコープでのみ使用できます。

public void method() {
    class TestInner {
        public void test() {
            System.out.println("局部内部类");
        }
    }

    new TestInner().test();
}

ローカル内部クラスがアクセスするローカル変数はfinalまたは事実上のfinalでなければなりません。

静的ネスト型クラス

staticで修飾されたネストされたクラスは、外部クラスオブジェクトに依存せず、外部クラスの静的メンバにのみ直接アクセスできます。

public class TestOuter {
    private static String outerName;

    static class TestInner {
        public void test() {
            outerName = "test";
        }
    }
}

オブジェクトの作成に外部クラスインスタンスは必要ありません。

TestOuter.TestInner inner = new TestOuter.TestInner();

匿名の内部クラス

匿名内部クラスは、インターフェイスまたは親クラスの実装が一度だけ使用される場合に使用できます。

Person person = new Person() {
    @Override
    public void eat() {
        System.out.println("执行 eat 方法");
    }
};
person.eat();

匿名内部クラスには明示的なクラス名はありませんが、コンパイラは対応するクラスを生成します。同じ実装を繰り返す必要がある場合は、コードの重複を避けるために名前付きクラスを定義する。

イベント·リスニング例

public class Cal {
    private final JButton button1 = new JButton("1");
    private final JButton button2 = new JButton("2");
    private final JButton buttonAdd = new JButton("+");

    public Cal() {
        buttonAdd.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                // 实现相加功能
            }
        });

        button1.addActionListener(new NumberAction());
        button2.addActionListener(new NumberAction());
    }

    class NumberAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            // 把按钮文字显示到显示区域
        }
    }
}

気に入ったならばコメントを残してくださいね~

... ページビュー
© 2026 跨越星轨的客 @Hoshiumi
Powered by theme astro-koharu · Inspired by Shoka