3

我正在尝试测试以下情况:

  1. 有一个主要的。( city.Main)
  2. 有一个包。( package castle)
  3. 在包中,有一个公共类(castle.Guard)和一个包私有类(castle.Princess)。
  4. 如果公共类返回私有类的实例怎么办?

这是我的代码:

主.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;
    }
}

公主.java

package castle;

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

请注意,其中的所有 4 个语句main()都有错误。

我也做过一些研究。事实上,我想模仿这个答案。但我不明白为什么我的代码会抛出错误。

感谢您的任何解释!


编辑:

我打算将castle-Princess package-private设为私有。我知道,通过从包中返回包私有类,我应该为错误做好准备。但是为什么这个答案有效,而我的答案无效?

4

5 回答 5

5

Princess类的默认范围为castlepackage ,因此它在citypackage 中不可见。为了规避:

(我们可以采用以下三种方法之一。)

1)制作Princess课程public并使用它。

package castle;

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

2)或者,定义 apublic interface并让Princess实现它并使用interface reference代替class reference。我更喜欢这个。

城堡\IPPrincess.java

// Interface definition
package castle;

public interface IPrincess {
    public void sayHi();
}

城堡\公主.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

公主.java

package castle;

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

另外,请确保将其导入Main.

于 2013-04-13T05:39:46.140 回答
0

问题在于 Princess 类的定义中有一个非常小的错误:

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 修饰符,则无法在声明它的文件之外访问 Princess 类。

于 2013-04-13T05:31:56.640 回答
0

您的示例有所不同,因为您的类位于不同的包中,并且从 Main 中看不到 Guard 和 Princess。

但是公共方法可以返回私有类的实例。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 回答