ハン・シュンピンは基礎ゼロで 30 日間で Java を学習しました [第 8 章 オブジェクト指向プログラミング (上級)]

クラス変数

P373~P423

クラス変数は静的変数とも呼ばれます

静的変数は同じクラスのすべてのオブジェクトで共有されます

静的変数はクラスのロード時に生成されます

クラス変数の定義方法

访问修饰符 static 数据类型 变量名;

クラス変数にアクセスする方法

  • クラス名.クラス変数名
  • オブジェクト名.クラス変数名

静的変数のアクセス権とアクセス修飾子の範囲は、通常のプロパティと同じです。

クラス変数の使用法の詳細

特定のクラスのすべてのオブジェクトに変数を共有させる必要がある場合は、クラス変数の使用を検討できます。

クラスメソッド

访问修饰符 static 数据返回类型 方法名(){}

クラスメソッド呼び出し

  • クラス名.クラスメソッド名
  • オブジェクト名.クラスメソッド名

クラスメソッドの使用例

メソッドにオブジェクト関連のメンバーが関与しない場合、メソッドを静的メソッドとして設計することで開発効率を向上させることができます。

インスタンスを作成したくない場合は、メソッドを呼び出すこともできます。現時点では、メソッドを静的メソッドにすることが非常に適切です。

例: ツールクラスのメソッド

Math クラス、Arrays クラス、Collections コレクション クラス

クラスメソッドの考慮事項

  • クラスメソッドと通常メソッドの両方がクラスのロード時にロードされ、構造情報がメソッド領域に格納されます。クラスメソッドには this パラメータはなく、通常メソッドには this パラメータが暗黙的に含まれます。
  • クラスメソッドはクラス名またはオブジェクト名で呼び出すことができます
  • 通常のメソッドはオブジェクトに関連しているため、オブジェクト名で呼び出す必要があります。
  • this や super などのオブジェクト関連のキーワードはクラス メソッドでは使用できません
  • クラスメソッドでは静的変数または静的メソッドのみにアクセスできます
  • 通常のメンバー メソッドは、非静的メンバーと静的メンバーの両方にアクセスできます

メインメソッド

public static void main(String[] args){}

  1. public: Java仮想マシンはクラスのmain()メソッドを呼び出す必要があるため、このメソッドのアクセス権限はpublicである必要があります。
  2. static: Java 仮想マシンは main() メソッドの実行時にオブジェクトを作成する必要がないため、メソッドは静的である必要があります。
  3. このメソッドは Sting 型の配列パラメータを受け入れます。これには、Java コマンドの実行時に実行中のクラスに渡されるパラメータが格納されます。

知らせ

main メソッドでは、main メソッドが配置されているクラスの静的メソッドまたは静的プロパティを直接呼び出すことができます。

ただし、クラスの非静的メンバーに直接アクセスすることはできません。このオブジェクトを通じてクラスの非静的メンバーにアクセスするには、その前にクラスの強さオブジェクトを作成する必要があります。

コードブロック

コード ブロックは初期化ブロックとも呼ばれ、クラスのメンバーに属しメソッドに似ており、メソッド本体内の論理ステートメントをカプセル化し、{} で囲みます。

ただし、メソッドとは異なり、メソッド名、戻り値、パラメータはなく、メソッド本体のみがあり、オブジェクトまたはクラスを通じて明示的に呼び出す必要はなく、クラスがロードされるとき、またはオブジェクトがロードされたときに暗黙的に呼び出されます。創造された

基本的な文法

[修饰符]{
  代码
};

知らせ

  1. 修飾子はオプションですが、記述時に静的にのみ指定できます。
  2. コード ブロックは 2 つのカテゴリに分類されます。静的に変更されたものは静的コード ブロックと呼ばれ、静的に変更されなかったものは通常のコード ブロックと呼ばれます。
  3. 論理ステートメントには、任意の論理ステートメント (入力、出力、メソッド呼び出し、ループ、判定) を使用できます。
  4. セミコロンは記述しても省略しても構いません

