【问题标题】:Java: How to check if an object is an instance of a non-static inner class, regardless of the outer object?Java:无论外部对象如何,如何检查对象是否是非静态内部类的实例?
【发布时间】:2013-07-04 10:40:55
【问题描述】:

如果我有一个内部类,例如

class Outer{
    class Inner{}
}

有没有办法检查任意Object 是否是任意Inner 的实例,而不管其外部对象如何?当对象不是来自同一个OuterInners 时,instanceof 给出 false。我知道一种解决方法就是让Inner 成为一个静态类,但我想知道我所问的是否可行。

例子:

class Outer{
    Inner inner = new Inner();
    class Inner{}

    public boolean isInner(Object o){
        return o instanceof Inner;
    }
}


Outer outer1 = new Outer();
Outer outer2 = new Outer();
boolean answer = outer1.isInner(outer2.inner); //gives false

【问题讨论】:

  • 你能举一个instanceof Inner返回假的例子吗?
  • @cambecc, o instanceof Outer.Innero 是任何OuterInner 的实例而不是您从中调用它的那个时,给出错误。
  • 不知道你所说的“任何Outer 不是你打电话的那个人”是什么意思。一个快速的代码示例对于回答您的问题非常有用。你不是说Outer.InnerOtherOuter.Inner 应该是相同的Inner,对吗?
  • @cambecc,包括示例。
  • 感谢您的示例。刚刚尝试运行它;结果是true。你确定你看到falsefalse 的结果将违反 JLS §15.20.2,其中说:“在运行时,如果 RelationalExpression 的值不为 null 并且引用可以强制转换为ReferenceType 而不引发 ClassCastException。" 我们知道 outer2.inner 可以转换为 Inner,因为那是它的类型。尝试将isInner 的参数更改为类型Inner,您将看到不需要显式转换并且不会发生编译错误。不知道为什么你会看到false

标签: java inner-classes instanceof


【解决方案1】:

然后呢?

public static boolean isInnerClass(Class<?> clazz) {
    return clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers());
}

方法isMemberClass() 将测试该方法是否是成员(而不是匿名或本地类),第二个条件将验证您的成员类不是静态的。

顺便说一下,documentation 解释了本地、匿名和嵌套类之间的区别。

嵌套类分为两类:静态和非静态。声明为静态的嵌套类简称为静态嵌套类。非静态嵌套类称为内部类

【讨论】:

  • 请注意,isMemberClass() 对匿名类和本地类返回 false(这是有道理的,但可能会令人惊讶)。如果您对这些类类型感兴趣,请使用 isAnonymousClass()isLocalClass()
【解决方案2】:

o 是任何OuterInner 的实例时,o instanceof Outer.Inner 给出false,而不是您调用它的那个。

这不会发生在我身上 - 无论Outer 属于哪个特定封闭实例o 属于o instanceof Inner,我都会得到true

class Outer {
  class Inner {}

  void test() {
    // Inner instance that belongs to this Outer
    Inner thisInner = new Inner();

    // Inner instance that belongs to a different Outer
    Outer other = new Outer();
    Inner otherInner = other.new Inner();

    // both print true
    System.out.println(thisInner instanceof Inner);
    System.out.println(otherInner instanceof Inner);
  }

  public static void main(String[] args) {
    new Outer().test();
  }
}

使用 Java 6 和 7 测试。

【讨论】:

    【解决方案3】:

    您是否尝试过使用getEnclosingClass()

    返回底层类的直接封闭类。 如果底层类是顶级类,则此方法返回 null。

    Outer.class.equals(object.getClass().getEnclosingClass())
    

    获得正确的对象封闭类,恕我直言,并不是那么容易。阅读this

    有点黑客行为是:

    object.getClass().getName().contains("Outer$");
    

    【讨论】:

    • 但这也适用于任何假设的 OtherInner ...?
    【解决方案4】:

    你总是可以的:

    getClass().getName()
    

    并进行字符串比较。

    编辑:考虑继承(在内部类中?谁会这样做?!)你总是可以遍历getSuperclass() 并检查它们,甚至去实现接口。

    【讨论】:

    • @IanRoberts - 为什么不呢? 2 内部实例将具有相同的完全限定类名,而与父对象无关
    • 是的,但是如果Inner2 extends Inner 则类为Inner2 的对象Inner 的实例,即使它们的类名不同。
    • @IanRoberts - 没错。虽然仍然可以修复:-)(编辑传入)
    • 类名并不能说明它是否是静态的。
    【解决方案5】:

    java.lang.Class.getEnclosingClass() 方法返回底层类的直接封闭类。如果该类是顶级类,则此方法返回 null。

    下面的例子展示了java.lang.Class.getEnclosureClass()方法的使用:

    import java.lang.*;
    
    public class ClassDemo {
       // constructor
       public ClassDemo() {
    
          // class Outer as inner class for class ClassDemo
          class Outer {
    
             public void show() {
                // inner class of Class Outer
                class Inner {
    
                   public void show() {
                      System.out.print(getClass().getName() + " inner in...");
                      System.out.println(getClass().getEnclosingClass());    
                   }
                }
                System.out.print(getClass().getName() + " inner in...");
                System.out.println(getClass().getEnclosingClass());
    
                // inner class show() function
                Inner i = new Inner();
                i.show();
             }
          }
    
          // outer class show() function
          Outer o = new Outer();
          o.show();
       }
    
       public static void main(String[] args) {
         ClassDemo cls = new ClassDemo();
       }
    }
    

    输出

    ClassDemo$1Outer inner in...类ClassDemo

    ClassDemo$1Outer$1Inner 内...class ClassDemo$1Outer

    【讨论】:

      【解决方案6】:

      我在谷歌上搜索找到更好的答案,发现那里没有。

      这是我所拥有的,效果很好:

          public static boolean isStatic(Class klass) {
                  return Modifier.isStatic(klass.getModifiers());
          }
      
          /**
           * Non static inner class
           */
          public static boolean isInnerclass(Class klass) {
                  return klass.getDeclaringClass() != null && !isStatic(klass);
          }
      

      对于本地内部类将返回 true。 isMemberClass 和其他人不适用于此目的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-24
        • 2015-08-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多