Я уже писал в блоге об утилите класса Java Collections и специально писал об использовании методов коллекций emptyList (), emptyMap () и emptySet (). В этой статье я рассмотрю иногда тонкие, но существенные различия между использованием соответствующих полей класса Collections для доступа к пустой коллекции и использованием соответствующих методов класса Collections для доступа к пустой коллекции.
Следующий код демонстрирует прямой доступ к полям Collections для указания пустых коллекций.
Использование полей коллекций для пустых коллекций
|
01
02
03
04
05
06
07
08
09
10
11
|
/** * Instantiate my collections with empty versions using Collections fields. * This will result in javac compiler warnings stating 'warning: [unchecked] * unchecked conversion'. */public void instantiateWithEmptyCollectionsFieldsAssigment(){ this.stringsList = Collections.EMPTY_LIST; this.stringsSet = Collections.EMPTY_SET; this.stringsMap = Collections.EMPTY_MAP; } |
Приведенный выше код компилируется с помощью javac , но приводит к появлению предупреждающего сообщения (генерируемого в этом случае NetBeans и Ant)
|
1
2
3
4
|
-do-compile: [javac] Compiling 1 source file to C:\java\examples\typesafeEmptyCollections\build\classes [javac] Note: C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java uses unchecked or unsafe operations. [javac] Note: Recompile with -Xlint:unchecked for details. |
Указание -Xlint: не отмечено в качестве аргумента javac (в данном случае через javac.compilerargs=-Xlint:unchecked в файле project.properties NetBeans) помогает получить более конкретные предупреждающие сообщения для ранее перечисленного кода:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
[javac] Compiling 1 source file to C:\java\examples\typesafeEmptyCollections\build\classes[javac] C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java:27: warning: [unchecked] unchecked conversion[javac] this.stringsList = Collections.EMPTY_LIST;[javac] ^[javac] required: List<String>[javac] found: List[javac] C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java:28: warning: [unchecked] unchecked conversion[javac] this.stringsSet = Collections.EMPTY_SET;[javac] ^[javac] required: Set<String>[javac] found: Set[javac] C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java:29: warning: [unchecked] unchecked conversion[javac] this.stringsMap = Collections.EMPTY_MAP; [javac] ^[javac] required: Map<String,String>[javac] found: Map |
NetBeans также отобразит эти предупреждения, если в его параметрах установлен соответствующий флажок. Следующие три изображения демонстрируют, что установлена соответствующая подсказка для просмотра этих предупреждений в NetBeans, и предоставляют пример того, как NetBeans представляет приведенный выше код с предупреждениями.
К счастью, легко воспользоваться утилитой класса Collections и получить доступ к пустым коллекциям безопасным способом, который не приведет к этим предупреждениям javac и соответствующим подсказкам NetBeans. Этот подход заключается в использовании методов Collections , а не ее полей . Это продемонстрировано в следующем простом листинге кода.
Использование методов коллекций для пустых коллекций
|
01
02
03
04
05
06
07
08
09
10
|
/** * Instantiate my collections with empty versions using Collections methods. * This will avoid the javac compiler warnings alluding to 'unchecked conversion'. */public void instantiateWithEmptyCollectionsMethodsTypeInferred(){ this.stringsList = Collections.emptyList(); this.stringsSet = Collections.emptySet(); this.stringsMap = Collections.emptyMap();} |
Приведенный выше код скомпилируется без предупреждения, и подсказки NetBeans также не будут отображаться Документация Javadoc для каждого поля класса Collections не описывает причину появления этих предупреждений для полей, но документация для каждого из методов с одинаковыми именами обсуждает это. В частности, документация для каждого состояния Collections.emptyList () , Collections.emptySet () и Collections.emptyMap () : «(В отличие от этого метода поле не обеспечивает безопасность типов.)»
Использование методов Collections для пустых коллекций, показанных в последнем листинге кода, обеспечивало безопасность типов без необходимости явно указывать типы, хранящиеся в этой коллекции, потому что тип был выведен путем использования методов Collections в назначениях для известных и уже объявленных атрибутов экземпляра с явно указанные типы элементов. Если тип не может быть выведен, ошибки компилятора будут возникать при использовании методов Collections без явно определенного типа. Это показано на следующем снимке экрана с попыткой сделать это в NetBeans.
Конкретное сообщение об ошибке компилятора:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
[javac] C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java:62: error: method populateList in class Main cannot be applied to given types;[javac] populateList(Collections.emptyList());[javac] ^[javac] required: List<String>[javac] found: List<Object>[javac] reason: actual argument List<Object> cannot be converted to List<String> by method invocation conversion[javac] C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java:63: error: method populateSet in class Main cannot be applied to given types;[javac] populateSet(Collections.emptySet());[javac] ^[javac] required: Set<String>[javac] found: Set<Object>[javac] reason: actual argument Set<Object> cannot be converted to Set<String> by method invocation conversion[javac] C:\java\examples\typesafeEmptyCollections\src\dustin\examples\Main.java:64: error: method populateMap in class Main cannot be applied to given types;[javac] populateMap(Collections.emptyMap());[javac] ^[javac] required: Map<String,String>[javac] found: Map<Object,Object>[javac] reason: actual argument Map<Object,Object> cannot be converted to Map<String,String> by method invocation conversion[javac] 3 errors |
Эти ошибки компилятора исключаются, а безопасность типов достигается путем явного указания типов элементов коллекций в коде. Это показано в следующем листинге кода.
Явное указание типов элементов с помощью пустых методов коллекций
|
01
02
03
04
05
06
07
08
09
10
11
|
/** * Pass empty collections to another method for processing and specify those * empty methods using Collections methods. This will result in javac compiler * ERRORS unless the type is explicitly specified. */public void instantiateWithEmptyCollectionsMethodsTypeSpecified(){ populateList(Collections.<String>emptyList()); populateSet(Collections.<String>emptySet()); populateMap(Collections.<String, String>emptyMap());} |
Методы класса Collections для получения пустых коллекций предпочтительнее использования полей с одинаковыми именами Collections для той же цели из-за безопасности типов, которую обеспечивают методы. Это позволяет лучше использовать статическую систему типов Java, ключевую тему таких книг, как Effective Java . Приятным побочным эффектом является удаление беспорядочных предупреждений и помеченных подсказок NetBeans, но чем важнее результат, тем лучше и безопаснее код.
Ссылка: Безопасные для типов Пустые Коллекции в Java от нашего партнера JCG Дастина Маркса в блоге Inspired by Actual Events .




