13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
来源:互联网 发布:联想有windows系统平板 编辑:程序博客网 时间:2024/06/05 20:45
13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
问题描述:
[ERROR] /Users/jack/book/lightsword/src/main/scala/com/springboot/in/action/filter/LoginFilter.scala:28: error: ambiguous reference to overloaded definition,[INFO] both method toJSONString in object JSON of type (x$1: Any, x$2: com.alibaba.fastjson.serializer.SerializerFeature*)String[INFO] and method toJSONString in object JSON of type (x$1: Any)String[INFO] match argument types (Object) and expected result type Any[INFO] println(JSON.toJSONString(principal))[INFO] ^[ERROR] one error found
原因分析:
看日志:
[INFO] both method toJSONString in object JSON of type (x$1: Any, x$2: com.alibaba.fastjson.serializer.SerializerFeature*)String[INFO] and method toJSONString in object JSON of type (x$1: Any)String[INFO] match argument types (Object) and expected result type Any[INFO] println(JSON.toJSONString(principal))
意思是,JSON.toJSONString的两个方法:
toJSONString(x$1: Any)toJSONString(x$1: Any, x$2: com.alibaba.fastjson.serializer.SerializerFeature*)
同时匹配了方法的引用。
我们看这是这两个方法的java源码:
public static String toJSONString(Object object) { return toJSONString(object, new SerializerFeature[0]); } public static String toJSONString(Object object, SerializerFeature... features) { SerializeWriter out = new SerializeWriter(); try { JSONSerializer serializer = new JSONSerializer(out); for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) { serializer.config(feature, true); } serializer.write(object); return out.toString(); } finally { out.close(); } }
SerializerFeature... features 是一个可变长参数。
Java可变长参数的方法重载
在Java代码中,我们是不推荐带有变长参数的方法重载的。这样的代码调用人类阅读起来会感到“模糊”。
在项目和系统的开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java 5之前常用的设计技巧就是把形参定义成Collection类型或其子类类型,或者是数组类型,这种方法的缺点就是需要对空参数进行判断和筛选,比如实参为null值和长度为0的Collection或数组。
而 Java 5引入变长参数(varags)就是为了更好地提高方法的复用性,让方法的调用者可以“随心所欲”地传递实参数量,当然变长参数也是要遵循一定规则的,
比如变长参数必须是方法中的最后一个参数;一个方法不能定义多个变长参数等,这些基本规则需要牢记,但是即使记住了这些规则,仍然有可能出现错误,我们来看如下代码:
public class Client { //简单折扣计算 public void calPrice(int price,int discount){ float knockdownPrice =price * discount / 100.0F; System.out.println("简单折扣后的价格是:"+formateCurrency(knockdownPrice)); } //复杂多折扣计算 public void calPrice(int price,int... discounts){ float knockdownPrice = price; for(int discount:discounts){ knockdownPriceknockdownPrice = knockdownPrice * discount / 100; } System.out.println("复杂折扣后的价格是:" +formateCurrency(knockdownPrice)); } //格式化成本的货币形式 private String formateCurrency(float price){ return NumberFormat.getCurrencyInstance().format(price/100); } public static void main(String[] args) { Client client = new Client(); //499元的货物,打75折 client.calPrice(49900, 75); } }
运行结果:
简单折扣后的价格是:¥374.25
这是一个计算商品价格折扣的模拟类,带有变长参数的calPrice方法则是较复杂的折扣计算方式,多种折扣的叠加运算(模拟类是一种比较简单的实现)在实际生活中也是经常见到的,比如在大甩卖期间对VIP会员再度进行打折;或者当天是你的生日,再给你打个9折,也就是俗话说的“折上折”。
两个calPrice()方法重载有点特殊:
calPrice(int price,int... discounts)// A
的参数范畴覆盖了
calPrice(int price,int discount)// B
的参数范畴。
那问题就出来了:对于
calPrice(49900,75)
这样的计算,到底该调用哪个方法来处理呢?
从运行结果来看是调用了B方法,而不是变长参数A的方法.
原因分析:Java在编译时,首先会根据实参的数量和类型(这里是2个实参,都为int类型,注意没有转成int数组)来进行处理,也就是查找到calPrice(int price,int discount)方法,而且确认它是否符合方法签名条件。现在的问题是编译器为什么会首先根据2个int类型的实参而不是1个int类型、1个int数组类型的实参来查找方法呢?这是个好问题,也非常好回答:因为int是一个原生数据类型,而数组本身是一个对象,编译器想要“偷懒”,于是它会从最简单的开始“猜想”,只要符合编译条件的即可通过,于是就出现了此问题。
问题是阐述清楚了,为了让我们的程序能被“人类”看懂,还是慎重考虑变长参数的方法重载吧,否则让人伤脑筋不说,说不定哪天就陷入这类小陷阱里了。
Scala编译器的处理方式就比较“显式”了,直接抛出“ambiguous reference to overloaded definition” ERROR。
针对可变参数的方法重载机制,这是Scala的与java在编译处理上区别的地方。
Scala分辨重载方法的过程与Java极为相似。任何情况下,被选中的重载版本都是最符合参数静态类型的那个。有时如果不止一个最符合的版本;这种情况下编译器会给你一个“ambiguous reference to overloaded definition”(模糊引用了重载定义的方法)的错误。
解决方案:
在scala代码中显式调用:toJSONString(Object object, SerializerFeature... features) 。
另外,不推荐带有变长参数的方法重载。
参考资料:
1.http://www.cnblogs.com/DreamDrive/p/5412359.html
- 13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
- Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
- ambiguous call to overloaded function
- 'sqtr'ambiguous call to overloaded function
- error C2668: 'sqrt' : ambiguous call to overloaded
- Xcode报错Reference to '某个属性或对象' is ambiguous
- reference to "transform" is ambiguous
- json error: Use of overloaded operator [] is ambiguous
- error C2668: 'abs' : ambiguous call to overloaded function
- ambiguous call to overloaded function解决的办法
- C2668: 'sqrt' : ambiguous call to overloaded function(sqrt问题)
- 【关于DrawLine' : ambiguous call to overloaded function解决办法】
- error C2668: ‘pow’ : ambiguous call to overloaded function
- error C2668: ‘sqrt’ : ambiguous call to overloaded function
- JSON toJSONString
- JSON toJSONString
- undefined definition reference to XXX
- JSON中toJSONString、parseObject、parseArray的作用
- 13.6 SpringBoot集成Mongodb开发问题@EnableMongoRepositories路径配置
- 微信分布式数据存储协议对比——Paxos和Quorum
- 13.7 SpringBoot集成日志系统logback的几个问题
- 13.8 java.lang.IllegalArgumentException: Request header is too large
- the suspect
- 13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
- Python eval 函数妙用(转)
- 13.9 SpringBoot集成Swagger2中遇到的问题
- 13.4 库依赖冲突问题:Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path
- 润乾报表v5如何升级设计器的JDK版本
- 13.11 Scala混用Java的集合类调用scala的foreach遍历问题
- OSG的几个矩阵
- 9月12日云栖精选夜读:人工智能在细分及新兴领域的应用
- 13.12 Spring Boot集成Security中遇到的问题