这是一个概念性的问题。
我通常以逻辑方式将代码组织在软件包中。
例如:数学运算进入my.package.math
或业务逻辑进入my.package.business
,依此类推。
在这几天里,我怀疑我是否想对Java中的程序包可见性施加的约束感到惊讶。
让我显示一些代码来更好地解释我的情况:
我有以下包结构:
+-- org.example
+-- greetings
| +-- RandomGreetings
+-- GreetingsService
|
+-- Main
和以下代码:
GreetingsService.java
package org.example;
import org.example.greetings.RandomGreetings;
public class GreetingsService {
public String greetingsToTheWorld(){
RandomGreetings greetings = new RandomGreetings();
return greetings.say() + " World";
}
}
RandomGreetings.java
package org.example.greetings;
import java.util.Random;
class RandomGreetings {
public String say() {
Random rand = new Random();
int value = rand.nextInt(2);
return value==0 ? "Hello" : "Hi";
}
}
Main.java
package org.example;
public class Main {
public static void main(String[] args) {
GreetingsService sayHelloService = new GreetingsService();
System.out.println(sayHelloService.greetingsToTheWorld());
}
}
正如我向您展示的,此代码无法编译,因为类
RandomGreetings
是包可见的,这意味着GreetingsService无法实例化它。可以在类
RandomGreetings
中公开解决此问题:public class GreetingsService {
...
}
但是对我来说,
RandomGreetings
是一种我想保持封装且不公开可见的实现。在这种情况下,世界(任何导入我可能产生的jar工件的人)都可以看到并调用该类,而这并不是我想要的。
另一个可能的解决方案是将
GreetingsService
移动到相同的RandomGreetings级别,如下所示:+-- org.example
+-- greetings
| +-- RandomGreetings
| |
| +-- GreetingsService
|
+-- Main
在这种情况下,代码可以成功编译并且将
RandomGreetings
封装起来,但是最后我遇到了另一个问题。我不能再按照逻辑顺序在包中组织该类。
在这种情况下,有几个班级,因此情况仍然可以控制,但是如果班级数量增加,我认为只会有一个独特的大包装。
我知道在Java中没有subpackage visibility,那么如何处理这种情况?
您将如何解决上述代码的问题?
最佳答案
当您要使用软件包时,它必须具有一些入口点,该入口点必须为public
。否则,您将无法使用该包装,将其丢弃。这意味着您的org.example.greetings
软件包必须包含某些东西,即public
,并且可以从“外部”使用/调用它。不必是您的RandomGreetings
类。
您可以定义一个接口(在org.example
包中),在您的RandomGreetings
类中实现该接口,并使用另一个public
方法创建并返回“可见的包” RandomGreetings
类。代码可能看起来像这样:
package org.example;
public interface Greeting {
public String say();
}
这由
RandomGreetings
类实现:package org.example.greetings;
import org.example.Greeting;
class RandomGreetings implements Greeting {
// ...
}
然后,定义一个
public
助手类,以从RandomGreetings
包中返回一个org.example.greetings
对象:package org.example.greetings;
import org.example.Greeting;
public GeneratorHelper {
public static Greeting buildIt() {
return new RandomGreetings();
}
}
使用
GeneratorHelper.buildIt()
方法时,您将获得一些实现Greeting
接口的对象。但是您不能访问RandomGreetings
类本身,因为它仍然是“包可见的”。