2013-04-30 2 views
4

Мне нужно это сделать, проверьте импорт java.sql.PreparedStatement, у меня есть дерево синтаксического анализа, которое содержит инструкции импорта в этом списке, и я хочу проверить его, работает код alredy, но похоже, что это не самое лучшее, что может быть, есть ли лучший способ проверить этот список?Есть ли лучший способ поиска произвольных значений в этом списке?

List<DetailAST> packageDefinition = findAllAstsOfType(aAST, TokenTypes.IDENT); 
     for (int j = 0; j < packageDefinition.size() - 2; j++) { 
      if (packageDefinition.get(j).getText().equals("java")) { 
       if (packageDefinition.get(j + 1).getText().equals("sql")) { 
        if (packageDefinition.get(j + 2).getText().equals("PreparedStatement")) { 
         importsPreparedStatement = true; 
        } 
       } 
      } 
     } 
+4

Одна вещь, которую вы могли бы сделать, это добавить инструкцию 'break;' после вашего 'importPreparedStatement = true;'. – maba

+0

Как сказал maba, вы можете поставить инструкцию 'break;' после 'importPreparedStatement = true;'. Кроме того, я предполагаю, что у вас потенциально есть много импорта java.sql.', поэтому может быть незначительное улучшение, чтобы сначала проверить часть ** (j + 2) ** части определения. Это может уменьшить количество сравнений, которые вы можете сделать. – temelm

ответ

2

Помимо совмещая 3 сослагательного наклонения к одному:

if(statement1 && statement2 && statement3) 

есть некоторые другие идеи, которые пришли на ум:

Если importsPreparedStatement только должен быть правдой один раз, то вы можете break; после установки на true. Поэтому, если нет смысла искать больше после того, как вы установите поле true, используйте break;.

С точки зрения дизайна вы можете объединить свои if s в виде doesImportPreparedStatement или isImportingPreparedStatement, или, может быть, containsImportPreparedStatement.

Я вижу еще одну вещь. Вы повторяете свой packageDefinition, но вы проверяете 3 элемента друг за другом. Я предполагаю, что они сгруппированы в группы по 3, так что вы можете сделать что-то вроде этого:

for (int j = 0; j < packageDefinition.size() - 2; j += 3) 

С точки зрения дизайна, если бы я тебя, я бы поставил эти 3 элементы в их собственном классе и в этом случае можно упростить вещи, и это будет выглядеть так:

for(DefinitionElement e : packageDefinitions) { 
    if(e.doesImportPreparedStatement()) { 
     importsPreparedStatement = true; 
     break; 
    } 
} 

в последнем случае тип DefinitionElement будет содержать 3 элементы, группы вместе в массиве и метод, который может сказать, содержит ли оно готовило импорт заявление или нет. Я думаю, что эта форма более читабельна и удобна в обслуживании. Из моего опыта вычисление с помощью индексов не является забавным, и вы должны понимать контекст, чтобы знать, что означает j + 2.

Если вы не хотите (или не можете) переместить их в свой класс, вы можете хотя бы дать имя индексу j + 2 и j + 1, чтобы потом узнать, что они означают.

+0

спасибо, я рефакторинг кода прямо сейчас :) –

+0

Я думаю, что перемещение вашей группы элементов в собственный класс является * предпочтительным * способом. –

2

Я не очень понимаю ваш DetailAST класса и как вы вставили differenct объектов в список, но по крайней мере вы можете использовать && вместо вложенных if заявлений.

List<DetailAST> packageDefinition = findAllAstsOfType(aAST, TokenTypes.IDENT); 
for (int j = 0; j < packageDefinition.size() - 2; j++) { 
    if (packageDefinition.get(j).getText().equals("java") && 
     packageDefinition.get(j + 1).getText().equals("sql") && 
     packageDefinition.get(j + 2).getText().equals("PreparedStatement")) { 
     importsPreparedStatement = true; 
     break; 
    } 
} 
+0

DetailAst - это узел дерева синтаксического анализа для кода, он содержит токен с типом и его братьями и сестрами, в этом случае я ищу операторы импорта и проверяя узлы IDENT, которые образуют имя пакета, быть импортированным, это класс checkstyle, и я не полностью осознаю его возможности, у меня просто есть код ссылки из кодовой базы. –

-1

Вы можете попробовать это решение, которое находит массив внутри большего массива:

public static int findArray(Integer[] array, Integer[] subArray) 
{ 
    if (Collections.indexOfSubList(Arrays.asList(array), Arrays.asList(subArray)) != null) 
    { 
     importsPreparedStatement = true; 
    { 
} 

Просто сделайте subArray[] = {"java,"sql",PreparedStatement"};

1

Использование && оператора, чтобы сделать его как одно условие. Как:

if ((packageDefinition.get(j).getText().equals("java")) && 
    (packageDefinition.get(j + 1).getText().equals("sql")) && 
    (packageDefinition.get(j + 2).getText().equals("PreparedStatement"))) 
{ 
    importsPreparedStatement = true; 
} 

Поскольку оператор в Java && делает short-circuit.

Например, если (packageDefinition.get(j).getText().equals("java")) оценен как false. Остальные два не будут оцениваться просто потому, что это было бы необязательно.

+0

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