内部クラスと匿名内部クラスの使用法

高洛峰
リリース: 2016-12-15 13:15:18
オリジナル
2802 人が閲覧しました

1. 内部クラス:

(1) 内部クラスと同じ名前のメソッド

内部クラスに同じ名前のメソッドがある場合、それを呼び出す必要があります。 "OuterClass.this.MethodName()" 形式 (OuterClass は MethodName を実際の外部クラス名とそのメソッドに置き換えます。これは、内部クラスにメソッドがない場合、外部クラスへの参照を示すキーワードです)。同じ名前の場合は、外部クラスのメソッドを直接呼び出すことができます。
ただし、周辺クラスは内部クラスのプライベート メソッドを直接呼び出すことはできません。また、外部クラスは他のクラスのプライベート メソッドを直接呼び出すことはできません。注: 内部クラスが外部クラスを直接使用する権限は、メソッドが静的であるかどうかとは関係なく、内部クラスに同じ名前のメソッドがあるかどうかによって決まります。

package innerclass;
public class OuterClass {
    private void outerMethod() {
        System.out.println("It's Method of OuterClass");
    }
    public static void main(String[] args) {
        OuterClass t = new OuterClass();
        OuterClass.Innerclass in = t.new Innerclass();
        in.innerMethod();
    }
 
    class Innerclass {
        public void innerMethod() {
           OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法
           outerMethod();// 内部类没有同名方法时执行外部类的方法
        }
        private void outerMethod() {
            System.out.println("It's Method of Innerclass");
        }
    }
}
ログイン後にコピー

出力結果は以下の通りです:

It's Method of OuterClass
It's Method of Innerclass
ログイン後にコピー

(2) 内部クラスのインスタンス化

内部クラスのインスタンス化は通常のクラスとは異なり、必要に応じていつでもインスタンス化できますが、内部クラスは外部クラスのインスタンス化後にインスタンス化する必要があります。そうして初めてインスタンス化され、外部クラスとの関係を確立することができます

つまり、外部クラスの非静的メソッドでは、内部クラスのオブジェクトをインスタンス化できます

private void outerMethod() {
    System.out.println("It's Method of OuterClass");
    Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊
}
ログイン後にコピー

しかし、静的メソッドでは注意が必要です! ! ! !静的メソッドで内部クラスを直接 new することはできません。そうしないと、エラーが発生します:

OuterClass 型の囲みインスタンスはアクセスできません。OuterClass 型の囲みインスタンスで割り当てを修飾する必要があります (例: x.new A() where x)。これは、クラスがインスタンス化される前に静的メソッドが使用できるためです。この時点では、動的内部クラスはまだインスタンス化されていません。 ? 存在しないものを呼び出すことはできません。

Static メソッドで新しい内部クラスを作成したい場合は、内部クラスを Static として宣言できます

public class OuterClass {
    private void outerMethod() {
        System.out.println("It's Method of OuterClass");
    }
 
    public static void main(String[] args) {
        Innerclass in = new Innerclass();
        in.innerMethod();
    }
 
    static class Innerclass {//把内部类声明为static
        public void innerMethod() {
            System.out.println("It's Method of innerMethod");
 
        }
    }
 
}
ログイン後にコピー

もちろん、static メソッドは通常は使用されませんが、このメソッドをお勧めします: x.new A() 、ここで、xは外部クラスOuterClassのインスタンス、Aは内部クラスInnerclass

package innerclass;
public class OuterClass {
    private void outerMethod() {
        System.out.println("It's Method of OuterClass");
    }
    public static void main(String[] args) {
        OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式
        in.innerMethod();
    }
    class Innerclass {
        public void innerMethod() {
            System.out.println("It's Method of innerMethod");
        }
    }
}
ログイン後にコピー

x.new A()、xは外部クラスOuterClassのインスタンス、Aはクラスclass Innerclass、もちろんそれは可能です

(3) 内部クラスをいつ使用するか? 典型的な状況は、内部クラスが特定のクラスを継承するか、特定のインターフェイスを実装し、内部クラスのコードがオブジェクトを操作することです。それを作成する外部クラスの。したがって、内部クラスは、外部クラスへの何らかのウィンドウを提供すると考えることができます。

