2

Is it possible to create an array of static classes in Java? For example:

SceneObject[] scenes = {Loading.class, Menu.class};
// Loading and Menu extend SceneObject

We need to call static methods via the array, not instantiate them.

EDIT:

The following is what we are trying to accomplish. We could alternatively use many switches, but it sounds redundant to add every object to every switch in every method.

package net.bitworm.gameengine;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;

import net.bitworm.scenes.*;

public class SceneController {

public enum Scene{
    LOADING_SCENE,
    MENU,
    SCENE_1
}

public static SceneObject[] scenes = {new Loading(), new Menu()};

public volatile static Scene currentScene = Scene.LOADING_SCENE;

public static void setScene(Scene newScene){
    currentScene = newScene;
    System.out.println("Switched to " + currentScene.toString());
}

public static void update(GameContainer container, int delta){
    scenes[currentScene.ordinal()].update(container, delta);
}
public static void render(GameContainer container, Graphics g){
    scenes[currentScene.ordinal()].render(container, g);
}
public static void mouseMoved(int oldx, int oldy, int newx, int newy){
    scenes[currentScene.ordinal()].mouseMoved(oldx, oldy, newx, newy);
}
public static void mousePressed(int button, int x, int y){
    scenes[currentScene.ordinal()].mousePressed(button, x, y);;
}
public static void mouseReleased(int button, int x, int y){
    scenes[currentScene.ordinal()].mouseReleased(button, x, y);
}
public static void mouseWheelMoved(int change){
    scenes[currentScene.ordinal()].mouseWheelMoved(change);
}
public static void keyPressed(int key, char c){
    scenes[currentScene.ordinal()].keyPressed(key, c);
}
public static void keyReleased(int key, char c){
    scenes[currentScene.ordinal()].keyReleased(key, c);
}
4
  • Did you get an error when you tried this? Commented Jan 1, 2015 at 9:27
  • Yes. Type mismatch: cannot convert from Class<Menu> to SceneObject Commented Jan 1, 2015 at 9:27
  • Right, so you can define Class[] scenes = ... Commented Jan 1, 2015 at 9:28
  • In future, always specify an error in the question. Additionally, give more context - we can't tell what you're trying to achieve, which makes it harder to help you. Commented Jan 1, 2015 at 9:30

2 Answers 2

10

You need to differentiate between classes and objects. For example, you might have:

SceneObject[] scenes = { new Loading(), new Menu() };

or

Class[] classes = { Loading.class, Menu.class };

It's not clear from your question which you mean, but hopefully that should satisfy either case... note that you can't have generic arrays, so with the Class[] you can't specify that each class must extend SceneObject.

EDIT: Now we've got a bit more information, it sounds like you've got this:

abstract class SceneObject {}

class Menu extends SceneObject {
    static void foo() {
    }

    static void bar() {
    }
}

class Loading extends SceneObject {
    static void foo() {
    }

    static void bar() {
    }
}

The two foo methods here are completely unrelated - you can't use polymorphism to call them, because they're static methods. If you want to use polymorphism - i.e. call a method knowing which signature you want to call, but with an implementation that depends on the target of the call - you need instance methods:

abstract class SceneObject {
    abstract void foo() {
    }

    abstract void foo() {
    }
}

class Menu extends SceneObject {
    @Override void foo() {
    }

    @Override void bar() {
    }
}

class Loading extends SceneObject {
    @Override void foo() {
    }

    @Override void bar() {
    }
}

Then you can write:

SceneObject[] scenes = { new Loading(), new Menu() };

...

for (SceneObject scene : scenes) {
    scene.foo();
    scene.bar();
}
Sign up to request clarification or add additional context in comments.

15 Comments

Cannot create a generic array of Class<? extends SceneObject>
Yep. that works, unfortunatley, when we try to call the methods from the array, the methods are undefined for type Class.
@RayToal: Well not really - you could have a List<Class<? extends SceneObject>> easily enough. It's just that arrays can't be generic.
Is it possible to create an array to call static methods from without instantiating any classes or using a switch?
@GraysonPike: Why are you so against creating instances? It's not like you need to create lots of instances of these. Don't fight against the language.
|
1

Other than making an array of classes that extend SceneObject, we can make a container for these objects:

//a container that holds only the classes of SceneObject
public class ClassBox<T extends SceneObject> {
    private Class<T> theClass;

    public ClassBox(Class<T> theClass) {
        this.theClass = theClass;
    }
    public Class getTheClass() { //'getClass()' method is reserved, we use a more unique name
        return theClass;
    }
}

//testing classes
abstract class SceneObject {}
class Loading extends SceneObject {}
class Menu extends SceneObject {}
class noExtends1 {}

//testing 
public void main() {
    ClassBox[] scenes = {new ClassBox<>(Loading.class), new ClassBox<>(Menu.class)}; //these classes extend SceneObject
//  ClassBox[] sceneserror = {new ClassBox<>(Loading.class), new ClassBox<>(noExtends1.class)}; //gives error because 2nd array elem is not extending, so I commented it

    Log.v("custom log.v call", String.valueOf(Loading.class));
    Log.v("custom log.v call", String.valueOf(Menu.class));
    Log.v("custom log.v call", String.valueOf(scenes[0].getTheClass()));
    Log.v("custom log.v call", String.valueOf(scenes[1].getTheClass()));

//result is:
//V/custom log.v call: class me2.iwanttobealeader.pie$Loading
//V/custom log.v call: class me2.iwanttobealeader.pie$Menu
//V/custom log.v call: class me2.iwanttobealeader.pie$Loading
//V/custom log.v call: class me2.iwanttobealeader.pie$Menu
}

This answer has the benefit of specifying multiple criteria of inheritance for example:

public class ClassBox<T extends Fragment & FR_DbRequests.SynchListener>
//now it must implement the abstract class SyncListener and extend Fragment

But also the disadvantage of instantiating an additional object ,namely the container+variable containing the class, instead of just the variable containing the class.

2 Comments

When giving an answer it is preferable to give some explanation as to WHY your answer is the one.
Actually it's not "the one", it's just another way of making an array of classes, but let me just edit the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.