105

我现在正在与其他人一起在一个 grails 项目中工作。我必须编写一些 Java 类。但我需要访问用 groovy 创建的可搜索对象。看来,这个对象必须放在默认包中。

我的问题是:有没有办法从命名包中的 Java 类访问默认包中的这个对象?

4

5 回答 5

133

您不能使用命名包中的默认包中的类。
从技术上讲,您可以,如 Sharique Abdullah通过反射 API的回答所示,但是来自未命名命名空间的类不在导入声明的范围内)

在 J2SE 1.4 之前,您可以使用如下语法从默认包中导入类:

import Unfinished;

已经不允许了。因此,要从打包类中访问默认包类,需要将默认包类移动到它自己的包中。

如果您可以访问 groovy 生成的源代码,则需要进行一些后处理以将文件移动到专用包中并在其开头添加此“包”指令。


2014 年更新:对于 JDK7 和 JDK8,错误 6975015描述了更严格的禁止从未命名包导入的禁令。

TypeName必须是类类型、接口类型、枚举类型或注释类型的规范名称。
该类型必须是命名包的成员,或者是其最外层词法封闭类型是命名包的成员的类型的成员,否则会发生编译时错误


Andreas在评论中指出:

“为什么[默认包]首先存在?设计错误?”

不,这是故意的。
JLS 7.4.2。Unnamed Packages说:“Java SE 平台提供了未命名的包,主要是为了方便开发小型或临时应用程序或刚开始开发时”。

于 2008-11-12T12:44:01.597 回答
62

事实上,你可以。

到目前为止,您可以使用反射 API 访问任何类。至少我能够:)

Class fooClass = Class.forName("FooBar");
Method fooMethod = fooClass.getMethod("fooMethod", String.class);

String fooReturned = (String)fooMethod.invoke(fooClass.newInstance(), "I did it");
于 2009-02-18T14:10:45.080 回答
7

使用jarjar重新打包 jar 文件,规则如下:

rule * <target package name>.@1

源jar文件默认包中的所有类都会移动到目标包中,从而可以访问。

于 2014-03-13T02:37:03.243 回答
3

您可以在代码中使用包Groovy,一切都会正常工作。

这可能意味着对代码的轻微重组,grails-app一开始会有点痛苦,但在大型 grails 项目中,将东西组织在包中才有意义。我们使用 Java 标准包命名约定com.foo.<app>.<package>

正如您所发现的,将所有内容都放在默认包中会成为集成的障碍。

控制器似乎是一个 Grails 工件(或工件),它拒绝放入 Java 包中。可能我只是还没有弄清楚Convention。;-)

于 2008-11-12T14:12:20.873 回答
0

只是为了完成这个想法:

default-package 内部,您可以访问位于命名包中的对象。

于 2020-04-26T08:10:11.200 回答