我必须分配什么编译时类型才能获得java.util.Map的返回值<TextAttribute,?>

我想从另一个字体派生出一个字体。 这是我想要做的:

val font : Font = this.label.getFont(); val attributes : Map<TextAttribute, Any> = font.getAttributes(); attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); this.label.setFont(font.deriveFont(attributes)); 

但是,Kotlin编译器在这一行上抱怨:

 val attributes : Map<TextAttribute, Any> = font.getAttributes(); 

随着消息:

  Type mismatch: inferred type is (Mutable)Map<TextAttribute!, *>! but Map<TextAttribute, Any> was expected 

根据我对Java泛型的有限理解,我明白font.getAttributes()返回一个java.util.Map<TextAttribute, ?> ; 后一种类型的参数意味着当你从这个映射中创建一个有界/关闭的泛型类型时,请指定作为第二个类型参数的任何扩展java.lang.Object的东西

所以,当我首先尝试了以下几行:

 val attributes : java.util.Map<TextAttribute, Object> = font.getAttributes(); 

Kotlin编译器说:

这个类不应该在Kotlin中使用。 改为使用kotlin.collections.Map或kotlin.collections.MutableMap。

还说:

  Type mismatch: inferred type is (MutableMap<TextAttribute!, *>..kotlin.collections.Map<TextAttribute!, *>?) but java.util.Map<TextAttribute, Object> was expected 

我不知道是什么! 符号表示和通配符星号符号的意思。 这是什么意思?

第一个问题是getAttributes方法返回一个可以包含null的映射,而Map<TextAttribute, Any>声明它的值不能为null。 第二个问题是Kotlin中的Map接口不允许突变。

要解决这些问题,请将您的代码更改为例如:

 val attributes : Map<TextAttribute, *> = font.getAttributes(); val updatedAttributes = attributes.plus(TextAttribute.UNDERLINE to TextAttribute.UNDERLINE_ON) 

甚至更简洁:

 val updatedAttributes = font.attributes.plus(TextAttribute.UNDERLINE to TextAttribute.UNDERLINE_ON) 

最后,由于Kotlin具有方便的扩展方法,整个字体可以变成:

 label.font = label.font.run { deriveFont(attributes.plus(TextAttribute.UNDERLINE to TextAttribute.UNDERLINE_ON)) } 

我在Kotlin文档中查找了Star Projections ,从快速阅读中可以看出,这是Kotlin向泛型引入差异的方式,所以outout中的星号*意味着out Any? ,所以我改变了我的代码,它工作:

 val attributesMap : Map<TextAttribute, Any?> = font.getAttributes(); val attributes : MutableMap<TextAttribute, Any?> = attributesMap as MutableMap<TextAttribute, Any?>; 

还有,我使用的编译时类型是一个只读接口kotlin.collections.Map<K, V> ,因为我正在把项目放入它。 但那是我注意到的,并且一旦我摆脱了前一行中的铸造错误,就要照顾好了。