防止toString()中无限递归的最有效方法? [英] Most efficient way to prevent an infinite recursion in toString()?

查看:103
本文介绍了防止toString()中无限递归的最有效方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果收集的项目图中的某个地方是一个返回自身的引用,那么对于集合上的字符串可能会进入无限循环。请参阅下面的示例。

To string on a collection can get into a infinite loop if somewhere in the graph of collected items is a reference back to itself. See example below.

是的,良好的编码实践应该首先防止这种情况,但无论如何,我的问题是:检测递归的最有效方法是什么?这种情况?

Yes, good coding practices should prevent this in the first place, but anyway, my question is: What is the most efficient way to detect a recursion in this situation?

一种方法是在threadlocal中使用一个集合,但这看起来有点沉重。

One approach is to use a set in a threadlocal, but that seems a bit heavy.

public class AntiRecusionList<E> extends ArrayList<E> {
  @Override
  public String toString() {
    if (  /* ???? test if "this" has been seen before */ ) {
        return "{skipping recursion}";
    } else {
        return super.toString();
    }
  }
}


public class AntiRecusionListTest {
  @Test
  public void testToString() throws Exception {
      AntiRecusionList<AntiRecusionList> list1 = new AntiRecusionList<>();
      AntiRecusionList<AntiRecusionList> list2 = new AntiRecusionList<>();
      list2.add(list1);
      list1.add(list2);
      list1.toString();  //BOOM !
  }
}


推荐答案

我在问题中提到的threadlocal位:

The threadlocal bit I mentioned in the question:

public class AntiRecusionList<E> extends ArrayList<E> {


private final ThreadLocal<IdentityHashMap<AntiRecusionList<E>, ?>> fToStringChecker =
        new ThreadLocal<IdentityHashMap<AntiRecusionList<E>, ?>>() {
            @Override
            protected IdentityHashMap<AntiRecusionList<E>, ?> initialValue() {
                return new IdentityHashMap<>();
            }
        };    

@Override
public String toString() {
    boolean entry = fToStringChecker.get().size() == 0;
    try {
        if (fToStringChecker.get().containsKey(this)/* test if "this" has been seen before */) {
            return "{skipping recursion}";
        } else {
            fToStringChecker.get().put(this, null);
            entry = true;
        }
        return super.toString();
    } finally {
        if (entry)
            fToStringChecker.get().clear();
    }
}
}

这篇关于防止toString()中无限递归的最有效方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