理解

  1. これは、初期化操作を実行できる別の形式のコンストラクター (コンストラクターの補足メカニズム) と同等です。
  2. 複数のコンストラクターに繰り返しステートメントがある場合、それらを初期化ブロックに抽出してコードの再利用性を向上させることができます。
  3. オブジェクトを作成するためにどのコンストラクターが呼び出されても、コード ブロックのコンテンツが最初に呼び出されます。
  4. コード ブロック呼び出しの順序はコンストラクターよりも優先されます。

コード ブロックの使用法の詳細、com.codeBlock.CodeBlockDetail.java

  1. 静的コード ブロックは静的コード ブロックとも呼ばれ、クラスを初期化し、クラスのロード時に実行するために使用され、一度だけ実行されます。通常のコードブロックであれば、オブジェクトを作成して一度実行します。
  2. クラスがロードされるとき
    1. オブジェクトインスタンス作成時(新規)
    2. サブクラス オブジェクト インスタンスを作成します。親クラスもロードされます。親クラスが最初にロードされ、サブクラスが後でロードされます。
    3. クラスの静的メンバー(静的プロパティ、静的メソッド)を使用する場合
  3. 通常のコード ブロックは、オブジェクト インスタンスの作成時に暗黙的に呼び出されます。作成したら一度だけ呼び出されます。これはコンストラクターの補足に相当します。クラスの静的メンバーだけを使用する場合、通常のコード ブロックは実行されません。
  4. オブジェクトを作成するときのクラス内の呼び出しシーケンスは次のとおりです。
    1. 静的コード ブロックと静的属性の初期化を呼び出します (注: 静的コード ブロックと静的属性の初期化の呼び出しは同じ優先順位を持ちます。複数の静的コード ブロックと複数の静的変数の初期化がある場合、それらは定義された順序で呼び出されます)。
    2. 通常のコードブロックと通常の属性の初期化を呼び出します(注:通常のコードブロックと通常の属性の初期化呼び出しの優先順位は同じです。複数の通常のコードブロックと通常の属性の初期化がある場合、それらは定義された順序で呼び出されます) )
    3. 呼び出しコンストラクター
  5. コンストラクターの先頭は実際には super() を暗黙的に示し、通常のコード ブロックを呼び出します。静的コード ブロックと属性の初期化はクラスのロード時に実行されるため、コンストラクターや通常のコード ブロックよりも前に実行されます。コードブロック詳細03.java
  6. サブクラス作成時の静的コードブロック、静的プロパティの初期化、共通コードブロック、共通プロパティの初期化、コンストラクターの呼び出し順序は以下のとおりです。
    1. 親クラスの静的コードブロック、静的プロパティの初期化
    2. サブクラスの静的コードブロック、静的プロパティの初期化
    3. 親クラスの共通コードブロック、通常のプロパティ初期化
    4. 親クラスのコンストラクター
    5. サブクラスの通常のコード ブロック、通常の初期化
    6. サブクラスコンストラクター
  7. 静的コード ブロックは静的メンバーのみを直接呼び出すことができ、通常のコード ブロックは任意のメンバーを呼び出すことができます。
package com.codeBlock;

public class CodeBlockDetail {
    public static void main(String[] args) {
        //1. static代码块也叫静态代码块,作用是对类进行初始化,且随着类的加载而执行,并且只会执行一次。
        //如果是普通代码块,每创建一个对象,就执行。
        //2. 类什么时候被加载
            //1. 创建对象实例时(new)
            //2. 创建子类对象实例,父类也会被加载
//        AA aa = new AA();   // bb的静态代码块被执行
                             // aa的静态代码块被执行
                             // bb的普通代码块
            //3. 使用类的静态成员时(静态属性,静态方法)
//        System.out.println(Cat.name);   //cat的静态代码块被执行
                                            //mao
        //3. 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。
        //如果只是使用类的静态成员,普通代码块并不会执行。
//        BB.show();    //bb的静态代码块被执行
                        //调用静态属性,普通代码块不调用
//        BB bb1 = new BB();  //bb的静态代码块被执行
                            //bb的普通代码块
    }
}

