使用内部クラス

章X内部クラス

10.1内部クラスを定義する方法

コード10.1-1に示すように

public class Parcel1 {
    public class Contents{
        private int value = 0;
    
        public int getValue(){
            return value;
        }
    }
}

これは、クラス定義内の非常に単純な方法で、あなたは、単に別のクラスの内部クラスとしては、内容的のクラス定義は、内部クラスと呼ばれることができます

その後、としてコード10.1-1、それにコンテンツの内容にアクセスする方法をプログラマに示しますか?

コード10.1-2に示すように

public class Parcel1 {

    public class Contents{
        private int value = 0;

        public int getValue(){
            return value;
        }
    }

    public Contents contents(){
        return new Contents();
    }

    public static void main(String[] args) {
        Parcel1 p1 = new Parcel1();
        Parcel1.Contents pc1 = p1.contents();
        System.out.println(pc1.getValue());
    }
}

出力:0

上記のコードは、それを見るのが好き、あなたは外部のクラスを使用することができ、内容を基準点と同等の内容を、アクセスするためのメソッドを書くことができます。このクラスは、同様に、内部クラスへの参照を作成する方法の中で定義されますParcel1.ContentsのPC1 = p1.contents()に示すように、コンテンツの内部クラスにPC1アクセスと同等のものを保持しています。

今、私は内容10.1-2メソッドが静的メソッドになると、PC1はまたそれへのアクセス権を持って、質問がありますか?

そして、なぜそれを訪問していない、生活が困難にコンパイル?以下の分析を考えてみましょう。

外部クラスへの道10.2リンク

あなただけ強制的にロードするかのように、このようにコードを書きたい、なぜここを参照してください、あなたは理解していませんか?それとも、トラブルの多くは、完全に直接得た内部クラスを定義し、クラスを再定義すると思うし、今私たちのための方法の中で定義され、このクラスの利点を見ていないように見えるん。次の例を見てください10.2-1

public class Parcel2 {

    private static int i = 11;

    public class Parcel2Inner {

        public Parcel2Inner(){
            i++;
        }

        public int getValue(){
            return i;
        }

    }

    public Parcel2Inner parcel2Inner(){
        return new Parcel2Inner();
    }

    public static void main(String[] args) {
        Parcel2 p2 = new Parcel2();
        for(int i = 0;i < 5;i++){
            p2.parcel2Inner();
        }
        System.out.println("p2.i = " + p2.i);
    }
}

出力:16

オブジェクトが生成され、リンクのその周辺オブジェクトされたときに、内部クラス・オブジェクトを作成するときに上記のコードに示すように、インナークラスParcel2Inner私のParcel2値にアクセス可能であり、これもでき値が変更されます。

だから、質問は内部クラスのオブジェクトにそれを作成する方法、ありますか?プログラマは右、メソッドはクラスの外にオブジェクトを返すたびに書き込むことはできませんか?コード10.2-2を参照してください。

public class Parcel3 {

    public class Contents {

        public Parcel3 dotThis(){
            return Parcel3.this;
        }

        public String toString(){
            return "Contents";
        }
    }

    public Parcel3 contents(){
        return new Contents().dotThis();
    }

    public String toString(){
        return "Parcel3";
    }

    public static void main(String[] args) {
        Parcel3 pc3 = new Parcel3();
        Contents c = pc3.new Contents();
        Parcel3 parcel3 = pc3.contents();
        System.out.println(pc3);
        System.out.println(c);
        System.out.println(parcel3);
    }
}

出力:
Parcel3
内容
Parcel3

上記のコードに示すように、Parcel3コンテンツクラスは、内部を画定する、内部クラスがメソッドdotThis()を定義し、この方法は、外部のターゲットクラスの値を返し、クラス外部コンテンツ()メソッドは、この方法があります返された参照またはクラスの外。

10.3上方遷移クラス内部

この資料では、このクラスは内部クラスを保持しているアクセス今すぐ表示するために、そして、そのようなクラスとは何の関係もありません、このような内部型へのアクセスにそれを保持する方法ですか?そして、それは何を内部クラスと最終的には上向きの遷移が重要ですか?
図10.3-1

public interface Animal {

    void eat();
}

public class Parcel4 {

    private class Dog implements Animal {

        @Override
        public void eat() {
            System.out.println("啃骨头");
        }
    }

    public Animal getDog(){
        return new Dog();
    }

    public static void main(String[] args) {
        Parcel4 p4 = new Parcel4();
        //Animal dog = p4.new Dog();
        Animal dog = p4.getDog();
        dog.eat();
    }
}

