Я уже писал в блоге об утилите класса 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 .