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相关推荐

  1. ambiguous reference to overloaded definition(scala与java重载逻辑不匹配)

    0.美图 1.问题 Error:(108, 47) ambiguous reference to overloaded definition, both method toJSONString in ...

  2. Scala中解析json工具对比

    写再前面的总结: 1, 做少量文件解析,优先用json4s,因为json4s时基于Scala开发的,对scala使用场景支持更好 2. 做大量数据的解析,追求序列化.反序列化速度时,考虑用fastjs ...

  3. python中json.loads报错: Expecting ‘,‘ delimiter: line 1 column 3545 (char 3544)

    在python中使用json.loads报错: Expecting ',' delimiter: line 1 column 3545 (char 3544) 原因: json字符串为: jsonSt ...

  4. maven中引入oracle驱动报错Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0

    maven中引入oracle驱动报错Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0 问题:引入依赖之后会报错.在maven中央库中查找ojdbc, ...

  5. HQL语句中数据类型转换,及hibernate中createQuery执行hql报错

    一.HQL语句中数据类型转换: 我们需要从数据库中取出序号最大的记录,想到的方法就是使用order by子句进行排序(desc倒序),然后取出第一个对象,可是当初设计数据库时(我们是在原来的数据库的基 ...

  6. JSON文件报错解决方法(Expected value at 1:0/Expected 'a' at 8:20)

    在构建java项目时,可能会出现.json文件报错(出现红叉叉),无论怎么调整,而且项目还能正常运行,但是这个红叉叉就是会一直存在,作为具有强迫症的我是不能忍的,下面步骤为错误描述与决解操作. jso ...

  7. spring boot ajax 415,解决@RequestBody接收json对象报错415的问题

    @RequestBody接收json对象报错415 前端请求: $.ajax({ url: basePath() + "/index/login.do", type : " ...

  8. 关于在VUE中使用sass loader报错的问题

    关于在VUE中使用sass loader报错的问题 一般是关于依赖问题 因为npm的跨境问题导致很多包下载断点,故使用淘宝镜像方可解决问题.能处理百分之七十的问题 关于webpack问题 可能由于we ...

  9. python response.json()报错_Django JsonResponse json格式报错 解决Django响应JsonResponse返回json格式数据报错问题...

    想了解解决Django响应JsonResponse返回json格式数据报错问题的相关内容吗,彭世瑜在本文为您仔细讲解Django JsonResponse json格式报错的相关知识和一些Code实例 ...

最新文章

  1. 我是Redis,MySQL大哥被我害惨了!
  2. 浅谈移动Web开发:深入概念
  3. 华为鸿蒙测试结果,华为鸿蒙OS系统测试结果相继出炉!果然没让花粉们久等:最好的体验...
  4. 致27岁的老光棍天空
  5. 【Nutch2.2.1基础教程之2.2】集成Nutch/Hbase/Solr构建搜索引擎之二:内容分析
  6. 用信号量进程同步与互斥
  7. eclipse mysql jndi_裴东辉-MyEclipse和Eclipse中使用JNDI来配置程序的开发,以及服务器的配置 - 裴东辉...
  8. 《一段代码告诉你,Python的正则表达式怎么用》
  9. python简单的爬虫程序代码_简单的电子邮件爬虫Python代码
  10. Java中堆内存和栈内存的区别
  11. 树莓派SSH脚本自动将攻击IP加入黑名单
  12. Citrix HDX 3D Pro - 注意事项 - 2017H1
  13. 工业控制系统发展历程
  14. vue中使用kindeditor编辑器_vue集成kindeditor富文本
  15. python绘制彩色地震剖面断层解释_地震剖面上断层的识别标志主要有哪些
  16. 逻辑回归原理与sklearn实现
  17. Kaggle ICML2013 fer2013人脸表情识别/面部表情识别:训练、调优、调试与踩坑
  18. Zigbee安全漏洞分析
  19. 人民币转换---java代码实现
  20. Office365完整离线安装包下载及自定义安装教程

热门文章

  1. 计算机用并行传输还是串行,网线RJ45是并行传输还是串行
  2. java jvm容器_java – YARN:容器和JVM
  3. SQLite在指定列后面插入字段_个人学习系列 - 防止MySQL重复插入数据
  4. 1.2 位于Shell脚本第一行的#!
  5. [Linux] 020 RPM 包的命名原则与其依赖性
  6. Linux 安装 redis
  7. 能使用html/css解决的问题就不要使用JS
  8. 赫夫曼编码c++中的实现
  9. 【Vegas原创】分别用Toad、EM解表锁
  10. MFC和QT等UI框架的特点