class BB {
    static {
        System.out.println("bb的静态代码块被执行");
    }
    {
        System.out.println("bb的普通代码块");
    }

    public static void show() {
        System.out.println("调用静态属性,普通代码块不调用");
    }
}

class AA extends BB {
    static {
        System.out.println("aa的静态代码块被执行");
    }
}
class Cat{
    public static String name="mao";
    static {
        System.out.println("cat的静态代码块被执行");
    }
}

デザインパターン

デザインパターンとは何ですか

  1. 静的メソッドと静的プロパティの古典的な使用法
  2. デザイン パターンは、多数の実践を要約および理論化した後の、推奨されるコード構造、プログラミング スタイル、および問題解決の考え方です。

シングルトンパターン

  1. クラスのいわゆるシングルトン設計パターンでは、ソフトウェア システム全体で特定のクラスのオブジェクト インスタンスが 1 つだけ存在できるようにするために特定のメソッドを採用し、このクラスはそのオブジェクト インスタンスを取得するメソッドのみを提供します。
  2. シングルトンモードにはハングリーマンスタイルとレイジーマンスタイルの2つの方法があります

シングルトンパターンの適用例

[腹ペコ中華風]、com.single_.SingleTon01.java

クラスがロードされていればこのオブジェクトが作成されますが、クラス変数を使用するだけの場合もありますが、使用しない場合でも一緒にこのオブジェクトが作成されるため、リソースが無駄になります。

ステップ:

  1. コンストラクターの民営化: 直接新規の防止

  2. クラス内で作成されたオブジェクト

  3. 静的パブリック メソッドを公開します。インスタンスの取得

    (なぜ静的なのか?インスタンスを作成せずにクラスメソッドを直接呼び出したい場合、それは静的であり、メソッド内のプロパティも静的であるためです)

    (getInstance が複数回呼び出され、異なる変数名で受け取られた場合、静的プロパティは 1 回しか初期化されないため、実際には同じオブジェクトを指します)

  4. コード

public class SingleTon01 {
    public static void main(String[] args) {
//        GirlFriend xiaohong = new GirlFriend("xiaohong");
//        GirlFriend xiaobai = new GirlFriend("xiaobai");
        GirlFriend instance = GirlFriend.getInstance();
        System.out.println(instance);
    }
}

class GirlFriend {
    private String name;
    //如何保证只能有一个girlfriend
    //步骤:
    //1、构造器私有化
    //2、类的内部创建
    private static GirlFriend gf = new GirlFriend("xiaohong");
    private GirlFriend(String name) {
        this.name = name;
    }
    //3、提供一个公共静态方法
    public static GirlFriend getInstance() {
        return gf;
    }
    @Override
    public String toString() {
        return "GirlFriend{" + "name='" + name + '\'' + '}';
    }
}

[怠惰なスタイル]、com.single_.SingleTon02.java

ユーザーが getInstance メソッドを呼び出した場合にのみオブジェクトが作成されます。このメソッドが呼び出されている場合、再度呼び出されると、最後に作成されたオブジェクトが返されます。

public class SingleTon02 {
    public static void main(String[] args) {
        System.out.println(Cat.getInstance());
    }
}
//希望程序运行过程中只能创建一个Cat
class Cat{
    private String name;
    private static Cat cat;
    //1、构造器私有化
    //2、定义一个static属性对象
    private Cat(String name) {
        this.name = name;
    }
    //3、提供公共static方法,返回cat对象
    
    public static Cat getInstance(){
        if(cat==null){
            cat= new Cat("xiaomao");
        }
        return cat;
    }

ハングリーマンスタイルと怠け者スタイルの違い

