Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition

简介: 问题描述:[ERROR] /Users/jack/book/lightsword/src/main/scala/com/springboot/in/action/filter/LoginFilter.

问题描述:

[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

相关文章
|
8月前
|
资源调度 JavaScript Windows
yarn install命令报错解决办法-warning package-lock.json found.
yarn install命令报错解决办法-warning package-lock.json found.
146 0
|
JSON 边缘计算 数据格式
KubeEdge安装加入边缘节点报错: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal number into
KubeEdge安装加入边缘节点报错: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal number into
245 0
|
24天前
|
JSON DataWorks 关系型数据库
DataWorks操作报错合集之同步Elasticsearch数据报错:Cat response did not contain a JSON Array,是什么导致的
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
17天前
|
JSON 资源调度 Kubernetes
实时计算 Flink版操作报错合集之解析JSON数组时,遇到报错,该怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
2月前
|
JSON 数据格式
解决报错TypeError: Converting circular structure to JSON --> starting at object with constructor
解决报错TypeError: Converting circular structure to JSON --> starting at object with constructor
|
2月前
|
JSON 运维 Kubernetes
云效产品使用报错问题之流水线中配置了AppStack,构建时下载的制品内容为json字符串,如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
2月前
|
SQL DataWorks 关系型数据库
DataWorks操作报错合集之DataWorks在同步mysql时报错Code:[Framework-02],mysql里面有个json类型字段,是什么原因导致的
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
68 0
|
2月前
|
JSON JavaScript 前端开发
【报错】unexpected non-whitespace character after JSON
【报错】unexpected non-whitespace character after JSON
125 0
|
2月前
|
SQL 消息中间件 Java
Flink报错问题之使用debezium-json format报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
|
JSON 数据格式
解决POSTMAN传参报错,JSON parse error: Cannot deserialize instance of `java.util.ArrayList` out of START_OB
解决POSTMAN传参报错,JSON parse error: Cannot deserialize instance of `java.util.ArrayList` out of START_OB
解决POSTMAN传参报错,JSON parse error: Cannot deserialize instance of `java.util.ArrayList` out of START_OB