那么public方法返回私有类实例呢?

时间:2013-04-13 05:26:20

标签: java class package private public

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

  1. 有一个主要的。 (city.Main
  2. 有一个包裹。 (package castle
  3. 在包中,有一个公共类(castle.Guard)和一个包 - 私有类(castle.Princess)。
  4. 公共类返回私有类的实例怎么办?
  5. 这是我的代码:

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

    Princess.java

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

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

    我也做了一些研究。实际上我想模仿this answer。但我不知道为什么我的代码会抛出错误。

    感谢您的解释!


    编辑:

    我打算将castle-Princess 包 - 私有。我知道从包中返回一个 package-private 类,我应该为错误做好准备。但为什么that answer有效,但我的却没有?

5 个答案:

答案 0 :(得分:5)

Princess类默认作用于castle包,因此在city包中不可见。规避:

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

1)制作Princesspublic并使用它。

package castle;

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

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

castle \ IPrincess.java

// Interface definition
package castle;

public interface IPrincess {
    public void sayHi();
}

castle \ Princess.java

// Implement the interface in Princess class
package castle;

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

castle \ 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;
    }
}

city \ 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)或者,将所有类放在同一个包中。

答案 1 :(得分:1)

您无法返回类中私有作用域的类型。任何外部资源如何知道那个类型甚至IS是否属于另一个类的私有范围?

这种设计甚至不会编译。

修改:

简单的解决方案是将其公开,然后您可以在包外部使用它。

答案 2 :(得分:1)

您尝试模仿的答案有效,因为所有类都在同一个包中

如果您将UntrustworthyFriendFriend放在不同的软件包中(与您的方案一样),则会出现同样的问题。

Princess只能在public

的包裹外显示

<强> Princess.java

package castle;

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

另外,请务必将其导入Main

答案 3 :(得分: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修饰符,则无法在声明它的文件之外访问公主类。

答案 4 :(得分: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>  {
...

这就是你问的问题。诀窍是方法的返回类型是私有类实现的公共接口。你可以做类似的事情。