  1. 両者の主な違いはオブジェクト作成のタイミングにあり、Hungry スタイルはクラスのロード時にオブジェクト インスタンスを作成するのに対し、Lazy スタイルは使用時にオブジェクト インスタンスを作成します。
  2. ハングリー スタイルにはスレッド セーフティの問題はありませんが、遅延スタイルにはスレッド セーフティの問題があります (スレッド学習を参照)
  3. ハングリー スタイルではリソースを無駄にする可能性があります。プログラマがオブジェクト インスタンスを使用しない場合、ハングリー スタイルで作成されたオブジェクトは無駄になります。また、レイジー スタイルは使用時に作成されるため、そのようなことはありません。問題
  4. javaSE 標準クラスでは、java.lang.Runtime が古典的なシングルトン パターンです。
public class Runtime {
    private static Runtime currentRuntime = new Runtime();
    public static Runtime getRuntime() {
        return currentRuntime;
    }
    /** Don't let anyone else instantiate this class */
    private Runtime() {}
    }

最後のキーワード

Final はクラス、プロパティ、メソッド、ローカル変数を変更できます

使用法: com.final_.Final01.java

  1. クラスを継承したくない場合は、最終変更を使用できます。
  2. 親クラスのメソッドをサブクラスで上書き/オーバーライドしたくない場合 [アクセス修飾子最終戻り型メソッド名]
  3. クラスの属性の値を変更したくない場合 [public Final double TAX_RATE=0.08]
  4. ローカル変数を変更したくない場合 [final double TAX_RATE=0.08]
package com.final_;
public class Final01 {
    public static void main(String[] args) {
        A a = new A();
        a.TAX_RATE=0.09;
    }
}
//如果要求A不能被其他类继承,使用final修饰A
//final class A{
class A{
    //    不希望类的某个属性的值被修改
//    public final double TAX_RATE=0.08;
    public double TAX_RATE=0.08;


    //    不希望方法被子类覆盖
//    public final void hi(){}
    public void hi(){
        //    不希望某个局部变量被修改
//        final int money=100;
        int money=100;
        money =101;
    }
}

class B extends A{
    @Override
    public void hi() {
        super.hi();
    }
}

最終的な詳細

  1. 最終的に変更されたプロパティは定数とも呼ばれ、XX_XX_XX という名前が付けられます。
  2. 最終的に変更された属性には、定義時に初期値を割り当てる必要があり、それ以降は変更できません。初期値は次の位置に割り当てることができます。
    1. 定義されたとき
    2. コンストラクター内で
    3. コードブロック内で
class AA{
  public final double TAX_RATE=0.08;//定义时
  public final double TAX_RATE2;
  public final double TAX_RATE3;
  public AA(){//构造器中赋值
    TAX_RATE2=1.1;
  }
  {//代码块赋值
    TAX_RATE3=8.8;
  }
}
  1. 最終的に変更されたプロパティが静的な場合、初期化位置は次のとおりです。
    1. 定義されたとき
    2. 静的ブロック
class BB{
  public static final double TAX_RATE=0.08;//定义时
  public static final double TAX_RATE2;
  static {//代码块赋值
    TAX_RATE3=8.8;
  }
}
  1. 最終クラスは継承できませんが、オブジェクトはインスタンス化できます
  2. クラスが最終クラスではなく最終メソッドを含む場合、そのメソッドはオーバーライドできませんが、継承できます。
  3. 一般に、クラスがfinalであれば、メソッドをfinalとして記述する必要はありません。
  4. Final はコンストラクターを変更できません
  5. Final と static はよく一緒に使用されますが、これはより効率的であり、クラスの読み込みを引き起こしません。基礎となるコンパイラは com.final_.FinalStatic.java を最適化しています。
package com.final_;
public class FinalStatic {
    public static void main(String[] args) {

        System.out.println(AA.name);
    }
}

class AA {
    public static final String name = "aaa";
    static {
        System.out.println("静态代码块");
    }
}

