3

次の状況をテストしようとしています。

  1. メインがあります。( city.Main)
  2. パッケージがあります。( package castle)
  3. パッケージ内には、public クラス ( castle.Guard) とpackage-privateクラス ( castle.Princess) があります。
  4. パブリック クラスがプライベート クラスのインスタンスを返す場合はどうなるでしょうか。

これが私のコードです:

Main.java

package city;

import castle.Guard;

public class Main {

    public static void main(String[] args) {
        Princess princess = Guard.getPrincessStatic();
        // Error: Princess cannot be resolved to a type
        
        Guard.getPrincessStatic().sayHi();
        // Error: The type Princess is not visible
        
        Guard guard = new Guard();
        guard.getPrincess().sayHi();
        // Error: The type Princess is not visible
        
        guard.getPrincessMember().sayHi();
        // Error: The type Princess is not visible
    }

}

Guard.java

package castle;

public class Guard {

    public Princess getPrincess() {
        return new Princess();
    }

    public static Princess getPrincessStatic() {
        return new Princess();
    }
    
    private Princess m_princess = new Princess();
    
    public Princess getPrincessMember() {
        return m_princess;
    }
}

プリンセスジャバ

package castle;

class Princess {
    public void sayHi() { System.out.println("Hi world"); }
}

の 4 つのステートメントすべてにmain()エラーがあることに注意してください。

私もいくつかの研究を行ってきました。実際、私はこの答えを模倣したいと思っています。しかし、コードがエラーをスローする理由はわかりません。

説明をありがとう!


編集:

castle-Princess package-privateにするつもりです。package-privateクラスをそのパッケージから返すことで、エラーに備える必要があることはわかっています。しかし、なぜその答えが機能するのに、私の機能は機能しないのですか?

4

5 に答える 5

5

Princessclass はデフォルトでcastlepackage にスコープされているため、 package 内では見えませんcity。それを回避するには:

(次の 3 つのアプローチのいずれかを行うことができます。)

1)Princessクラスpublicを作成し、それを使用します。

package castle;

// added public modifier
public class Princess {
     public void sayHi() { System.out.println("Hi world"); }
}

public interface2) または、 aを定義してPrincess実装し、 のinterface reference代わりにを使用しclass referenceます。私はこれを好むでしょう。

お城\IPrincess.java

// Interface definition
package castle;

public interface IPrincess {
    public void sayHi();
}

城 \ Princess.java

// Implement the interface in Princess class
package castle;

class Princess implements IPrincess {
    public void sayHi() { System.out.println("Hi world"); }
}

城\ Guard.java

// Modify the Guard class
package castle;

public class Guard {
    public IPrincess getPrincess() {
        return new Princess();
    }
    public static IPrincess getPrincessStatic() {
        return new Princess();
    }

    // for here i use Princess instead of IPrincess. (@midnite)
    private Princess m_princess = new Princess();
    public IPrincess getPrincessMember() {
        return m_princess;
    }
}

都市\ Main.java

// Modify the main class
  package city;

  import castle.Guard;
  import castle.IPrincess;

  public class Main {

  public static void main(String[] args) {

     IPrincess princess = Guard.getPrincessStatic();

     Guard.getPrincessStatic().sayHi();

     Guard guard = new Guard();
     guard.getPrincess().sayHi();

     guard.getPrincessMember().sayHi();
   }
}

3) または、すべてのクラスを同じパッケージに入れます。

于 2013-04-13T05:31:41.483 に答える
1

クラス内で非公開スコープの型を返すことはできません。別のクラス内で非公開のスコープである場合、外部ソースはどのようにしてそのタイプが何であるかを知ることができますか?

この設計はコンパイルさえしません。

編集:

簡単な解決策は、それを公開して、パッケージの外部で使用できるようにすることです。

于 2013-04-13T05:30:05.443 に答える
1

すべてのクラスが同じパッケージ内にあるため、模倣しようとしている答えが機能します

と を別のパッケージに入れるUntrustworthyFriendFriend(シナリオとして)、同じ問題が発生します。

Princess次の場合にのみ、パッケージの外側に表示できますpublic

プリンセスジャバ

package castle;

public class Princess {
    public void sayHi() { System.out.println("Hi world"); }
}

また、必ずインポートしてMainください。

于 2013-04-13T05:39:46.140 に答える
0

クラスが異なるパッケージにあり、Guard と Princess が Main から見えないため、例は異なります。

ただし、パブリック メソッドはプライベート クラスのインスタンスを返すことができます。JDK には例がたくさんあります。java.util.Arrays

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}
...
private static class ArrayList<E> extends AbstractList<E>  {
...

それはあなたが尋ねるものです。秘訣は、メソッドの戻り値の型が、プライベート クラスが実装するパブリック インターフェイスであることです。同様のことができます。

于 2013-04-13T06:10:11.030 に答える
0

問題は、プリンセス クラスの定義の非常に小さなエラーにあります。

package castle;

class Princess {
    public void sayHi() { System.out.println("Hi world"); }
}

public最初はすべて問題ないように見えますが、クラス名の前に修飾子がありません:

package castle;

//here!
public class Princess {
    public void sayHi() { System.out.println("Hi world"); }
}

public 修飾子がないと、宣言されているファイルの外部からプリンセス クラスにアクセスできません。

于 2013-04-13T05:31:56.640 に答える