我之前曾在Java Collections类的实用程序上进行过博客撰写,并且特别地在使用Usings Collections Methods上的博客emptyList(),emptyMap()和emptySet()上进行了博客撰写。 在本文中,我研究了使用Collections
类的相关字段访问空集合与使用Collections
类的相关方法访问空集合之间有时细微但重要的区别。
以下代码演示了直接访问Collections
的字段以指定空集合。
将集合的字段用于空集合
/*** 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生成):
-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:unchecked指定为 javac
的参数(在这种情况下,通过NetBeans project.properties
文件中的javac.compilerargs=-Xlint:unchecked
)有助于获取更具体的警告消息,用于前面列出的代码:
[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
的方法而不是其字段 。 下一个简单的代码清单对此进行了演示。
对空集合使用集合的方法
/*** 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提示。 Collections
类的每个字段的Javadoc文档都没有解决为什么这些字段会出现这些警告的问题,但是每个类似方法的文档都对此进行了讨论。 具体来说,有关Collections.emptyList() , Collections.emptySet()和Collections.emptyMap()的文档每个状态为“((不同于此方法,该字段不提供类型安全性。)”
对最后一个代码清单中显示的空集合使用Collections
方法可提供类型安全性,而无需显式指定存储在该集合中的类型,因为类型是通过在显式分配给已知和已经声明的实例属性时使用Collections
方法来推断的指定的元素类型。 如果无法推断类型,则使用没有显式指定类型的Collections
方法时将导致编译器错误 。 下一个尝试在NetBeans中执行此操作的屏幕快照中显示了这一点。
具体的编译器错误消息是:
[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
通过在代码中显式指定集合元素的类型,可以避免这些编译器错误并实现类型安全。 这显示在下一个代码清单中。
使用Collections的Empty方法显式指定元素类型
/*** 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提示,但是更重要的结果是更好,更安全的代码。
参考: JCG合作伙伴 Dustin Marx在Inspired by Actual Events博客中提供的Java类型安全的空集合 。
翻译自: https://www.javacodegeeks.com/2012/11/type-safe-empty-collections-in-java.html