web-dev-qa-db-ja.com

Javaでプライベート内部クラスメンバーをパブリックにする理由

Javaでクラスの外部からアクセスできない場合にプライベートプライベートクラスpublicのメンバーを宣言する理由は何ですか?それともできますか?

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }
}
33
vitaut

InnerEvenIteratorクラスがクラスを拡張したり、インターフェースを実装したりしない場合、他のクラスがそのインスタンスにアクセスできないため、それはナンセンスだと思います。

ただし、他の非プライベートクラスまたはインターフェイスを拡張または実装する場合は、理にかなっています。例:

interface EvenIterator {
    public boolean hasNext();
}


public class DataStructure {
    // ...

    private class InnerEvenIterator implements EvenIterator{
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }

    InnerEvenIterator iterator;

    public EvenIterator getIterator(){
         return iterator;
    }     

}
32
Gursel Koca

このメソッドはpublicにして、意味的にパブリックであることを示すことができます。ただし、コンパイラはこの特定のケースでは可視性ルールを適用しません。

いくつかのリファクタリング中に、この内部クラスをトップレベルにする必要があると想像してください。このメソッドがprivateである場合、どのようにしてpublicにするか、またはより制限的な修飾子を使用するかをどのように決定しますか?メソッドをpublicとして宣言すると、元の作者の意図が読者に伝わります。このメソッドは、実装の詳細とは見なされません。

14
axtavt

interfaceを実装するときに役立ちます。

class DataStructure implements Iterable<DataStructure> {

    @Override
    public Iterator<DataStructure> iterator() {
        return new InnerEvenIterator();
    }
    // ...        

    private class InnerEvenIterator implements Iterator<DataStructure> {
        // ...    
        public boolean hasNext() { // Why public?
            // ...
            return false;
        }

        @Override
        public DataStructure next() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    public static void main(String[] ex) {
        DataStructure ds = new DataStructure();
        Iterator<DataStructure> ids = ds.iterator();
        ids.hasNext(); // accessable            
    }
}
8

サンプルコードにIteratorインターフェース部分の実装がないと思います。その場合、あなたはできませんhasNext()メソッドにpublic以外の可視性識別子を設定します。これにより、可視性が低下するためです(インターフェースメソッドにはpublic可視性があります)。コンパイルされません。

4

有用でないアクセス修飾子の多くの組み合わせがあります。プライベート内部クラスのパブリックメソッドは、パブリッククラス/インターフェイスでパブリックメソッドを実装する場合にのみ役立ちます。

public class DataStructure {
    // ...

    private class InnerEvenIterator implements Iterator {
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }

    public Iterator iterator() {
        return new InnerEvenIterator();
    }
}

ところで:抽象クラスは、実際にはpublicであるにもかかわらず、しばしばprotectedコンストラクターを持っています

3
Peter Lawrey

内部クラスがプライベートの場合、外部クラスの外部から名前でアクセスすることはできません。内部クラスと外部クラスは、互いのプライベートメソッドとプライベートインスタンス変数にアクセスできます。内部クラスまたは外部クラス内にいる限り、修飾子publicおよびprivateは同じ効果があります。あなたのコード例では:

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }
}

クラスDataStructureに関する限り、これは完全に以下と同等です。

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

        private boolean hasNext() {
            // ...
        }
    }
}

これは、DataStructureだけがアクセスできるため、パブリックまたはプライベートのどちらに設定してもかまいません。いずれにせよ、DataStructureは、それにアクセスできる唯一のクラスです。どちらの修飾子を使用しても、機能上の違いはありません。ランダムに選択できないのは、実装時または拡張時だけです。その場合、アクセスを減らすことはできませんが、増やすことはできます。したがって、抽象メソッドがアクセスを保護している場合は、それをパブリックに変更できます。どちらも実際には何の違いもありません。

他のクラスで内部クラスを使用することを計画している場合、それをパブリックにする場合、おそらく最初から内部クラスにするべきではありません。

さらに、他のクラスを拡張または実装する内部クラスの要件はありません。彼らがそうすることは一般的かもしれませんが、それは確かに必要ではありません。

1
sage88