出力:骨の上かじります

私はあなたのすべてを知っていると確信しています。この出力は、犬はおそらく訪問されていません。このクラスのクラスのいずれかが、なぜあなたはそれへのアクセスを得ることができ、民間、非によって変更されますか?Parcel4が公開されているので、一瞬の視線のためだと思う、とParcel4は、その内部クラスにアクセスすることができ、その後、あなたはParcel4動物内部クラスにもアクセスすることができますクラスの犬で、犬クラスは動物のインタフェースを実装したものですので、getDog( )コードをより美しくする、上方遷移の目的を達成するようにサブクラス方法は、動物のクラスを返すあります。

任意のクラスの内部の方法と範囲で定義された10.4

上に示したクラス内のいくつかの定義は、私はそれを書くための方法や内部クラスの定義内の役割をしたい場合はどのように共通の内部クラスの定義はありますか?
あなたは定義のこれらのタイプのアイデアを検討するかもしれません。

  1. 私は、参照インタフェースを返すために内部クラスを定義するインタフェースを実装する内部クラスを定義したいと思います
  2. 私は、問題を解決したい、とこのクラスは、人々が使用できるように、定義がカプセル化されていることで、それは、一般に公開したくありません
  3. 私は怠け者だったので...

以下は、いくつかの定義によって内部クラスです。

  • 方法(ローカル内部)で定義されたクラス
  • クラスでは、スコープ内のプロセスにおける内部(内側部材クラス)の範囲に定義されています
  • クラスは、匿名のインターフェース(匿名内部クラス)を実装します
  • クラスの非デフォルトコンストラクタを拡張する匿名クラス
  • 初期化動作のフィールドを実行する匿名クラス、
  • 一例として、設定を初期化する匿名クラス
  • クラス内に定義された方法はまた、部分的な内部クラスとして知られています
public class Parcel5 {
        private Destination destination(String s){
    
            class PDestination implements Destination{
    
                String label;
    
                public PDestination(String whereTo){
                    label = whereTo;
                }
    
                @Override
                public String readLabel() {
                    return label;
                }
            }
            return new PDestination(s);
        }
    
        public static void main(String[] args) {
            Parcel5 p5 = new Parcel5();
            Destination destination = p5.destination("China");
            System.out.println(destination.readLabel());
        }
}

出力:中国

上記のコードに示すように、この方法は、クラスで定義されたとき、あなたは方法の準備に挿入することができますし、内部クラス属性はすべて分類されているときに、非常に好奇心が強い、内部クラス、私はこのコードを書いています実行のプロセスはどのようなものです、デバッガは、私が見つけた、なくなっているp5.destination最初の実行が新しいPDestination(複数可)を返します(「中国」)の実装が、その後、初期化PDestinationを、行くときに、外部とのどのたちクラスの初期化方法は同じであるが、この方法は、クラス内部アクセスへのアクセスを提供します。
注:ローカル内部クラスの定義は、アクセス修飾子を持つことができません

  • クラスでは、スコープ内部の方法の範囲に定義されています
public class Parcel6 {
        // 吃椰子的方法
        private void eatCoconut(boolean flag){
            // 如果可以吃椰子的话
            if(flag){
                class Coconut {
                    private String pipe;
    
                    public Coconut(String pipe){
                        this.pipe = pipe;
                    }
    
                    // 喝椰子汁的方法
                    String drinkCoconutJuice(){
                        System.out.println("喝椰子汁");
                        return pipe;
                    }
                }
                // 提供一个吸管,可以喝椰子汁
                Coconut coconut = new Coconut("用吸管喝");
                coconut.drinkCoconutJuice();
            }
    
            /**
             * 如果可以吃椰子的话,你才可以用吸管喝椰子汁
             * 如果不能接到喝椰子汁的指令的话,那么你就不能喝椰子汁
             */
            // Coconut coconut = new Coconut("用吸管喝");
            // coconut.drinkCoconutJuice();
        }
    
        public static void main(String[] args) {
            Parcel6 p6 = new Parcel6();
            p6.eatCoconut(true);
        }
}

出力:ココナッツミルクを飲みます

上記のコードに示すように、唯一のプログラマは、プログラムを伝え、プログラムは、このコマンドを受信したときに、今私は、ココナッツを食べたい、それはあなたが飲むことができるので、すぐにあなたのためのココナッツとわらを用意し、良い答えです新鮮なココナッツミルク。プログラマはココナッツを食べにしたくない場合は、プログラムはココナッツのために準備、ましてやあなたはココナッツミルクを飲ませません。

  • インターフェイス匿名を実装するクラス

