Java 互相關(guān)聯(lián)的實體無限遞歸
今天在測試的時候出現(xiàn)了一個bug,在把關(guān)聯(lián)實體序列化返回的過程中報錯了,提示
Caused by: java.lang.StackOverflowError: null
這個是堆棧溢出錯誤,根據(jù)錯誤線索查找,最后發(fā)現(xiàn)Column和Table實體互相關(guān)聯(lián),也就是說
Column實體中有Table屬性,Table實體中也有Column屬性,導(dǎo)致了在序列化的過程中出現(xiàn)了死循環(huán),無限遞歸,以至堆棧溢出報錯。
在Jackson2.0以前的解決辦法是
在關(guān)聯(lián)的屬性上添加
1
|
@JsonBackReference |
或者
1
|
@JsonIgnore |
注解中的一個即可。但是從Jackson2.0以后的版本開始,提供@JsonIdentityInfo注解實現(xiàn)這個問題的解決,在實體類前加注解
1
|
@JsonIdentityInfo (generator=ObjectIdGenerators.IntSequenceGenerator. class , property= "@id" ) |
好好理解Java中的遞歸
遞歸的思想
把規(guī)模大的問題轉(zhuǎn)化為規(guī)模小的相似的子問題來解決。在函數(shù)實現(xiàn)時,因為解決大問題的方法和解決小問題的方法往往是同一個方法,所以就產(chǎn)生了函數(shù)調(diào)用它自身的情況。另外這個解決問題的函數(shù)必須有明顯的結(jié)束條件,這樣就不會產(chǎn)生無限遞歸的情況了。
一句話總結(jié):遞歸就是自己調(diào)用自己。
遞歸的條件要素
1、遞歸有兩個重要條件
- 可以通過遞歸調(diào)用來縮小問題規(guī)模,且新問題與原問題有著相同的形式。(自身調(diào)用)
- 存在一種簡單情境,可以使遞歸在簡單情境下退出。(遞歸出口)
2、遞歸的三要素
- 嘗試將一個問題化簡到更小的規(guī)模
- 父問題與子問題不能有重疊的部分
- 一定有一種可以退出程序的情況
遞歸的算法結(jié)構(gòu)
遞歸的常用算法偽代碼如下:
1
2
3
4
5
6
7
|
func( mode){ if (endCondition){ //遞歸出口 end; } else { func(mode_small) //調(diào)用本身,遞歸 } } |
遞歸實戰(zhàn)舉例
遞歸講起來還是有點小抽象,我們直接來看代碼
1、斐波那契數(shù)的遞歸實現(xiàn)
斐波那契數(shù)列的遞推公式:Fib(n)=Fib(n-1)+Fib(n-2),生成數(shù)列(1、1、2、3、5、8...)。
1
2
3
4
5
6
7
8
9
|
public static int fib( int n) throws Exception { if (n < 0 ){ throw new Exception( "請輸入正確的參數(shù)" ); } else if (n == 0 || n == 1 ){ return n; } else { return fib(n - 1 ) + fib(n - 2 ); // 調(diào)用自己 } } |
2、99乘法表的遞歸實現(xiàn)
1
2
3
4
5
6
7
8
9
10
|
public static void mul( int n){ if (n== 1 ){ System.out.println( "1*1=1" ); } else { mul(n - 1 ); for ( int i= 1 ;i<=n;i++){ System.out.println(i + "*" + n + "=" + i*n + " " ); } } } |
小結(jié)一下吧
遞歸算法是一種直接或間接地調(diào)用自身的算法。如果一個問題可以解可以分解為幾個子問題的解; 這個問題與分解之后的子問題,除了數(shù)據(jù)規(guī)模不同,求解思路完全一樣;并且存在明顯的遞歸終止條件;那么遞歸將是一種不錯的選擇。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://kangkang.blog.csdn.net/article/details/53393467