  1. ラッパー クラス (Integer、Double、Float、Boolean はすべて最終クラスです)、String も最終クラスです

抽象クラス

com.abstract_.Abstract01.java

親クラスの一部のメソッドを宣言する必要があるが、それらの実装方法がわからない場合は、それらを抽象メソッドとして宣言できます。その場合、このクラスは抽象クラスになります。

package com.abstract_;

public class Abstract01 {
    public static void main(String[] args) {

    }
}

abstract class Animal {
    private String name;
    public Animal(String name) {
        this.name = name;
    }

    //eat实现了,但没什么意义
    //出现了父类方法不确定性的问题
    //考虑将该方法设计为抽象方法
    //所谓抽象方法就是没有实现的方法
    //所谓没有实现就是没有方法体{}
    //当一个类中存在抽象方法时,需要将该类声明为abstract类
    //一般来说,抽象类会被继承,由其子类来实现抽象方法
    public abstract void eat();
}

導入

  1. abstract キーワードを使用してクラスを変更すると、そのクラスは抽象クラスと呼ばれます。

    访问修饰符 abstract 类名{}

  2. abstract キーワードを使用してメソッドを変更すると、そのメソッドはメソッド本体 {} のない抽象メソッドになります。

    访问修饰符 abstract 返回类型 方法名(参数列表);

  3. 抽象クラスの価値は設計にあり、設計者が設計した後、サブクラスに抽象クラスを継承させて実装します。

抽象クラスの詳細

  1. 抽象クラスはインスタンス化できません
  2. 抽象クラスには必ずしも抽象メソッドが含まれる必要はありません。つまり、抽象クラスは抽象メソッドを持たない可能性があります。
  3. ただし、クラスに抽象メソッドが含まれている場合は、クラスを抽象として宣言する必要があります。
  4. abstract はクラスとメソッドのみを変更でき、属性などは変更できません
  5. 抽象クラスはクラスであるため、抽象クラスは任意のメンバーを持つことができます。
  6. 抽象メソッドにはメソッド本体 {} を含めることはできません
  7. クラスが抽象クラスを継承する場合、それ自体が抽象クラスでない限り、その抽象クラスのすべての抽象メソッドを実装する必要があります。
  8. これらのキーワードは書き換えに反するため、抽象メソッドを private、final、static で修飾することはできません。

演習、com.abstract_.AbstractExercise01.java

name、id、salal の 3 つの属性を含む抽象クラスとして宣言された Employee クラスを作成し、必要なコンストラクターと抽象メソッド work() を提供します。Manager クラスの場合、彼は従業員であるだけでなく、ボーナス属性も持っています。継承のアイデアを使用して CommonEmployee クラスと Manager クラスを設計し、属性アクセスに必要なメソッドを提供し、 work()、"Manager" を実装するようにクラスに要求してください。 , 一般的な従業員名勤務中...」

package com.abstract_;
public class AbstractExercise01 {
    public static void main(String[] args) {
        CommonEmployee xiaoming = new CommonEmployee("小明", 101, 1000);
        Manager daming = new Manager("大明", 99, 1100, 2000);
        xiaoming.work();
        daming.work();
    }
}
abstract class Employee {
    private String name;
    private int id;
    private double salary;
    public Employee(String name, int id, double salary) {
        this.name = name;
        this.id = id;
        this.salary = salary;
    }
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}
    public double getSalary() {return salary;}
    public void setSalary(double salary) {this.salary = salary;}
    public abstract void work();
}
class Manager extends Employee {
    private double bonus;
    public Manager(String name, int id, double salary, double bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }
    public double getBonus() {return bonus;}
    public void setBonus(double bonus) {this.bonus = bonus;}
    @Override
    public void work() {
        System.out.println("经理 " + getName() + "工作中..");
    }
}
class CommonEmployee extends Employee {
    public CommonEmployee(String name, int id, double salary) {
        super(name, id, salary);
    }
    @Override
    public void work() {
        System.out.println("普通员工" + getName() + "工作中..");
    }
}

インターフェース

