javascript
13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition
13.10 Scala中使用JSON.toJSONString報(bào)錯(cuò):ambiguous reference to overloaded definition
問(wèn)題描述:
[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的兩個(gè)方法:
toJSONString(x$1: Any)toJSONString(x$1: Any, x$2: com.alibaba.fastjson.serializer.SerializerFeature*)同時(shí)匹配了方法的引用。
我們看這是這兩個(gè)方法的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 是一個(gè)可變長(zhǎng)參數(shù)。
Java可變長(zhǎng)參數(shù)的方法重載
在Java代碼中,我們是不推薦帶有變長(zhǎng)參數(shù)的方法重載的。這樣的代碼調(diào)用人類(lèi)閱讀起來(lái)會(huì)感到“模糊”。
在項(xiàng)目和系統(tǒng)的開(kāi)發(fā)中,為了提高方法的靈活度和可復(fù)用性,我們經(jīng)常要傳遞不確定數(shù)量的參數(shù)到方法中,在Java 5之前常用的設(shè)計(jì)技巧就是把形參定義成Collection類(lèi)型或其子類(lèi)類(lèi)型,或者是數(shù)組類(lèi)型,這種方法的缺點(diǎn)就是需要對(duì)空參數(shù)進(jìn)行判斷和篩選,比如實(shí)參為null值和長(zhǎng)度為0的Collection或數(shù)組。
而 Java 5引入變長(zhǎng)參數(shù)(varags)就是為了更好地提高方法的復(fù)用性,讓方法的調(diào)用者可以“隨心所欲”地傳遞實(shí)參數(shù)量,當(dāng)然變長(zhǎng)參數(shù)也是要遵循一定規(guī)則的,
比如變長(zhǎng)參數(shù)必須是方法中的最后一個(gè)參數(shù);一個(gè)方法不能定義多個(gè)變長(zhǎng)參數(shù)等,這些基本規(guī)則需要牢記,但是即使記住了這些規(guī)則,仍然有可能出現(xiàn)錯(cuò)誤,我們來(lái)看如下代碼:
public class Client { //簡(jiǎn)單折扣計(jì)算 public void calPrice(int price,int discount){ float knockdownPrice =price * discount / 100.0F; System.out.println("簡(jiǎn)單折扣后的價(jià)格是:"+formateCurrency(knockdownPrice)); } //復(fù)雜多折扣計(jì)算 public void calPrice(int price,int... discounts){ float knockdownPrice = price; for(int discount:discounts){ knockdownPriceknockdownPrice = knockdownPrice * discount / 100; } System.out.println("復(fù)雜折扣后的價(jià)格是:" +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); } }運(yùn)行結(jié)果:
簡(jiǎn)單折扣后的價(jià)格是:¥374.25
這是一個(gè)計(jì)算商品價(jià)格折扣的模擬類(lèi),帶有變長(zhǎng)參數(shù)的calPrice方法則是較復(fù)雜的折扣計(jì)算方式,多種折扣的疊加運(yùn)算(模擬類(lèi)是一種比較簡(jiǎn)單的實(shí)現(xiàn))在實(shí)際生活中也是經(jīng)常見(jiàn)到的,比如在大甩賣(mài)期間對(duì)VIP會(huì)員再度進(jìn)行打折;或者當(dāng)天是你的生日,再給你打個(gè)9折,也就是俗話說(shuō)的“折上折”。
兩個(gè)calPrice()方法重載有點(diǎn)特殊:
calPrice(int price,int... discounts)// A的參數(shù)范疇覆蓋了
calPrice(int price,int discount)// B的參數(shù)范疇。
那問(wèn)題就出來(lái)了:對(duì)于
calPrice(49900,75)這樣的計(jì)算,到底該調(diào)用哪個(gè)方法來(lái)處理呢?
從運(yùn)行結(jié)果來(lái)看是調(diào)用了B方法,而不是變長(zhǎng)參數(shù)A的方法.
原因分析:Java在編譯時(shí),首先會(huì)根據(jù)實(shí)參的數(shù)量和類(lèi)型(這里是2個(gè)實(shí)參,都為int類(lèi)型,注意沒(méi)有轉(zhuǎn)成int數(shù)組)來(lái)進(jìn)行處理,也就是查找到calPrice(int price,int discount)方法,而且確認(rèn)它是否符合方法簽名條件。現(xiàn)在的問(wèn)題是編譯器為什么會(huì)首先根據(jù)2個(gè)int類(lèi)型的實(shí)參而不是1個(gè)int類(lèi)型、1個(gè)int數(shù)組類(lèi)型的實(shí)參來(lái)查找方法呢?這是個(gè)好問(wèn)題,也非常好回答:因?yàn)閕nt是一個(gè)原生數(shù)據(jù)類(lèi)型,而數(shù)組本身是一個(gè)對(duì)象,編譯器想要“偷懶”,于是它會(huì)從最簡(jiǎn)單的開(kāi)始“猜想”,只要符合編譯條件的即可通過(guò),于是就出現(xiàn)了此問(wèn)題。
問(wèn)題是闡述清楚了,為了讓我們的程序能被“人類(lèi)”看懂,還是慎重考慮變長(zhǎng)參數(shù)的方法重載吧,否則讓人傷腦筋不說(shuō),說(shuō)不定哪天就陷入這類(lèi)小陷阱里了。
Scala編譯器的處理方式就比較“顯式”了,直接拋出“ambiguous reference to overloaded definition” ERROR。
針對(duì)可變參數(shù)的方法重載機(jī)制,這是Scala的與java在編譯處理上區(qū)別的地方。
Scala分辨重載方法的過(guò)程與Java極為相似。任何情況下,被選中的重載版本都是最符合參數(shù)靜態(tài)類(lèi)型的那個(gè)。有時(shí)如果不止一個(gè)最符合的版本;這種情況下編譯器會(huì)給你一個(gè)“ambiguous reference to overloaded definition”(模糊引用了重載定義的方法)的錯(cuò)誤。
解決方案:
在scala代碼中顯式調(diào)用:toJSONString(Object object, SerializerFeature... features) 。
另外,不推薦帶有變長(zhǎng)參數(shù)的方法重載。
參考資料:
 1.http://www.cnblogs.com/DreamDrive/p/5412359.html
總結(jié)
以上是生活随笔為你收集整理的13.10 Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: 公司车可以抵押贷款吗 公司的车能做抵押吗
 - 下一篇: word怎么设置标题与正文之间的间距