简体   繁体   中英

Creating an array of classes in Java

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);
}

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 - ie 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();
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM