如何访问默认包中的 java 类?

Posted

技术标签:

【中文标题】如何访问默认包中的 java 类?【英文标题】:How to access java-classes in the default-package? 【发布时间】:2010-09-21 23:31:09 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

You can’t use 来自命名包的默认包中的类。 (技术上您可以,如 Sharique Abdullah 的 answer 通过反射 API 所示,来自未命名命名空间的类不在范围内 进口声明)

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

import Unfinished;

那是no longer allowed。因此,要从打包类中访问默认包类,需要将默认包类移动到它自己的包中。

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


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

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


Andreas 指出in the comments:

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

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

【讨论】:

正如我之前向其他人解释过的,默认包在 Java 世界中是二等公民。只是不要那样做。 :-) 似乎我必须学习 Groovy(在一个非常时间受限的项目中)或默认包中的代码。 :-( @ChrisJester-Young 如果是这样,为什么它首先存在?设计错误? 为什么它被弃用了? @Pacerier “为什么[默认包]首先存在?设计错误?”不,这是故意的。 JLS 7.4.2. Unnamed Packages 说:“Java SE 平台提供未命名的包主要是为了方便在开发小型或临时应用程序或刚刚开始开发时".【参考方案2】:

事实上,你可以。

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

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

String fooReturned = (String)fooMethod.invoke(fooClass.newInstance(), "I did it");

【讨论】:

对于 Scala,以下代码有效:val bar = "hi"; val fooClass = Class.forName("FooClass"); val fooMethod = fooClass.getMethod("foo", classOf[Array[String]]); val fooReturned = fooMethod.invoke(fooClass.newInstance(), Array(bar)); 很好的答案,+1。但是,由于问题很时髦,您可以使用鸭子打字(我猜像 Duct 胶带)...Class.forName("FooBar").newInstance().fooMethod("I did it") 好吧,如果我有两个名为 FooBar 的类来自两个不同的 jar 文件,那么会调用哪一个?【参考方案3】:

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

rule * <target package name>.@1

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

【讨论】:

如何使用 jarjar 的演示会很棒 @BiGGZ:查看 jarjar github repo 上的 README.md 文件,了解如何将 jarjar 与 ant、gradle 或命令行一起使用。【参考方案4】:

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

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

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

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

【讨论】:

【参考方案5】:

只是为了完成这个想法:

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

【讨论】:

以上是关于如何访问默认包中的 java 类?的主要内容,如果未能解决你的问题,请参考以下文章

Java权限修饰符

publicprotected默认private修饰符修饰的区别

publicprotected默认private修饰符修饰的区别

在Java和c#中如果不写访问修饰符,类和类成员默认的是啥访问修饰符?

在Java和c#中如果不写访问修饰符,类和类成员默认的是啥访问修饰符?

如何调用不在默认包中的Bean类