インターフェイスは、いくつかの未実現のメソッドを与え、それらを一緒にカプセル化し、特定のクラスがそれらのメソッドを使用する必要があるときに、特定の状況に応じてこれらのメソッドを書き出すことです。

interface 接口名{
//属性
//方法(1抽象方法2默认方法3静态方法)
}
class 类名 implements 接口名{
  自己属性;
  自己方法;
  必须实现接口的抽象方法
}

JDK7.0 より前では、インターフェイス内のすべてのメソッドにはメソッド本体がありません

JDK8.0 以降、インターフェイス クラスには静的な変更が必要な静的メソッドを含めることができ、デフォルトのメソッドにはデフォルトの変更が必要です。つまり、インターフェイスにはメソッドの特定の実装を含めることができます。

クイックスタート、com.interface_.Interface01.java

package com.interface_;

public class Interface01 {
    public static void main(String[] args) {
        Computer computer = new Computer();
        Camera camera = new Camera();
        Phone phone = new Phone();
        computer.work(camera);
        computer.work(phone);
    }
}
interface UsbInterface {
    public void start();
    public void stop();
}

class Computer {
    public void work(UsbInterface usbInterface) {
        usbInterface.start();
        usbInterface.stop();
    }
}

class Camera implements UsbInterface {
    @Override
    public void start() {
        System.out.println("我是相机,开始工作");
    }

    @Override
    public void stop() {
        System.out.println("我是相机,结束工作");
    }
}

class Phone implements UsbInterface {
    @Override
    public void start() {
        System.out.println("我是手机,开始工作");
    }

    @Override
    public void stop() {
        System.out.println("我是手机,结束工作");
    }
}

インターフェースの詳細

  1. インターフェースをインスタンス化できません

  2. インターフェイス内のすべてのメソッドはパブリック メソッドであり、インターフェイス内の抽象メソッドを抽象メソッドで変更する必要はありません。

  3. 共通クラス実装インターフェイスは、インターフェイスのすべてのメソッドを実装する必要があります

  4. 抽象クラスはインターフェイスを実装するため、インターフェイスのメソッドを実装する必要はありません

  5. クラスは複数のインターフェイスを同時に実装できます

  6. インターフェイス内のプロパティは、final のみにすることができ、public static Final です。たとえば、 int a=1; は実際には public static Final int a=1; です。

  7. インターフェイス内の属性のアクセス形式: インターフェイス名。属性名

  8. インターフェイスは他のクラスから継承することはできませんが、他の複数のインターフェイスから継承することはできます

    interface extends B,C{}

  9. インターフェイス修飾子は、クラス修飾子と同様に、public およびデフォルトのみにすることができます。

インターフェイスの実装とクラスの継承

インターフェースと継承はさまざまな問題を解決します

  • 継承の価値は、コードの再利用性と保守性を解決することにあります。
  • インターフェイスの価値は、設計、さまざまな仕様の設計、および他のクラスにこれらのメソッドを実装させることにあります。

インターフェースはコードの分離をある程度実現します

抽象クラスと抽象インターフェイスを使用する場合

参考

クラスを設計するときは、まずインターフェイスを使用してクラスの特性を抽象化することを検討し、一部のメソッドが再利用できることがわかったら、抽象クラスを使用してコードを再利用できます。簡単に言うと、インターフェイスは物事の特性を抽象化するために使用され、抽象クラスはコードを再利用するために使用されます。

もちろん、すべてのクラスがインターフェイスから抽象クラス、そしてクラスへと設計されているわけではありません。プログラミングが従うべき絶対的なパラダイムはありません。ご自身のニーズに合わせてデザインしてください。

インターフェース多態性

  1. 多態性パラメータ、InterfacePolyParameter.java
  2. 多態性配列、InterfacePloyArr.java
  3. InterfacePolyPass.java にはポリモーフィックなパス現象があります。

まとめ

クラスの 5 つのメンバー: プロパティ、メソッド、コンストラクター、コード ブロック、内部クラス

