为什么不将嵌套类设为静态?

时间:2012-12-20 20:18:02

标签: java nested-class

如果我有一个嵌套类的类,为什么你不希望它是静态的?是否有一种方法可以让同一个类的两个实例拥有不同的嵌套类?

例如:

class MyClass {  
    public static class myInnerClass {

    }
}

6 个答案:

答案 0 :(得分:6)

  

为什么你不希望它是静态的

因为我希望它访问父对象的实例数据。

  

是否有一种方法可以让同一个类的两个实例拥有不同的嵌套类?

have你是什么意思?申报?一个类只有一个声明,列出所有嵌套类。所以,在这种情况下答案是否定的。

答案 1 :(得分:3)

ComparatorRunnable(多线程)实现为例。当您需要一个可以访问当前实例的字段和方法但在该类之外没有用的额外类时,这是一个典型示例。但是,静态类在封闭类型之外也是有用的。

public class EnclosingType
{

    private static final class StaticRunnableImplementation implements Runnable
    {
        private final EnclosingType instance;

        public StaticRunnableImplementation(EnclosingType instance)
        {
            this.instance = instance;
        }

        @Override
        public void run()
        {
            instance.getSomething();
            //getSomething() leads to compile error
        }
    }

    public class NonStaticRunnableImplementation implements Runnable
    {
        @Override
        public void run()
        {
            doStuff();
        }

    }

    public int getSomething()
    {
        return 42;
    } 

    public synchronized void doStuff()
    {
        ;
    }

    public void doSomething()
    {
        Thread t1 = new Thread(new StaticRunnableImplementation(this));
        Thread t2 = new Thread(new NonStaticRunnableImplementation());

        t1.start();
        t2.start();
    }
}

如果嵌套类被声明为静态,则无法访问封闭类型的当前实例的非静态方法和字段。

答案 2 :(得分:2)

我不知道我是否正确理解了您的问题,但静态内部类与非静态类之间的区别在于第二个需要从要创建的父类引用。

最好创建静态类,因为可以创建“隐藏的ciclic引用”。例如,在GUI开发中执行类似

的操作是正常的
public class View {
    private Table table;        
    ...
    private void addListeners() {
        this.table.addListener(new TableSelectionListener());
    }

    privte class TableSelectionListener implements Table.SelectionListener {
        @Overrides
        public void selected(SelectionEvent evt) { /* do stuff.*/ }
    }
}

许多程序员都没有意识到,但您现在在ViewTable之间有一个循环引用,因为SelectionListener是非静态的,会保存对其父级的引用。所以

  

查看 - >表 - > TableSelectionListener - >图

如果您声明TableSelectionListener static,则只需要创建视图中的“命名空间”,但除此之外,它不会保存对任何View的引用,除非您保存它在一个领域。但是,你将回到第一个问题:P

希望有所帮助:)

答案 3 :(得分:0)

non-static nested class已关联,并且可以访问封闭类实例的成员:

  

非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有。

答案 4 :(得分:0)

例如,如果实现某种类型的Listener,通常需要在收到事件时调用外部类的方法。在这种情况下,内部类比具有对外部类实例的显式引用的嵌套类更简单。

这通常用于GUI组件。例如(使用实际不存在的API):

public class CircleView extends View {
     private final Circle circle = new Circle();
     private final Button button = new Button();

     public CircleView() {
         circle.setColor(Color.RED);
         button.addClickListener(new MyClickListener());
     }

     private toggleColor() {
         circle.setColor(circle.getColor() == Color.RED ? Color.BLUE : Color.RED);
     }

     private class MyClickListener implements ClickListener() {
         @Override
         public void onClick() {
             // Only possible because of the implicit reference:
             toggleColor();
         }
     }
}

答案 5 :(得分:0)

非静态嵌套类允许以隐式/魔法方式执行以下操作:

class MyClass {  
    public static class MyInnerClass {
        final MyClass myClass_this;
        public MyInnerClass(MyClass parent) {
            // Nested class instance has/keeps access to "parent" object.
            // In a nested non-static class the "parent" is -guaranteed- to be
            // non-null as the nested class can only be created with
            // an instance of the containing class.
            myClass_this = parent;
        }
        public Foo bar() {
            // Use myClass_this
            // Would be available as MyClass.this or implicit resolution in a
            // a nested non-static class.
        }
    }
}

范围访问的规则也有所不同,但上面应该显示它何时有用/可取。在这两种情况下,内部类(MyClass$MyInnerClass)只有一个类型,尽管可能有很多实例。

这是一个“好”的东西,让这种非静态嵌套类型行为是值得商榷的,但 是用Java提供的。

然而,这种“非静态”行为在Java中非常有用的一种情况是使用匿名类(例如事件处理程序或回调),它们表现为非静态嵌套类; 而“不同的“构造相同的机制允许访问封闭类型中定义的方法。因此,将匿名类移动到非静态嵌套类只能被视为这种常见习语的扩展,这也允许暴露主格类型。

(C#没有“非静态”嵌套类的概念,但很容易按照上面的方式模拟它 - 虽然我认为通过更精细的界面通常会更好。此外,其他构造如此因为封闭可以最大限度地减少需求/使用。)