我々は、すべてのインターフェイスを使用すると、インターフェイスのオブジェクトを返すことができないことを意味する、インスタンス化できないことを知って、あなただけのオブジェクトが、このインタフェースのサブクラスで返すことができますが、これは以下のように定義されている場合、あなたはそれを疑うでしょうか?

public interface Contents {

    int getValue();
}

public class Parcel7 {

    private Contents contents(){
        return new Contents() {

            private int value = 11;

            @Override
            public int getValue() {
                return value;
            }
        };
    }

    public static void main(String[] args) {
        Parcel7 p7 = new Parcel7();
        System.out.println(p7.contents().getValue());
    }
}

出力:11

なぜインタフェースを定義返すことができますか?しかし、また、{}、最終的にどのような地獄ありますか?実際には、これは匿名の内部クラスの書き込みの一種であり、実際には上述した内部クラスと上方遷移が類似しています。その匿名内部クラスは新しい内容を()、実際に内容を実装するクラスに属しているが、実装クラス名が隠されている、とのコードサンプルは、次を変換するために使用することができ返します。

public class Parcel7b {

    private class MyContents implements Contents {

        private int value = 11;

        @Override
        public int getValue() {
            return 11;
        }
    }

    public Contents contents(){
        return new MyContents();
    }

    public static void main(String[] args) {
        Parcel7b parcel7b = new Parcel7b();
        System.out.println(parcel7b.contents().getValue());
    }
}

結果の出力は、あなたはそれを知っている必要があります〜!あなたはこのコードとコードセクション10.3が非常に一貫示さ思いませんか?

  • クラスの非デフォルトコンストラクタを拡張する匿名クラス

あなたはそれを表現する方法を、パラメータ(デフォルト以外のコンストラクタ)でコンストラクタを返すようにしたい場合は?

public class WithArgsConstructor {

    private int sum;

    public WithArgsConstructor(int sum){
        this.sum = sum;
    }

    public int sumAll(){
        return sum;
    }
}

public class Parcel8 {

    private WithArgsConstructor withArgsConstructor(int x){

        // 返回WithArgsConstructor带参数的构造器,执行字段初始化
        return new WithArgsConstructor(x){

            // 重写sumAll方法,实现子类的执行逻辑
            @Override
            public int sumAll(){
                return super.sumAll() * 2;
            }
        };
    }

    public static void main(String[] args) {
        Parcel8 p8 = new Parcel8();
        System.out.println(p8.withArgsConstructor(10).sumAll());
    }
}

WithArgsConstructorコードは非常にシンプルである上に、フィールドの合計の定義は、コンストラクタの初期化、sumAll方法は和、withArgsConstructor方法Parcel8は直接xの値を返すの値を返しますが、この時点で、あなたは戻り値に何かをしたいです特別な治療は、例えば、あなたは、クラスを定義するビジネス・ロジック・サブクラスを実装するためにsumAllメソッドをオーバーライドします。内部クラスの終わりを意味するものではありませんが、式の最後が、この表現は、匿名内部クラスを含むように起こる;「」Javaで考えることは、コード・ページ198で述べています。

  • 匿名クラス、それはフィールドの初期化を実行することができます

上記のコードは、実際に操作を開始することができますが、コンストラクタの引数場合、フィールドのコンストラクタを初期化することによって実行され、あなたはまた、初期化動作を行うことができますか?また、これは可能です。

public class Parcel9 {

    private Destination destination(String dest){
        return new Destination() {

            // 初始化赋值操作
            private String label = dest;

            @Override
            public String readLabel() {
                return label;
            }
        };
    }

    public static void main(String[] args) {
        Parcel9 p9 = new Parcel9();
        System.out.println(p9.destination("pen").readLabel());
    }
}

アイデアのP198をプログラミングJavaは、最終ではない場合、私は最終的に、またコンパイラエラーとして定義されていないため、コンパイラは、提案、質問のこの部分を文句を言うだろう、フィールドが動作するように初期化されている場合、そのパラメータは最終的でなければならないと述べました。
私は、民間、公共を読んだときに、問題がない、プライベートな問題を考慮していません。

私は翻訳の問題の中国語版であるかわからない、またはこの質問を除外するためのアップグレードのように多くのJavaバージョンの後、私が書かれているものを何も独自の研究を持っていない、そこにもあるダニエルは、問題を説明するのに役立つ知っているしたいと考えています。

  • 一例として、設定を初期化する匿名クラス