package 包名;
class 类名 extends 父类 implements 接口名{
  成员变量//属性
  构造方法//构造器
  成员方法//方法
  代码块
 }

内部クラス

別のクラス構造がクラス内に完全にネストされています。ネストされたクラスは内部クラスと呼ばれ、他のクラスをネストしたクラスは外部クラスと呼ばれます。

内部クラスの最大の特徴は、プライベートプロパティに直接アクセスでき、クラス間の包含関係を反映できることです。

基本的な文法

class Outer{//外部类
  class Inner{//内部类
  }
}
class Other{//外部其他类
}

内部クラスの分類

外部クラスのローカル位置で定義されます: メソッド内など

  • ローカル内部クラス (クラス名付き)
  • 匿名内部クラス (クラス名なし)

外部クラスのメンバー位置で定義されます。

  • メンバーの内部クラス (静的で変更されていない)
  • 静的内部クラス (静的変更を使用)

外部クラスでローカルに定義されます。

ローカル内部クラス、com.innerclass.LocalInnerClass.java

  • ローカル内部クラスは、メソッド内など、外部クラスのローカルな位置で定義され、クラス名を持ちます。
  • ステータスがローカル変数であるため、アクセス修飾子を追加できません。ローカル変数は修飾子を使用できませんが、final を使用して変更できます。
  • スコープ: それを定義するメソッドまたはコード ブロック内でのみ、クラス型のローカル変数と同等です。
  • ローカルの内部クラスは、プライベート メンバーを含む外部クラスのメンバーに直接アクセスします。
  • 外部クラスはオブジェクトを作成してから、内部クラスのメンバーにアクセスする必要があります。
  • 他の外部クラスはローカルの内部クラスにアクセスできません
  • 外部クラスとローカル内部クラスが同じ名前を持つ場合、デフォルトでは近接性の原則に従います。すべての関係者から外部クラスのメンバーを吸収する場合は、外部クラス名.this.Member アクセスを使用できます。
public class LocalInnerClass {
    public static void main(String[] args) {
    }
}

class Outer {
    private int n1 = 100;
    private void m2() {}
    private void m1() {
        // 局部内部类是定义在外部类的局部位置,比如方法中,并且有类名
        // 不能添加访问修饰符,因为他的地位就是一个局部变量。
        // 局部变量不能使用修饰符,但是可以用final修饰
        class Inner { // 局部内部类
            // 局部内部类可以直接访问外部类成员,包括私有的
            public void f1() {
                System.out.println("n1=" + n1);
            }
        }
    }
}

  1. ローカル内部クラスはメソッド/コード ブロックで定義されます。
  2. スコープはメソッド本体/コードブロック内にあります
  3. 本質はクラスです

匿名内部クラス、com.anonymousInner.AnonymousInnerClass.java

匿名の内部クラスは、メソッドなどの外部クラスのローカルな場所で定義され、クラス名がなく、依然としてオブジェクトです。

匿名内部クラスは、インターフェイスの実装または親クラスの継承と同等です。

匿名内部クラスの基本構文

new 类或接口(参数列表){
  匿名类类体
};

  1. 匿名内部クラスはクラス定義であるだけでなくオブジェクトでもあるため、文法の観点からはクラス特性とオブジェクト作成特性の両方を備えているため、匿名内部クラスのメソッドを呼び出すことができます。
  2. プライベートを含む外部クラスのすべてのメンバーに直接アクセスできます。
  3. ステータスがローカル変数であるため、アクセス修飾子を追加できません
  4. スコープ: それを定義するメソッドまたはコード ブロック内のみ
  5. 匿名の内部クラスが外部クラスのメンバーに直接アクセスする
  6. 他の外部クラスは匿名の内部クラスにアクセスできません
package com.anonymousInner;
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}
class Outer04 {//外部类
    private int n1 = 10;//属性
    public void method() {//方法
        //基于接口的匿名内部类
        //1、需求:想使用接口IA,并创建对象
        //2、传统方式:写一个类,实现该接口,然后创建对象
        //3、需求是Tiger类只使用一次,后面再不使用
//        IA tiger = new Tiger();
//        tiger.cry();
        //4、可以用匿名内部类来简化开发

        //演示基于接口的匿名内部类
        //tiger的编译类型:IA
        //tiger的运行类型:com.anonymousInner.Outer04$1
        //底层:class Outer04$1 implements IA{}
        IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("老虎叫");
            }
        };
        tiger.cry();
        System.out.println("tiger的运行类型"+tiger.getClass());

        //演示基于类的匿名内部类
        //jack的编译类型:
        //jack的运行类型:com.anonymousInner.Outer04$2
        //底层:class Outer04$2 extends Father{}
        //和""Father jack = new Father("jack");"" 有区别,区别在于"{};",
        //实际是匿名内部类继承了Father类,应该是叫向上转型
        Father jack = new Father("jack") {};
        System.out.println("jack的运行类型"+jack.getClass());
    }
}
interface IA {
    public void cry();
}
// 传统方法:写一个类,实现该接口,然后创建对象
class Tiger implements IA {
    @Override
    public void cry() {
        System.out.println("老虎叫");
    }
}
class Father {
    public Father(String name) {super();}
    public void test() {}
}

内部クラスの演習、com.anonymousInner.InnerClassExercise02.java

  1. ベルインターフェイス Bell があり、これはリングメソッドを備えています
  2. 携帯電話クラス Cellphone があり、目覚まし時計機能アラームクロックがあり、パラメータはベル型です。
  3. 携帯電話クラスの目覚まし時計機能をテストし、匿名の内部クラスをパラメータとして使用して、次のように出力します。
  4. 次に、別の匿名内部クラスを渡して、次のように出力します: 小さな友達は授業中です
//1. 有一个铃声接口Bell,里面有个ring方法
//2. 有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型
//3. 测试手机类的闹钟功能,通过匿名内部类作为参数,打印:懒猪起床了
//4. 再传入另一个匿名内部类,打印:小伙伴上课了
public class InnerClassExercise02 {
    public static void main(String[] args) {
        new Cellphone().alarmclock(new Bell(){
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });
        new Cellphone().alarmclock(new Bell() {
            @Override
            public void ring() {
                System.out.println("小伙伴上课了");
            }
        });
    }
}

interface Bell{
    public void ring();
}
class Cellphone{
    public void alarmclock(Bell bell){bell.ring();}
}

外部クラスのメンバー位置で定義されます。

メンバーの内部クラス

  1. プライベートを含む外部クラスのすべてのメンバーに直接アクセスできます。
  2. 任意のアクセス修飾子 public、protected、default、private を追加できます。ステータスはメンバーと同等です。
  3. スコープ: 外部クラスの他のメンバーと同様に、クラス本体全体です。
  4. メンバーの内部クラスが外部クラスに直接アクセスする
  5. 外部クラスが内部クラスにアクセス: アクセス時にオブジェクトを作成
  6. 外部の他のクラスが内部クラスのメンバーにアクセスする
  7. 外部クラスと内部クラスのメンバーが同じ名前である場合、内部クラスへのアクセスはデフォルトで近接性の原則に従います。外部クラスのメンバーにアクセスしたい場合は、(外部クラス名.this) を使用できます。 .member) アクセス

静的内部クラス

静的な内部クラスは、外部クラスのメンバー位置で定義され、静的な変更が行われます。

  1. プライベートクラスを含む外部クラスのすべての静的メンバーに直接アクセスできますが、非静的メンバーには直接アクセスできません
  2. 任意のアクセス修飾子を追加可能
  3. スコープ: 他のメンバーと同じ、クラス本体全体
  4. 静的内部クラスが外部クラスに直接アクセスする
  5. 外部クラスは静的内部クラスにアクセスするためのオブジェクトを作成します

おすすめ

転載: blog.csdn.net/weixin_65656674/article/details/126416751