溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

IDEA?Debug問(wèn)題怎么解決

發(fā)布時(shí)間:2023-01-09 09:26:05 來(lái)源:億速云 閱讀:143 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“IDEA Debug問(wèn)題怎么解決”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“IDEA Debug問(wèn)題怎么解決”吧!

問(wèn)題引入

最近看了 eclipse 開(kāi)源的集合 Eclipse Collections,覺(jué)得它的 api 相比 JDK 集合 api 簡(jiǎn)潔,想在實(shí)際項(xiàng)目中使用,如下。

JDK api

 // users is List<String> 
 users.stream.map(user -> user.getName()).collect(Collectors.toList());

Eclipse Collections api

 //users is MutableList
 users.collect(user -> user.getName);

項(xiàng)目實(shí)際開(kāi)發(fā)中使用集合最多的地方還是來(lái)自數(shù)據(jù)庫(kù)查詢,如下。

JDK api

List<User> findByCity(String city);

我想改成

MutableList<User> findByCity(String city);

然而報(bào)錯(cuò)了

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.ArrayList<?>] to type [org.eclipse.collections.api.list.MutableList<?>] for value '[]'; nested exception is java.lang.IllegalArgumentException: Unsupported Collection interface: org.eclipse.collections.api.list.MutableList
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)

太長(zhǎng)不看直接結(jié)論是改成下列代碼。

FastList<User> findByCity(String city);

Debug

對(duì)代碼簡(jiǎn)單分析

報(bào)錯(cuò)的地方都是 Spring 的包,證明我們使用的 Spring Data JPA 訪問(wèn)數(shù)據(jù)庫(kù),事實(shí)上也是。

查看類名稱,方法名稱。 有 convert.ConversionFailedException/convert.support.ConversionUtils.invokeConverter/convert.support.GenericConversionService.convert等等,關(guān)鍵詞 convert,我應(yīng)該聯(lián)想到這段代碼的功能是把什么類型 convert 到什么類型。

再分析報(bào)錯(cuò)的那一行我們會(huì)更清晰一點(diǎn)。

  • result 是轉(zhuǎn)換的結(jié)果。

  • converter是轉(zhuǎn)換器,結(jié)合上面的結(jié)論,這個(gè)類肯定是真正執(zhí)行轉(zhuǎn)換的類,我們要的核心代碼肯定在這里,如果你直接去看的話,它肯定是一個(gè)接口,面向接口編程。

  • sourceType 源類型,結(jié)合上述分析肯定是原始類型。

  • targetType 目標(biāo)類型,同上不贅述。

打斷點(diǎn)

IDEA 可以直接點(diǎn)擊報(bào)錯(cuò) class 定位到源文件,這里我們先點(diǎn)擊 ConversionFailedException ,再點(diǎn)擊 ConversionUtils.java:47,發(fā)現(xiàn)都是報(bào)錯(cuò)的異常,對(duì)我們沒(méi)有幫助。最后我們點(diǎn)擊 GenericConversionService.java:192,終于看到一行代碼了。

Object result = 
    ConversionUtils.invokeConverter(converter, source, sourceType, targetType);

斷點(diǎn)分析

執(zhí)行過(guò)程會(huì)停留在斷點(diǎn)處,我們可以查看上下文變量類的實(shí)例。這里我們以 converter 為例。按照數(shù)字步驟點(diǎn)擊,如下。

IDEA?Debug問(wèn)題怎么解決

可能的 converter 如下:

1. java.lang.String -> java.lang.Enum
2. NO_OP
3. java.lang.Boolean -> java.lang.String
// 等等。。。。。

由于是底層方法,被調(diào)用的次數(shù)很多,在這個(gè)斷點(diǎn)停留的次數(shù)也很多。很多次不是我們想要的 converter

條件斷點(diǎn)

顧名思義 IDEA 會(huì)通過(guò)我們添加的條件來(lái)判斷這個(gè)斷點(diǎn)是否需要被處理。

我們想要的 converter 是什么呢?回到代碼分析階段,我們想要的 convertersourceType &rarr; targetType,targetType 類型是什么呢?回到我們自己寫(xiě)的代碼。

MutableList<User> findByAdress(String address);

可以看到我們需要 targetTypeMutableList class。

下面添加條件斷點(diǎn):

IDEA?Debug問(wèn)題怎么解決

完整的條件如下:

MutableList.class.isAssignableFrom(targetType.getType());

添加成功的標(biāo)志如下。

IDEA?Debug問(wèn)題怎么解決

單步調(diào)試

Debug 模式啟動(dòng)程序,可以看到 IDEA 停留在我們的條件斷點(diǎn)上,并且targetType 的類型正是 MutableList。

IDEA?Debug問(wèn)題怎么解決

單步調(diào)試代碼,來(lái)到 org.springframework.core.CollectionFactory#createCollection 方法。

部分代碼如下:

//省略的代碼
// 判斷集合類型是不是 ArrayList 或者 List,顯然這里不是
else if (ArrayList.class == collectionType || List.class == collectionType) {
  return new ArrayList<>(capacity);
}
//省略的代碼
else {
//如果是集合類型的接口 或者 不是集合類型拋出異常
  if (collectionType.isInterface() || !Collection.class.isAssignableFrom(collectionType)) {
    throw new IllegalArgumentException("Unsupported Collection type: " + collectionType.getName());
  }
  try {
  //如果是集合類型的類,直接通過(guò)反射實(shí)例化。
    return (Collection<E>) ReflectionUtils.accessibleConstructor(collectionType).newInstance();
  }
}

重回代碼分析

我們的 targetType 的類型正是 MutableList,而 MutableList 是接口,走讀代碼可以發(fā)現(xiàn)最終會(huì)執(zhí)行下面的代碼,最終導(dǎo)致拋出異常。

if (collectionType.isInterface() || !Collection.class.isAssignableFrom(collectionType)) {
    throw new IllegalArgumentException("Unsupported Collection type: " + collectionType.getName());
  }

翻看控制臺(tái)找到了下面的異常信息,這也側(cè)面反映我們之前找的報(bào)錯(cuò)位置不是很精確。我們尋找異常時(shí)應(yīng)該選擇最原始的異常信息。

Caused by: java.lang.IllegalArgumentException: Unsupported Collection type: org.eclipse.collections.api.list.MutableList
	at org.springframework.core.CollectionFactory.createCollection(CollectionFactory.java:205)
	at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:81)

繼續(xù)分析源碼可以發(fā)現(xiàn),如果我們定義的類型不是接口,JPA 就會(huì)通過(guò)反射創(chuàng)建集合,即如下代碼:

return (Collection<E>) ReflectionUtils.accessibleConstructor(collectionType).newInstance();

所以我們只需要將 MutableList 換成它的實(shí)現(xiàn)類即可,比如 FastList。最終代碼如下:

FastList<User> findByCity(String city);

感謝各位的閱讀,以上就是“IDEA Debug問(wèn)題怎么解決”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)IDEA Debug問(wèn)題怎么解決這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI