2016-12-22 4 views
2

Я заинтересован в том, чтобы перейти к более функциональным конструкциям в Java и задавался вопросом, есть ли способ в Eclipse, чтобы он предупреждал, если у меня есть изменяемые локальные переменные, параметры, члены класса и т. Д. Таким образом, я мог бы мягко переносить код, поскольку я рефакторинг, и подталкивать в этом направлении, когда я пишу новый код.Предупреждение о изменяемых переменных Java в Eclipse

Я понимаю, что это не все, что есть в FP, но, по крайней мере, это будет начало.

Спасибо.

ответ

0

Получил дикие волосы за Xmas vacation и решил сыграть с парсером, чтобы получить список мест, которые могли бы выиграть от final. Найдено 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)); 
    } 

} 

И да, я получаю чуть меньше 6000 строк вывода из этого, что означает что у меня есть моя работа, вырезанная для меня, я должен выбрать для этого. И это не включает в себя параметры, которые должны быть сделаны final, объекты, которые все еще могут быть изменены и т. Д. Но опять же, это место для начала.

0

По моему опыту, вы можете получить довольно далеко с объявлением final, независимо от вашей IDE.

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

Идея здесь заключается в том, что вы устанавливаете их один раз в конструкторе, скажем, а затем никогда не прикасаетесь к ним снова. (Вы можете предоставить методы настройки, которые более понятны, но передают нежелательное представление о том, что этот объект является изменяемым.) Eclipse, IntelliJ и т. Д. Должны заметить объявление final и, естественно, сказать вам, когда у вас есть код, пытающийся заглушить эти вещи, когда это не должно. (Я забываю, скажут ли они вам, объявили ли вы конечную переменную экземпляра и не предоставили никакого способа ее установить.)

Один из кривых, на которые нужно обратить внимание, будет, конечно, объектами, поля которых могут быть изменены без изменения значения поля в вашем ImmutableThing:

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

Вы можете настроить strs в конструкторе, как указано выше, но содержимое, которое List «s, конечно, может быть изменен, так что нет ничего хорошего. В общем, любой изменяемый объект внутри объекта, который вы хотите быть неизменным, будет иметь эту проблему. Вы можете обойти эту проблему в случае Collections (вероятно, наиболее часто изменяемых объектов) с помощью нередактируемым коллекции:

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

или с использованием версий третьих сторон, например, от гуавы:

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

Другие объекты могут обеспечивать непревзойденные возможности; они не могут. Доступность этой функции, скорее всего, повлияет на то, как далеко вы достигнете этой парадигмы. Вообще говоря, вы можете получить довольно далеко с неизменяемыми объектами данных, и не очень далеко с врожденными состояниями, такими как потоки и пулы соединений.

+0

Спасибо, да, но я хочу знать, где мне еще нужно добавить окончательный, немодифицируемый список и т. Д. –

+0

Хмм. Представленные выше фрагменты были приведены в качестве примеров. Итак, если вы хотите, чтобы что-то было неизменным, вы бы сделали его похожим на «ImmutableThing» выше. Объявление всех его полей как «final». Предполагая, что это не поможет - не могли бы вы дать больше информации о чем-то конкретном, что вы пытаетесь сделать, может быть? –

+0

Ну, мой первоначальный вопрос был в том, можно ли заставить Eclipse дать предупреждение в таких случаях. Дайте указание, где вещи изменяемы. Конечно, я могу проверить свой код вручную, но у меня есть 30-летние годы императивных привычек, которые наверняка заставят меня по пути. Ваши примеры - именно то, что я хочу сделать; Мне просто хотелось бы помочь в определении того, куда он пойдет. –

Смежные вопросы