0

I've been learning Java recently and reached the following conclusion: declaring a static nested type is a meaningless redundancy.

I was reading the answers on the below question and while I do understand the answers (and it cleared my inetial confusion - similar to the one the asker had) Can a Static Nested Class be Instantiated Multiple Times? I also concluded that the word static regarding an inner type is meaningless, for example if we didn't declare the inner type as static, we still wouldn't need to instantiate the outer type to be able to create new objects of the inner type. after all its a nested type and not a member/variable of the outer type. I just tested some code (removed static) and my assumption was right.

Is there anything I missed?

here is the code I tested (Note when I removed Static from KeyEvent Type inside IGameInput, every thing worked fine)

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;
  }
}
Community
  • 1
  • 1

3 Answers3

3

You can't instantiate a non-static nested class without an instance of the containing class.

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

    class Inner { }
}

The only way you'd be able to do this is if you instantiated it within an instance of the containing class (most likely what you are doing, based on your explanation):

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

    class Inner { }
}

Or by using an instance of the containing class to instantiate the inner class:

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

    class Inner { }
}

Otherwise you'll get the compile-time error:

non-static variable this cannot be referenced from a static context


With your code example, it makes a lot more sense. KeyEvent is still static. Looking into JLS §9.5:

A member type declaration in an interface is implicitly static and public.

This means all classes, whether you explicitly define them as static or not, will be static.

Vince
  • 14,470
  • 7
  • 39
  • 84
1

KeyEvent is a nested class of the interface IGameInput.

Nested classes of an interface are always implicitly static (and public).

See the JLS:

A member type declaration in an interface is implicitly public and static. It is permitted to redundantly specify either or both of these modifiers.

So, your conclusion is correct, but only for nested classes of interfaces. It's false for nested classes of classes.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks, Ok lets forget about interfaces for a while, lets assume it was a class called GameInput, now in order to be able to instantiate a non static KeyEven I need to have something like GameInputInstance.KeyEvent ke1 = new GameInputInstance.KeyEvent(); now if KeyEvent was static and I had the following statement GameInput.KeyEvent ke2 = new GameInput.KeyEvent; what exactly is the difference between ke1 and ke2? in both cases I created an instance of the inner type both of them don't belong to any instance of the outer type! – Newbie And Curious Apr 13 '16 at 21:57
  • and I say they don't belong to any instance of GameInput because GameInput doesn't have a reference/member of KeyEvent, it just have an inner type definition of KeyEvent – Newbie And Curious Apr 13 '16 at 21:58
  • How about you do that, try to compile your code, see the difference by yourself, and ask a question with a minimal example containing real code that actually compiles? – JB Nizet Apr 13 '16 at 21:59
  • thanks again , yes the example I wrote was full of syntactical errors. sorry I was still trying to formulate my confusion, once the main question was answered and I realized that I need "static" in order to be able to create an instance without instantiating the outer type, I started to wonder why would anyone ever need a static inner type since it can be treated as an outer type, its kinda counter intuitive. anyway thanks again – Newbie And Curious Apr 13 '16 at 23:30
1

According to Java documentation Static Nested Classes cab be instantiated without having to instantiate the outer class. Notice: "In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.". If we have inner and out class like this:

public class A {
  static public class B {
  }
}

We can instantiate multiple instances of B like this:

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

Hope this helps.

Ramana
  • 31
  • 2