public abstract class Base {

    public Base(int i){
        System.out.println("Base Constructor = " + i);
    }

    abstract void f();
}

public class AnonymousConstructor {

    private static Base getBase(int i){

        return new Base(i){
            {
                System.out.println("Base Initialization" + i);
            }

            @Override
            public void f(){
                System.out.println("AnonymousConstructor.f()方法被调用了");
            }
        };
    }

    public static void main(String[] args) {
        Base base = getBase(57);
        base.f();
    }
}

出力:
ベース= 57は、コンストラクタである
ベース57は、初期化され
()メソッドが呼び出されAnonymousConstructor.f

「非デフォルトコンストラクタクラスを拡張する匿名クラス、」このコードとは、初期化プロセスは、コンストラクタによって達成され、同じカテゴリに属しています。

10.5ネストされたクラス

10.4我々は今、我々はコンテンツ()メソッドは静的になり、なぜ、10.1が提起したいくつかの質問を解決するため、エラーの原因をコンパイルする必要があり、道の6つの内部クラス定義を導入しました:

アイデアP201ページをプログラミングするJava、それは言う:あなたはstaticとして宣言内部クラスを入れ、内部クラスの前の関係とその外側のクラスを生成する必要がない場合。これは、そのクラスの周囲に定義された内部クラスですが、多くの場合、ネストされたクラスの内部クラスとその外側のクラスの前に接触のいくつかの種類を生成しませんネストされたクラスと呼ばれますが、実際に独立して存在することができます。ネストされたクラスは、内部の静的クラスと呼ばれています。
静的内部クラスを意味する:
(1)オブジェクトのネストされたクラスを作成するには、オブジェクトは、その囲みクラスを必要としない
(2)ネストされたクラスから非静的包含するクラスオブジェクトにアクセスすることができません

コード例10.5-1

public class Parcel10 {

    private int value = 11;

    static int bValue = 12;

    // 静态内部类
    private static class PContents implements Contents {

        // 编译报错,静态内部类PContents中没有叫value的字段
        @Override
        public int getValue() {
            return value;
        }

        // 编译不报错,静态内部类PContents可以访问静态属性bValue
        public int f(){
            return bValue;
        }
    }

    // 普通内部类
    private class PDestination implements Destination {

        @Override
        public String readLabel() {
            return "label";
        }
    }

    // 编译不报错,因为静态方法可以访问静态内部类
    public static Contents contents(){
        return new PContents();
    }

    // 编译报错,因为非静态方法不能访问静态内部类
    public Contents contents2(){
        Parcel10 p10 = new Parcel10();
        return p10.new PContents();
    }

    // 编译不报错,静态方法可以访问非静态内部类
    public static Destination destination(){
        Parcel10 p10 = new Parcel10();
        return p10.new PDestination();
    }

    // 编译不报错,非静态方法可以访问非静态内部类
    public Destination destination2(){
        return new PDestination();
    }
}

10.1コンパイラエラーが静的メソッドを直接非静的内部クラスにアクセスし、クラスを囲んでオブジェクトを作成する共通の内部クラスにアクセスする必要があることはできないで、上記のコードによって説明することができます。

10.5.2内部インターフェースクラス

ナニ?内部インターフェイスは、メソッドのみを定義することができ、また、クラスそれの内部インタフェースを置くことができますか?次のことができます!
通常の状況下では、それは任意の内部インターフェイスコードに配置することはできませんが、インタフェースの一部として、ネストされたクラスは、デフォルトのクラスのいずれかにインターフェイスを入れて、パブリックおよび静的です。クラスは静的ですが、インターフェースの規則に違反しない名前空間のネストされたクラスインターフェイス、に配置されますので、あなたも、クラス内で外部クラスのインターフェイスを実装することができますが、一般的に、我々は、そのような書き込みを提唱していません

public interface InnerInterface {

    void f();

    class InnerClass implements InnerInterface {

        @Override
        public void f() {
            System.out.println("实现了接口的方法");
        }

        public static void main(String[] args) {
            new InnerClass().f();
        }
    }

    // 不能在接口中使用main方法,你必须把它定义在接口的内部类中
//    public static void main(String[] args) {}
}

出力:インターフェイスメソッドを実装します

10.5.3内部クラスは多重継承を実装します

Javaでは、クラスとクラスの間の関係は、クラスとインタフェースとの間の関係は、クラスがより実施することができることが、多くの1つであり、典型的には界面で、次いで、連続単一の原理であるものの一つでありますインターフェイス、および内部クラスおよびインタフェースは「多重継承」と併せて実施することが可能で、使用が実現するキーワードが、インターフェースと内部クラスの実装の多重継承のシミュレーションを拡張することを意味するものではありません。