内部クラスを使用する最も魅力的な理由は、各内部クラスが (インターフェースの) 実装から独立して継承できるため、外部クラスが (インターフェース) の実装を継承しているかどうかに関係なく、内部クラスにはすべての実装が存在しないことです。効果。内部クラスによって提供される、複数の具象クラスまたは抽象クラスから継承する機能がなければ、設計およびプログラミングの問題によっては解決が困難になることがあります。この観点から見ると、内部クラスによって多重継承ソリューションが完成します。インターフェイスは問題の一部を解決し、内部クラスは効果的に「多重継承」を実装します。

(4) 静的メソッドで内部クラスをインスタンス化する例: (内部クラスは静的メソッドに配置されます)

public static void main(String[] args) {
    OuterClass out = new OuterClass();//外部实例
    OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类
    in.innerMethod();
}
ログイン後にコピー

per.speak() は呼び出すことができますが、per.say() は呼び出すことができません。 per は Person オブジェクトです。サブクラスのメソッドを呼び出したい場合は、((Boy) per).say(); に強制的にダウンキャストするか、Boy per = new Boy(); に直接変更できます。内部クラスのカスタム メソッドを呼び出したい場合は、内部クラスのオブジェクトを通じて呼び出す必要があることがわかります。では、匿名内部クラスに名前さえない場合、どうやって内部クラスのカスタム メソッドを呼び出すことができるのでしょうか?


(2) 匿名内部クラス

匿名内部クラスも名前のない内部クラスです。名前がないため、匿名内部クラスは通常、コード記述を簡素化するために使用されます。前提条件があります。親クラスを継承するか、インターフェイスを実装する必要がありますが、親クラスを継承したり、インターフェイスを実装したりできるのは 1 つだけです。

匿名内部クラスについては、さらに 2 つのルールがあります:

1) システムが匿名内部クラスを作成すると、すぐに内部クラスのオブジェクトが作成されるため、匿名内部クラスを抽象クラスにすることはできません。したがって、匿名内部クラスを抽象クラスとして定義することはできません。

2) 匿名内部クラスはコンストラクター (コンストラクター) を定義しません。匿名内部クラスはクラス名を持たないため、コンストラクターを定義できません。しかし、匿名内部クラスはインスタンス初期化ブロックを定義できます。

匿名クラスの存在を確認する方法。 ? ?名前が見えません。親クラスから new で作成されたオブジェクトのように感じます。また、匿名クラスには名前がありません。

まず疑似コードを見てみましょう

package javatest2;
public class JavaTest2 {
    public static void main(String[] args) {
        class Boy implements Person {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        }
        Person per = new Boy();
        per.speak();// 可调用
        per.say();// 不能调用
    }
}
interface Person {
    public void speak();
}
ログイン後にコピー

一般的に、オブジェクトを新規作成する場合、括弧の後にセミコロンが必要です。つまり、新規オブジェクトのステートメントが終了します。ただし、匿名の内部クラスがあり、括弧の後に中括弧があり、その中括弧内に新しいオブジェクトの特定の実装メソッドが含まれる場合は異なります。抽象クラスを直接 new することはできないことがわかっているため、その実装クラスを new する前に、まず実装クラスを作成する必要があります。上記の疑似コードは、new が Father の実装クラスであり、この実装クラスが匿名の内部クラスであることを示しています。
実際、上記の匿名内部クラスは次のように分割できます:
abstract class Father(){
....
}
public class Test{
   Father f1 = new Father(){ .... }  //这里就是有个匿名内部类
}
ログイン後にコピー

匿名内部クラスの使用法を体験するために、最初に例を見てみましょう:


运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上

public class JavaTest2 {
    public static void main(String[] args) {
        Person per = new Person() {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        };
        per.speak();// 可调用
        per.say();// 出错,不能调用
    }
}
 
interface Person {
    public void speak();
}
ログイン後にコピー

这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。

若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:

(1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。

(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:

public class JavaTest2 {
    public static void main(String[] args) {
        new Person() {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
 
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        }.say();// 直接调用匿名内部类的方法
    }
}
interface Person {
    public void speak();
}
ログイン後にコピー


更多内部类和匿名内部类的用法相关文章请关注PHP中文网!

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!