如何在Scala中用点符号读写java.util.Properties元素?
解决DynamicProps嵌套点访问的问题
问题根源
当你尝试sysProps.java.home时,Scala会先执行sysProps.java,如果这一步直接返回了String类型的属性值(或因找不到"java"属性返回空字符串),后续的.home就会因为String没有这个成员而报错。要实现嵌套点访问,每一层的属性访问都需要返回动态代理实例,而非直接返回属性值,直到最终需要取值时才返回结果。
实现思路
- 让DynamicProps类持有当前的属性前缀(比如访问
java时,前缀更新为"java."),而不是直接查找完整属性名。 - 重写
selectDynamic方法:- 若当前访问的是最终属性(如
home),则拼接前缀+属性名,从Properties中取值; - 若为中间层级(如
java),则返回新的DynamicProps实例,持有更新后的前缀。
- 若当前访问的是最终属性(如
- 可增加显式取值方法(如
value),避免歧义;也可通过判断属性是否存在来自动切换返回值或代理实例。
示例代码
方式一:显式调用取值方法(无歧义)
import java.util.Properties import scala.language.dynamics class DynamicProps(props: Properties, prefix: String = "") extends Dynamic { def selectDynamic(name: String): DynamicProps = { new DynamicProps(props, s"$prefix$name.") } // 显式获取最终属性值 def value: String = { val key = prefix.dropRight(1) props.getProperty(key, "") } // 支持动态赋值(如需写操作) def updateDynamic(name: String)(value: String): Unit = { val key = s"$prefix$name" props.setProperty(key, value) } } // 使用示例 val sysProps = new DynamicProps(System.getProperties()) println(sysProps.java.home.value) // 输出java.home的属性值
方式二:自动判断属性是否存在(有歧义风险)
如果不想显式调用value,可以尝试先查找完整属性名,存在则返回值,否则返回嵌套代理。但如果存在属性java和java.home,会优先返回java的属性值,需根据场景权衡:
import java.util.Properties import scala.language.dynamics class DynamicProps(props: Properties, prefix: String = "") extends Dynamic { def selectDynamic(name: String): Any = { val fullKey = s"$prefix$name" props.getProperty(fullKey) match { case null => new DynamicProps(props, s"$fullKey.") case value => value } } } // 使用示例 val sysProps = new DynamicProps(System.getProperties()) println(sysProps.java.home) // 直接输出属性值
内容的提问来源于stack exchange,提问作者Christopher Spears
相关产品推荐
相关产品推荐

