2

这是一个概念问题。
我通常按​​逻辑将代码组织在包中。例如:数学运算进入my.package.math或业务逻辑进入my.package.business等等。

在这些日子里,我有一个疑问,我想分享关于java中包可见性强加的约束。

让我展示一些代码来更好地解释我的情况:我有以下包结构:

+-- org.example
    +-- greetings
    |   +-- RandomGreetings
    +-- GreetingsService
    |
    +-- Main

和以下代码:

问候服务.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";
    }
}

主.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,那么您如何处理这种情况?
你将如何解决我上面的代码的问题?

4

1 回答 1

1

当你想使用一个包时,它必须有一些入口点,它必须是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中返回一个对象:RandomGreetingsorg.example.greetings

package org.example.greetings;

import org.example.Greeting;

public GeneratorHelper {
    public static Greeting buildIt() {
         return new RandomGreetings();
    }
}

当您使用该GeneratorHelper.buildIt()方法时,您会得到一些实现Greeting接口的对象。但是您不能访问RandomGreetings该类本身,因为它仍然是“包可见”。

于 2019-05-18T17:22:27.980 回答