В своей самой первой статье о JCG я хотел показать вам, как вы можете легко улучшить читабельность своего кода, используя возможности языка Java, даже для довольно простых вещей.
Давайте начнем с конкретного примера:
|
1
2
3
4
5
|
String color = "green";...if ( color!=null && color.equals("red") ) { System.out.println("Sorry, red is forbidden !");} |
Один из первых уроков, которые вы, вероятно, извлекли из своего учителя Java (или объектно-ориентированного программирования), — это важность проверки недействительности объекта перед вызовом метода для него. Исключения нулевого указателя (NPE) действительно являются одними из самых распространенных (и раздражающих) ошибок, возникающих в коде объектно-ориентированных языков .
В приведенном выше примере безопасно убедиться, что объект String ‘color’ не равен NULL, прежде чем сравнивать его с константой. Лично я всегда считал это ненужным бременем для программиста — особенно для современных ОО-языков, таких как Java. В качестве обходного пути, существует (действительно глупый) прием для переписывания условия без необходимости проверки на ничтожность. Помните, что метод equals () является симметричным (если a = b, то b = a).
|
1
2
3
|
if ( "red".equals(color) ) { System.out.println("Sorry, red is forbidden !");} |
На первый взгляд, это может показаться немного противоречивым при чтении, но устранение загрязняющего кода, безусловно, не бесполезно.
Давайте продолжим наш пример и представим, что теперь мы хотим сравнить наш цвет с несколькими значениями. Java-новички обычно пишут что-то вроде:
|
1
2
3
4
5
|
if ( "red".equals(color) || "yellow".equals(color) || "blue".equals(color) ) { System.out.println("This is a primary color");} |
Иногда я встречал более опытных Java-программистов, сокращающих такое длинное выражение if :
|
1
2
3
|
if ( "red|yellow|blue".indexOf(color)>=0 ) { System.out.println("This is a primary color");} |
Умный не так ли? Не так много на самом деле. Игра с подстроками может быть опасной игрой. Например, следующий код может не дать ожидаемых результатов, особенно если вы мужчина:
|
1
2
3
4
5
|
String type = "man";...if ( "woman|child".indexOf(type)>=0 ) { System.out.println("Women and children first !");} |
Если вы ищете хороший баланс между элегантностью и удобочитаемостью, вам лучше выбрать одну из следующих альтернатив.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import java.util.HashSet;import java.util.Set;public static final Set<string> PRIMARY_COLORS;static { PRIMARY_COLORS = new HashSet<string>(); PRIMARY_COLORS.add("red"); PRIMARY_COLORS.add("yellow"); PRIMARY_COLORS.add("blue");}...if ( PRIMARY_COLORS.contains(color) ) { System.out.println("This is a primary color");} |
Мало кто знает это (я допускаю, что синтаксис немного странный), но все же есть способ уменьшить многословность кода при инициализации набора основных цветов:
|
1
2
3
4
5
|
public static final Set<string> PRIMARY_COLORS = new HashSet<string>() {{ add("red"); add("yellow"); add("blue"); }}; |
Если сжатие кода становится навязчивой идеей, Java Collections Framework также может прийти на помощь:
|
1
2
3
4
5
6
7
8
|
import java.util.Arrays;import java.util.Collection;public static final Collection<string> PRIMARY_COLORS = Arrays.asList("red", "yellow", "blue");...if ( PRIMARY_COLORS.contains(color) ) { System.out.println("This is a primary color");} |
Ключевое слово final предотвращает повторное присвоение переменной PRIMARY_COLORS другой коллекции значений — это особенно важно, когда ваша переменная определена как public . Если безопасность является серьезной проблемой, вы должны также обернуть оригинальную коллекцию в неизменяемую коллекцию. Это гарантирует доступ только для чтения.
|
1
2
3
4
5
6
|
import java.util.Arrays;import java.util.Collection;import java.util.Collections;public static final Collection PRIMARY_COLORS = Collections.unmodifiableCollection( Arrays.asList("red", "yellow", "blue") ); |
Следует заметить, что, хотя и более читабельный, использование набора значений (особенно в больших коллекциях), как правило, будет медленнее, чем (я бы сказал: не так быстро, как), классических ленивых ИЛИ (т. Е. Использование «||» вместо « | ‘) из-за оценки короткого замыкания . Я склонен думать, что в настоящее время такие соображения становятся бесполезными.
После 16 лет жалоб у Java 7 — наконец-то! — введена поддержка String в операторах switch-case . Это позволяет нам кодировать такие вещи, как:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
boolean primary;switch(color) { case "red": primary=true; break; case "green": primary=true; break; case "blue": primary=true; break; default: primary=false;}if (primary) System.out.println("This is a primary color"); |
Давайте, наконец, закончим тем, что, пожалуй, является наиболее объектно-ориентированным решением нашей (так сказать) проблемы. Перечисления Java в основном являются классами и поэтому могут иметь методы и поля, как и любые другие классы. Применяя шаблон проектирования « Шаблонный метод» , можно определить абстрактный метод (моделирование теста), который должен быть реализован всеми подклассами (моделирование ответа теста, примененного к конкретному элементу перечисления):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
Color c = Color.valueOf("RED");if ( c.isPrimaryColor() ) { System.out.println("This is a primary color");}public enum Color { RED() { @Override public boolean isPrimaryColor() { return true; } }, BLUE() { @Override public boolean isPrimaryColor() { return true; } }, YELLOW() { @Override public boolean isPrimaryColor() { return true; } }; GREEN() { @Override public boolean isPrimaryColor() { return false; } }; public abstract boolean isPrimaryColor();} |
Полученный код понятен и самодокументирован. Использование этого шаблона во многих случаях является отличной альтернативой более распространенной логике «если — еще, если», поскольку ее легче читать, расширять и поддерживать.
В заключение я бы сказал, что, как очень часто — и это сила языка Java — для одной проблемы существует очень много разных решений с точки зрения реализации. Но решить, какой из них лучший, это другая история …
Справка: делай это коротко, но делай правильно! от нашего партнера по W4G Бернарда Линьи .
Статьи по Теме :