在 Java 中使用 import 语句自动删除显式包声明

Posted

技术标签:

【中文标题】在 Java 中使用 import 语句自动删除显式包声明【英文标题】:Automatically remove explicit package declarations with import statements in Java 【发布时间】:2011-01-09 16:42:27 【问题描述】:

我有一个由其他人创建的项目,其中包含数以千计的类文件,并且为每个对他们的任何类的引用都明确输入了包名称。看起来代码是反向工程的。有没有一个很好的 Java 工具可以重构代码,以便从类引用中删除显式类型的包前缀并移到导入语句中。

提前谢谢你。

编辑:

我认为一个例子会有所帮助。我想把导入放在顶部,我不在乎有多少导入。

javax.swing.JButton button1 = new javax.swing.JButton();

想象一下上面的代码,但绝对是在成千上万的类文件中成千上万行代码中无处不在。我希望能够删除所有前缀,并且只需要一个不错的 import javax.swing.JButton;在每个类文件的顶部。

【问题讨论】:

这是错误的。我们不应该窃取他人的作品,也不应该帮助任何人这样做。 @irreputable :这不是偷窃。这可能是用户有权使用库的情况,但原始制造商或负责人已经消失,源代码和可能的错误修正也随之消失。在这些情况下,您所能做的就是扭转局面并尝试自己纠正错误 没有人窃取任何人的作品。我正在与我的大学开展一项研究项目,该项目明确允许使用和修改另一所大学的源代码。 【参考方案1】:

我不知道这个用例的工具,但几个月前我不得不做类似的事情。

编写脚本或使用正则表达式进行搜索替换,以消除显式键入的包前缀。

比起让 eclipse 使用“组织导入”来完成其余的工作。 Ctrl-1

提示:为避免歧义,请使用不超过所需库的类路径设置。 对于大约 800 节课,我在 2 小时内完成。

或者找一个应得的人来做这项工作。

编辑:你应该知道在 Prefeneces/Java/Editor/Save Actions 中,Organize imports 可以配置为保存操作。

【讨论】:

是的,这是我认为我必须做的。编写正则表达式后只需 2 小时……听起来很有希望,并且可能正在这样做。谢谢。 这可能不像删除所有显式包引用那么简单;如果存在歧义(相同的类名),则需要保留这些显式引用。 使用eclipse的保存动作,至少可以改变顺序(和可见性) 有人有正则表达式的例子吗? 很难为所有这些想出一个单一的正则表达式,但您可以执行以下操作:突出显示除现有导入列表之外的所有内容,然后按 CTRL-F 查找/替换。搜索“(org|com).[a-z.]*”并确保选中“正则表达式”和“区分大小写”选项。然后替换为“”(无)。然后“组织进口”并猜测每个进口应该是什么。 :)【参考方案2】:

对于单一类型,eclipse 提供“添加导入”操作 (Shift+Ctrl+M)。它完全符合您的要求 - 有一个很大的限制:您必须将光标放在一个类型上,它只会影响“选定”的出现。

但也许这个动作可以用在脚本/全局方法中。 JDT 插件可以爬取 AST 并在它找到的每种类型上调用此操作。

【讨论】:

我将不得不研究脚本,但是我不知道编写一个使用正则表达式查找和替换的脚本是否更容易。不过,如果我能找到一个已经编写好的插件,我肯定会尝试使用它。谢谢。【参考方案3】:

This thread 说:

选择包资源管理器视图,右键单击您的项目,选择源然后组织导入。 Bobs 你的叔叔 - 所有不需要的导入都被删除

为了更好地格式化:

Right click project > Source > Organize imports

现在,剩下的就是找到一种从代码中去除完全限定名称的方法。你可能会想到一些正则表达式。看看this library - 它似乎很有帮助。 This article 也应该很有用。

【讨论】:

这不会将完全限定的类型声明(例如java.awt.Font foo)更改为带有导入语句的非限定声明(例如Font foo)。至少,在 Eclipse 3.5 中是这样的。 是的,我用下一步(实际上是上一步)更新了我的答案 有趣的库和文章...我将不得不研究这些,看看我可以多么容易地将它应用到我的项目中,谢谢。【参考方案4】:

我使用 Michael Ernst 的 Eclipse plugin 来满足您的需求。它将java.util.Collection 等引用转换为Collection,并在文件顶部添加import java.util.Collection;

它实际上与使用“Source -> Add Import”作为完全限定的引用相同,只是它允许您一次对整个 .java 文件执行此操作。

更好的是,它可以让您批处理您在包资源管理器中选择的所有 .java 文件。只需右键单击选择并从上下文菜单中选择“Source -> Clean qualified Type Declarations”。

Eclipse 更新站点:http://cqtp.sourceforge.net/eclipse/

【讨论】:

【参考方案5】:

IntelliJ Idea 具有针对每个文件执行此操作的工具。你也可以批量做,但我不知道怎么做。

尝试 30 天的评估,您可能会对导入清理功能感到满意。

【讨论】:

【参考方案6】:

我在使用轴生成的文件时遇到了同样的问题,我编写了一个小型的 groovy 脚本来执行此操作。我不是什么都做(你运行之后必须在eclipse中使用组织导入),而且我也没有很好地测试过,所以请谨慎使用。它也仅限于小写包名和驼峰式类名,但它可能是一个很好的起点

def replaceExplicitPackageNamesInFile(File javaFile)
 eol = org.codehaus.groovy.tools.Utilities.eol()

 newFile = ""
 explicitImportExpr = /([^\w])(([a-z0-9]+\.)+)([A-Z][a-zA-Z0-9]+)/
 imports = ""
 javaFile.eachLine  
  line = it.replaceAll(explicitImportExpr, 
   Object [] match ->
   imports += "import $match[2]+match[-1];$eol"
   match[1]+match[-1]
  )
  newFile += line+"$eol" 
 
 newFile2 = ""
 newFile.eachLine  line ->
  newFile2 +=
   line.replaceAll(/(^\s*package.*$)/, 
    Object [] match ->
    match[0] + eol + imports
    ) + eol
 
 javaFile.setText(newFile2)


def replaceExplicitPackageNamesInDir(File dir)
 dir.eachFileRecurse 
  if (it.isFile() && it.name ==~ /.*\.java\z/)
   println "Processing $it.absolutePath - dir.absolutePath"
   replaceExplicitPackageNamesInFile(it)
  
 

【讨论】:

【参考方案7】:

您可能需要替换所有javax.swing.。然后组织导入。

【讨论】:

【参考方案8】:

我已经能够通过在目标文件上运行下面的 sed 命令来删除接口中的所有显式包名称,然后在 eclipse 中重新组织导入:

sed -e 's/java\.[^ ]*\.//g;s/com\.[^ ]*\.//g'

【讨论】:

以上是关于在 Java 中使用 import 语句自动删除显式包声明的主要内容,如果未能解决你的问题,请参考以下文章

如何从回显语句中删除双引号 [关闭]

java中import的作用

在 Java 中的 Import 语句中使用 * [重复]

[Eclipse]保存java文件时,自动删除不需要的包import

Android Studio设置自动导入import以及自动删除没用到的import

IDEA 实用功能Auto Import:自动优化导包(自动删除导入包)