Java静态嵌套类型语义

时间:2016-04-13 21:22:27

标签: java

我最近一直在学习Java并得出以下结论: 声明静态嵌套类型是一种无意义的冗余。

我正在阅读以下问题的答案,虽然我理解答案(并且它清除了我的无聊混淆 - 类似于提问者的那个) Can a Static Nested Class be Instantiated Multiple Times? 我还得出结论,关于内部类型的静态这个词是没有意义的,例如,如果我们没有将内部类型声明为静态,我们仍然不需要实例化外部类型以便能够创建内部类型的新对象。毕竟它是一个嵌套类型而不是外部类型的成员/变量。我刚刚测试了一些代码(删除静态),我的假设是正确的。

我错过了什么吗?

这是我测试的代码(注意当我从IGameInput中的KeyEvent类型中删除Static时,每件事都运行正常)

package FrameWork;
import java.util.List;
public interface IGameInput {

    //type definitions
    public static class KeyEvent {
public static final int KEY_DOWN = 0;
public static final int KEY_UP = 1;
public int type;
public int keyCode;
public char keyChar;
    }
}

///////////////////////

package FrameWork.Imp;


import java.util.ArrayList;
import java.util.List;

/*
*/
public class Pool<T> 
{  
    public interface PoolObjectFactory<T> {
    public T createObject(); 
}

    private final ArrayList<T> freeObjects;
    private final PoolObjectFactory<T> factory;
    private final int maxSize;

    public Pool(PoolObjectFactory<T> factory, int maxSize)
    {
        this.factory = factory;
        this.maxSize = maxSize;
        this.freeObjects = new ArrayList<T>(maxSize);
    }

    public T newObject() 
    {
        T object = null;
        if (freeObjects.size() == 0)
        {
            object = factory.createObject();
        }
        else
        {
            object = freeObjects.remove(freeObjects.size() - 1);
        }
        return object;
    }

    public void free(T object) 
    {
        if (freeObjects.size() < maxSize)
        {
            freeObjects.add(object);
        }
    }
}

////////////////////////

package FrameWork.Imp;

import java.util.ArrayList;
import java.util.List;
import android.view.View;
import android.view.View.OnKeyListener;
import FrameWork.IGameInput.KeyEvent;
import FrameWork.Imp.Pool.PoolObjectFactory;

public class KeyboardHandler implements OnKeyListener {
  boolean[] pressedKeys = new boolean[128];
  Pool<KeyEvent> keyEventPool;
  List<KeyEvent> keyEventsBuffer = new ArrayList<KeyEvent>();
  List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();

  public KeyboardHandler(View view) {

    PoolObjectFactory<KeyEvent> factory;
    factory =
        new PoolObjectFactory<KeyEvent>() {
          @Override
          public KeyEvent createObject() {
            return new KeyEvent();
          }
        };
    keyEventPool = new Pool<KeyEvent>(factory, 100);
    view.setOnKeyListener(this);
    view.setFocusableInTouchMode(true);
    view.requestFocus();
  }

  @Override
  public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
    if (event.getAction() == android.view.KeyEvent.ACTION_MULTIPLE) return false;
    synchronized (this) {
      KeyEvent keyEvent = keyEventPool.newObject();
      keyEvent.keyCode = keyCode;
      keyEvent.keyChar = (char) event.getUnicodeChar();
      if (event.getAction() == android.view.KeyEvent.ACTION_DOWN) {
        keyEvent.type = KeyEvent.KEY_DOWN;
        if (keyCode > 0 && keyCode < 127) pressedKeys[keyCode] = true;
      }
      if (event.getAction() == android.view.KeyEvent.ACTION_UP) {
        keyEvent.type = KeyEvent.KEY_UP;
        if (keyCode > 0 && keyCode < 127) pressedKeys[keyCode] = false;
      }
      keyEventsBuffer.add(keyEvent);
    }
    return false;
  }
}

3 个答案:

答案 0 :(得分:3)

无法 实例化非静态嵌套类,而不包含包含类的实例。

class Test {
    public static void main(String[] args) { //static, non-instance method
        Inner inner = new Inner(); //error
    }

    class Inner { }
}

你能够做到这一点的唯一方法是,如果你在包含类的实例中实例化它(你很可能正在做什么,根据你的解释):

class Test {
    public void someMethod() { //non-static, instance method
        Inner inner = new Inner();
    }

    class Inner { }
}

或者通过使用包含类的实例来实例化内部类:

class Test {
    public static void main(String[] args) { //static, non-instance method
        Test test = new Test();
        Inner inner = test.new Inner(); //error
    }

    class Inner { }
}

否则您将收到编译时错误:

  

非静态变量,不能从静态上下文引用

使用您的代码示例,它更有意义。 KeyEvent仍然是静态的。展望JLS §9.5

  

接口中的成员类型声明是隐式静态和公共的。

这意味着所有类,无论您是否明确将其定义为static,都将为static

答案 1 :(得分:1)

KeyEvent界面 IGameInput的嵌套类。

接口的嵌套类始终是隐式静态(和公共)。

请参阅the JLS

  

接口中的成员类型声明是隐式公共和静态的。允许冗余地指定这些修饰符中的一个或两个。

因此,您的结论是正确的,但仅适用于嵌套的接口类。对于嵌套的类类,它是错误的。

答案 2 :(得分:1)

根据more info here静态嵌套类,可以实例化cab,而无需实例化外部类。注意:“实际上,静态嵌套类在行为上是一个顶级类,它已经嵌套在另一个顶级类中,以方便打包。”如果我们有这样的内外阶段:

public class A {
  static public class B {
  }
}

我们可以像这样实例化B的多个实例:

        A.B b1 = new A.B();
        A.B b2 = new A.B();

希望这有帮助。