0

我在 JAVA 代码中有枚举ERequestTypes我的枚举包含 20 多个元素,每个元素都是我的 JAVA 代码中的函数的名称。现在我想做以下事情而不是编写switch(ERequestTypes) case,并且在这种情况下以这种方式调用函数:

switch(ERequestTypes a) {
    case ERequestTypes.Initialize:
        Initialize();
    case ERequestTypes.Uninitialize:
        Uninitialize();
}

我想用一条线来做。枚举中的所有函数都具有相同的参数并返回相同的 int 值。我怎么能做到这一点?可能像在 C++ 或其他东西中一样在枚举中保留函数的指针。请帮忙 !

class CRequestValue {
    /**
     * Constructor.
     * 
     * @param aName - Name of the request.
     * @param aCode - Code of the request.
     */
    public CRequestValue(String aName, int aCode) {
        this.mName = aName;
        this.mCode = aCode;
    }

    private String mName;
    private int    mCode;

    public String GetName() {
        return this.mName;
    }

    public int GetCode() {
        return this.mCode;
    }

} /* class CRequestValue **/

enum ERequestTypes
{
    Initialize(new CRequestValue("Initialize", 0)),
    Uninitialize(new CRequestValue("Uninitialize", 1)),
    GetDeviceInfoList(new CRequestValue("GetDeviceInfoList", 2)),
    GetDeviceInfo(new CRequestValue("GetDeviceInfo", 3));

    private CRequestValue mRequestValue;

    private ERequestTypes(CRequestValue aRequestValue) {
        this.mRequestValue = aRequestValue;
    }

    public String GetName() {
        return this.mRequestValue.GetName();
    }

    public int GetCode() {
        return this.mRequestValue.GetCode();
    }

} /* enum ERequestTypes **/
4

3 回答 3

3

我不确定您的目标是什么,但您可以使用多态性而不是 switch 块,例如:

interface Invokable {
    int init(Object arg);
    int uninit(Object arg);
}

enum Request {
    INIT() {
        @Override
        public int invoke(Invokable invokable, Object arg) {
            return invokable.init(arg);
        }
    },
    UNINIT() {
        @Override
        public int invoke(Invokable invokable, Object arg) {
            return invokable.uninit(arg);
        }
    },
    ;
    public abstract int invoke(Invokable invokable, Object arg);
}


Invokable i = ....;
Object arg = ....;
Request r = Request.INIT;
r.invoke(i, arg); // should invoke Invokable.init(arg);
r = Request.UNINIT;
r.invoke(i, arg); // should invoke Invokable.uninit(arg);
于 2012-06-29T15:09:04.427 回答
2

你正在寻找反射

ErequestTypes a = <init>;
Object o = Class.forName(<your class name>).getMethod(a.getName(), <argtype>.class).invoke(<instance of your class, or null if static method>, <arg>);

请注意,如果您已经知道方法所在的类,则不需要 Class.forName。

于 2012-06-29T14:58:44.700 回答
0

您可以使用 Pavel 提到的多态性,但还有另一种解决方案——您根本不需要枚举。

将每个函数设为自己的对象并像枚举本身一样传递/使用这些对象的实例非常简单。

还有一些使用匿名内部类的解决方案(将它们附加到对象实例并传递这些实例),但我认为这通常不像只制作单独的对象那样可重用。

这是一些假代码:

public void MainClass {
    private final Runnable init=new Runnable {
        run() {
            // Initialize the system
        }
    }
    private final Runnable uninit = new Runnable() {
        run() {
            // Uninitialize the system
        }
    }

public someMethod() {

    // At this point you can treat the instances as you would any variable...
    Runnable nextOperation = init;

    // and executing whichever one you have is as simple as:
    nextOperation.run();

如果您希望“类型安全”(与枚举一样),请不要扩展 Runnable,而是创建一个扩展 Runnable 的新类,然后扩展该类。

由于这些是“内部类”(在另一个类的上下文中定义),它们可以访问和修改所有类成员变量,使它们更像独立方法而不是独立类。

最后请注意,由于每个类都是匿名在线定义的,因此它们几乎与创建枚举一样难以创建“重复项”,因此您通常可以将它们完全视为枚举(例如,使用“==”而不是 .equals()。

于 2012-06-29T15:41:45.677 回答