检查是否是私有静态内部类的实例



问题的标题听起来像是一个很好的思想实验。遗憾的是,事实并非如此。让我们假设下面的代码结构:

class Outer {
    private static class Inner implements SomeInterface {
        ...
    }
    public static SomeInterface returnInner() {
        return new Inner();
    }
}

是否有一个良好的,干净的方式来执行以下检查:

SomeInterface a  = A.returnInner();
if (a instanceof Outer.Inner)
    throw new Error("Ooops, something bad happened");

你认为这不是一个真实的例子吗?检查Arrays类和方法asList(T ...),它返回自己的List<T>实现,这恰好是private static class ArrayList<T>(这与通常的ArrayList无关-感谢Sun和Oracle没有你我会怎么做)。我需要检查传递给我的方法的对象是否不是这个包装器类的实例,因为它没有实现add()方法(它使用AbstractList的实现-它抛出UnsupportedOperationException)。

真的没有好的方法来检查这个吗?甚至通过一些反射魔法?

有一个方法,但无论如何都不是一个好方法:

// WARNINIG: This is very fragile, please try avoiding code like this.
if (theirList.getClass().getEnclosingClass() != null) {
    // theirList is an instance of an inner class
}

问题不在于很难做到,而在于结果变得非常不可靠:

  • 此代码拒绝List<T> 的可变实现-例如,如果您决定使用自己的嵌套类实现List<T>,它将被拒绝
  • 此代码将接受顶级只读实现 -如果Oracle决定有一天将实现移到顶级,您的代码将停止工作

由于这些原因,最好尝试添加到类中,捕获异常,并在调用者传递给您只读列表时采取任何替代方法。

这是一个可怕的、肮脏的、容易出错的做法,但是您可以检查类的名称。内部类的名称是外围类的名称,后跟$和内部类的名称。在本例中:

SomeInterface instance = Outer.returnInner();
if (instance.getClass().getName().equals(Outer.class.getName() + "$Inner")) {
    throw new RuntimeException("Ooops, something bad happened");
}

最新更新