Java 为现有代码中的常量创建静态导入的简单方法?

Java 为现有代码中的常量创建静态导入的简单方法?,java,eclipse,Java,Eclipse,如果我在Foo中有一个常量条,我将在C类中使用它,我将不得不编写 Object o = Foo.BAR + "..."; 我可以在Eclipse中使用Ctrl-Shift-M(光标位于条形图上)为以下对象创建静态导入: import static Foo.BAR; Object o = BAR + "...."; 我目前正在用数千个我想转换为静态导入的文字更新遗留代码。Ctrl-Shift-O/Organize导入不起作用。我错过了什么把戏吗 EDIT:实际上,我更喜欢一种告诉Eclip

如果我在Foo中有一个常量条,我将在C类中使用它,我将不得不编写

Object o = Foo.BAR + "...";
我可以在Eclipse中使用Ctrl-Shift-M(光标位于条形图上)为以下对象创建静态导入:

import static Foo.BAR;

Object o = BAR + "....";
我目前正在用数千个我想转换为静态导入的文字更新遗留代码。Ctrl-Shift-O/Organize导入不起作用。我错过了什么把戏吗


EDIT:实际上,我更喜欢一种告诉Eclipse我想让Ctrl-Shift-M在这个特定类中的所有实例上发挥它的魔力,而不仅仅是在我放置光标的单个实例上。(这是遗留代码,因此实际上提高了可读性:))



编辑:我发现IntelliJ建议这样做。

一个警告:过度使用静态导入实际上会降低代码的可读性(imho),特别是当常量名称没有明确指示它所属的类或枚举时。您还可以从听起来相似甚至具有相同名称的不同类/枚举中获取常量名称

因此,你强迫读者做的是希望他的IDE能告诉他这个类(比如说,通过一个工具提示),或者他们必须导航到它来找到它是什么。打印输出和代码片段变得越来越不可修改


老实说,出于这些原因,我很少使用静态导入。

正则表达式就是为了解决这些问题而发明的!=)

您需要编写一个小脚本(或使用IDE正则表达式搜索/替换)。唯一的问题是,如果有很多类需要静态导入,那么它的工作量也一样大。否则,如果它只是一个类,比如FOO.BLAH,那么您可以使用一个正则表达式,比如

(\bFOO\(\w+)\b)
->替换为第2组($2或\2或您的正则表达式搜索程序捕获替换的方式)

您可以在此处尝试:。选择“替换”选项卡并键入$2

但是,如果您有这样的表达式,则可能会出现问题:
FOO f=FOO.blah+“FOO.blah”
,所以要小心


至于文件顶部的import语句,eclipse有一个自动导入特性,它在格式上自动导入,只要导入的名称足够唯一,它就可以工作。或者,如果由于名称太常见而无法使用它,则可以使用perl脚本来执行正则表达式,并在静态导入之前添加前缀

我不知道还有什么其他的自动重构可以满足您的需求,但是有两个关键方面可以做到这一点——一个是添加导入,另一个是从常量中删除类名

对于添加导入,我建议粘贴
import static application.KeyHolder.*在使用它们的每个文件上的包之后


要删除类名,请在eclipse中用Java搜索
KeyHolder.*
并搜索字段。然后可以查找/替换“KeyHolder.”,并替换为“”。为了防止不匹配,请确保替换的项目计数等于该文件的匹配数。另外,请确保在导入后向下搜索并开始。

如果我面临这样的挑战,我可能会编写一个小程序来帮我完成。Ruby和Python(JRuby和Jython?)非常适合这个任务,尽管您也可以用Java来完成


好吧,这可能会花费你至少和手工一样多的时间,但至少你会玩得很开心:)。

好吧,这是一个突然出现的解决方案。我建议使用一个简单的groovy脚本。基本上,语义与解析导入语句及其引用的文件有关。一些基本步骤可能是

  • 递归目录中的每个文件。检查文件扩展名是否为.java
  • 匹配以import开头的任何行
  • 对于每一行,打开相关的源文件(您已经知道import语句的路径)
  • 使用反射匹配静态修饰符的字段/方法声明
  • 在步骤5中找到的匹配项的import语句之后添加static
    如果我有时间,我会尝试发布一个小的groovy脚本来做同样的事情。

    Eclipse可以对项目中的所有文件进行全局搜索并替换为正则表达式

    要在所有文件的开头添加静态导入,可以将包声明本身与静态导入一起替换

    然后在整个项目范围内组织导入,就一切就绪了


    不过要小心,如果你做得不对,这也可能会造成很大的混乱。

    我不知道它是否适合你的需要,但是你可以在一个接口中定义这些常量,让你所有的类都实现这个接口。然后像其他人建议的那样使用一些智能RegExp,您可以消除所有
    Foo.
    事件

    例如:

    public interface Foo {
       static final String constant1 = "Some";
       static final String constant2 = "Value";
       //...
    }
    
    然后

    public class YourClass implements Foo {
       public YourClass() {
          System.out.println("Hello " + constant1);
       }
    }
    

    听起来是个不错的主意,但在您更改了所有文件后,它们会有多好?也许您应该考虑只更改您正在处理的文件,因为其他原因。

    确保与其他常量类没有冲突

    将所有“Foo.”替换为空(“”)

    使用顶部的这条线。为我工作


    导入静态Foo.*

    我知道这些事情。在这个特殊的例子中,我有一个到处都使用键常量的keyholder类,因此您关心的不是问题,而是相反的问题:当问题是“如何使用静态导入实现这一点”时,我不认为“不要使用静态导入”这是一个值得投票表决的答案。在回答问题时,保护人们不受善意但被误导的目的是一种由来已久的技巧。我不同意——我认为静态导入所有常量可以使代码更具可读性。牺牲真正的代码简洁性和可读性来改进打印输出和代码片段是荒谬的。大多数情况下,常量的名称就足够了-