参考chenssyの記事http://www.cnblogs.com/chenssy/p/3389027.htmlは非常に良い書かれています。

public class Food {

    private class InnerFruit implements Fruit{
        void meakFruit(){
            System.out.println("种一个水果");
        }
    }

    private class InnerMeat implements Meat{
        void makeMeat(){
            System.out.println("煮一块肉");
        }
    }

    public Fruit fruit(){
        return new InnerFruit();
    }

    public Meat meat(){
        return new InnerMeat();
    }

    public static void main(String[] args) {
        Food food = new Food();
        InnerFruit innerFruit = (InnerFruit)food.fruit();
        innerFruit.meakFruit();
        InnerMeat innerMeat = (InnerMeat) food.meat();
        innerMeat.makeMeat();
    }
}

出力:
果物の種類
や肉の部分を調理

10.6継承内部クラス

内部クラスとの間にも継承、似ていますが、まったく同じではない一般的なカテゴリ間の継承を実現することができます。

public class BaseClass {

    class BaseInnerClass {

        public void f(){
            System.out.println("BaseInnerClass.f()");
        }
    }

    private void g(){
        System.out.println("BaseClass.g()");
    }
}
/**
 *  可以看到,InheritInner只是继承自内部类BaseInnerClass,而不是外围类
 *  但是默认的构造方式会报编译错误,
 *  必须使用类似enclosingClassReference.super()才能编译通过
 *  用来来说明内部类与外部类对象引用之间的关联。
 *
 */
public class InheritInner extends BaseClass.BaseInnerClass{

    // 编译出错
//    public InheritInner(){}

    public InheritInner(BaseClass bc){
        bc.super();
    }

    @Override
    public void f() {
        System.out.println("InheritInner.f()");
    }

    /*
    * 加上@Override 会报错,因为BaseInnerClass 中没有g()方法
    * 这也是为什么覆写一定要加上Override注解的原因,否则默认是本类
    * 中持有的方法,会造成误解,程序员以为g()方法是重写过后的。
    @Override
    public void g(){
        System.out.println("InheritInner.g()");
    }*/

    public static void main(String[] args) {
        BaseClass baseClass = new BaseClass();
        InheritInner inheritInner = new InheritInner(baseClass);
        inheritInner.f();
    }
}

出力:InheritInner.f()

内部クラス10.7をカバー

クラスビュー内のコードの最初のカバー部上に:

public class Man {

    private ManWithKnowledge man;

    protected class ManWithKnowledge {

        public void haveKnowledge(){
            System.out.println("当今社会是需要知识的");
        }
    }

    // 我们想让它输出子类的haveKnowledge()方法
    public Man(){
        System.out.println("当我们有了一个孩子,我们更希望他可以当一个科学家,而不是网红");
        new ManWithKnowledge().haveKnowledge();
    }
}

// 网红
public class InternetCelebrity extends Man {

    protected class ManWithKnowledge {

        public void haveKnowledge(){
            System.out.println("网红是当今社会的一种病态");
        }
    }

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

出力:私たちは子供を持っている場合は、我々はネット赤ではなく、科学者として彼がすることを願って
今日の社会は、知識の必要性であります

私たちは、内部クラスが覆われているデフォルト。だから我々は我々の推測を達成するために、出力InternetCelebrity.haveKnowledge()に彼をしたいが、出力ManWithKnowledge.haveKnowledge()メソッド。
継承された周辺機器クラス、インナークラスは特に奇跡的変化、2つの内部クラスは、独立していない場合、この例では、独自の名前空間内の両方、時間を示しています。

約10.8は、クラス内部のソースコードを表し、

各クラスは、オブジェクトの種類を作成するために、すべての情報が含まれているの.classファイルがありますので
同じことを、内部クラスの.classファイルが生成されます
:ような表現を
OneClass $ OneInnerClass

内部クラスの利点:1、コードのパッケージ部分、あなたが内部リファレンス、外部クラスを保持するために内部クラス、デフォルトのクラスを作成します。2、内部クラスに関係なく、外側のクラスがインタフェースを継承するかどうかに、ある程度の柔軟性を持っています内部クラスが影響を受けないために達成するため、; 3、内部クラスは、効果的に多重継承の問題を解決することができます。

おすすめ

転載: www.cnblogs.com/cxuanBlog/p/10965669.html