简体   繁体   English

关于Eclipse中可变Java变量的警告

[英]Warning on mutable Java variables in Eclipse

I'm interested in moving toward more functional constructs in Java, and was wondering if there was a way in Eclipse to have it warn if I have mutable local variables, parameters, class members, etc. That way, I could gently migrate code as I'm refactoring, and be nudged in that direction as I write new code as well. 我对转向Java中的更多功能构造感兴趣,并且想知道Eclipse中是否有一种方法可以警告我是否存在可变的局部变量,参数,类成员等。这样,我可以像我正在重构,并且在编写新代码时也会朝着这个方向前进。

I realize that's not all there is to FP, but would at least be a start. 我意识到FP并不仅是全部,但至少是一个开始。

Thanks. 谢谢。

In my experience, you can get fairly far with the final declaration, regardless of your IDE. 以我的经验,无论您使用哪种IDE, final声明都可以走得很远。

public class ImmutableThing {
  private final int someInt;
  private final String aString;
}

The idea here is that you set these once in the constructor, say, and then never touch them again. 这里的想法是,您在构造函数中设置了一次,例如,然后再也不会碰它们。 (You could provide setter methods, which are more clear, but convey the unwanted notion that this object is mutable.) Eclipse, IntelliJ, etc. should notice the final declaration and naturally tell you when you have code trying to muck with these things when it shouldn't. (您可以提供更清晰的setter方法,但传达了该对象易变的不需要的概念。)Eclipse,IntelliJ等应注意final声明,并自然告诉您何时有代码试图将这些东西弄乱了不应该。 (I forget whether they will tell you if you've declared a final instance variable and provided no way to set it.) (我忘记了他们是否会告诉您是否声明了最终实例变量并且没有提供设置它的方法。)

One curveball to watch out for will of course be objects whose fields can be changed without changing the value of the field in your ImmutableThing : 当然,需要注意的一个曲线球是可以更改其字段而无需更改ImmutableThing字段的值的对象:

    private final List<String> strs; // Hmm.

You can set up the strs in the constructor as above, but that List 's contents can of course be changed, so that's no good. 您可以按上述方式在构造函数中设置strs ,但是List的内容当然可以更改,所以这不好。 In general, any mutable object inside an object you want to be immutable will have this problem. 通常,您想要不可变的对象内部的任何可变对象都会出现此问题。 You can get around this in the case of Collections (probably the most common mutable objects) by using unmodifiable collections: 对于Collections (可能是最常见的可变对象),可以通过使用不可修改的 collection来解决:

    strs = Collections.unmodifiableList<String>(initList);

or by using third-party versions, such as from Guava: 或使用第三方版本(例如来自Guava的版本):

    strs = ImmutableList<String>.of ("x", "y", "z");

Other objects might provide immutability features; 其他对象可能提供不变性功能。 they might not. 他们可能不会。 This feature availability will likely shape how far you get with this paradigm. 此功能的可用性可能会影响您使用此范例所能达到的程度。 Generally speaking, you can get pretty far with immutable data objects, and not very far with innately stateful things like streams and connection pools. 一般而言,使用不可变的数据对象可以使您受益匪浅,而对于诸如流和连接池之类的固有状态的事物,您可以做到的远不止于此。

Got a wild hair over Xmas vacation, and decided to play with a parser, to be able to get a list of places that could benefit from final . 在圣诞节假期满头白发,并决定使用解析器,以获取可以从final受益的位置的列表。 Found javaparser.org, and got the following code running as a simple start, that I hope to build on, going forward: 找到javaparser.org,并以下面的代码作为一个简单的开始运行,我希望以此为基础:

import java.io.File;
import java.io.FileNotFoundException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.body.FieldDeclaration;

public class JavaFPMain {

    public static void main(String[] args) throws Exception {
        JavaFPMain fpApp = new JavaFPMain();
        fpApp.run();
    }

    private void run() throws Exception {
        File projectDir = new File(...);
        FileUtils.listFiles(projectDir, new RegexFileFilter(".*.java"), DirectoryFileFilter.DIRECTORY)
            .stream()
            .forEach(this::parseFile);

        System.out.println("done");
    }

    private void parseFile(final File fi) {
        try {
            CompilationUnit compilationUnit = JavaParser.parse(fi);

            String AUTOWIRED = "Autowired";
            compilationUnit.getNodesByType(FieldDeclaration.class).stream()
                .filter(f -> !f.getModifiers().contains(Modifier.FINAL) &&
                             !containsAnnotation(f, AUTOWIRED))
                .forEach(f -> System.out.println("missing final: " + fi.getAbsolutePath() + "(" + f.getBegin().get().line + ") " + f.getVariable(0).getNameAsString()));
        } catch (FileNotFoundException ex) {
            throw new RuntimeException(ex);
        }
    }

    private boolean containsAnnotation(FieldDeclaration f, String name) {
        return f.getAnnotations()
                .stream()
                .anyMatch(a -> a.getNameAsString().equals(name));
    }

}

And yes, I get just short of 6,000 lines of output from this, which means that I have my work cut out for me, should I choose to pursue this. 是的,我从中只能得到6,000行的输出,这意味着如果我选择追求这一目标,我的工作就会被削减。 And that's not including parameters that should be made final , objects that are still modifiable, etc. But again, it's a place to start. 而且这还不包括应设为final参数,仍可修改的对象等。但这又是一个起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM