这是一个概念性问题。
我通常以逻辑方式将代码组织在软件包中。
例如:数学运算进入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无法实例化它。
可以通过将 public 放在类RandomGreetings
中来解决此问题:
public class GreetingsService {
...
}
但是对我来说RandomGreetings
是一个我想保持封装且不公开的实现。
在这种情况下,世界(任何导入我可能产生的jar工件的人)都可以看到并调用该类,而那并不是我想要的。
另一种可能的解决方案是将GreetingsService
移动到相同的RandomGreetings级别,如下所示:
+-- org.example
+-- greetings
| +-- RandomGreetings
| |
| +-- GreetingsService
|
+-- Main
在这种情况下,代码可以成功编译并且RandomGreetings
被封装,但是我最终遇到了另一个问题。
我不能再按照逻辑顺序在包中组织该类。
在这种情况下,有几个班级,因此情况仍然可以控制,但是如果班级数量增加,我认为只会有一个独特的大包装。
我知道在Java中没有subpackage visibility,那么如何处理这种情况?
您如何解决上面我的代码的问题?
答案 0 :(得分:1)
要使用程序包时,它必须具有一些入口点,该入口点必须为public
。否则,您将无法使用该包装,将其丢弃。这意味着您的org.example.greetings
软件包必须包含public
,并且可以从“外部”使用/调用。不必是您的RandomGreetings
班。
您可以定义一个接口(在org.example
包中),在您的RandomGreetings
类中实现它,并使用另一个public
方法来创建并返回“可见的包” {{1 }}类。代码可能看起来像这样:
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
类本身,因为它仍然是“包可见的”。