В своей самой первой статье о 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 Бернарда Линьи .
Статьи по Теме :