在Java中将字段的值定义为常量

4

我将在Java中实现一个标准的面向对象库。该标准包括许多通过终端传输的消息。每个消息都被实现为单独的类。

其中一些字段表示为char类型,并且这些字段具有标准中定义的值之一。例如,

public class OutgoingMessage {
    private char action;

此处action可以取这些值:

'0' - Do not print
'1' - Print
'2' - Print and Forward
'3' - Print and Reply
'F' - Forward
'R' - Reply

有些类具有超过2个字段的情况。在这种情况下,在类中定义这些字段作为常量可能会很混乱。

因此,我尝试将这些值实现为

public class OutgoingMessage {
    private char action;

    public final class ActionTypes {
        public static final char DO_NOT_PRINT = '0';
        public static final char PRINT = '1';
        ...

以下是使用方法:
...
message.setAction(OutgoingMessage.ActionTypes.DO_NOT_PRINT);
...
message.setFooBar(OutgoingMessage.FooBarTypes.FOO_BAR);
...

你认为呢?这种方法有什么问题吗?你会如何在库中定义这些常量?谢谢。

6
可以,如果你至少使用 jdk 1.5,也可以使用枚举类型。 - Rudy
1
在我看来也很完美。 - Kainsin
5个回答

8

建议使用枚举类型代替intchar常量:

public enum Action {
    DoNotPrint,
    Print,
    PrintAndForward,
    PrintAndReply,
    Forward,
    Reply
}

public class OutgoingMessage {
     private Action action;

如果您需要将一个字符与操作相关联,请按照以下步骤进行操作:

public enum Action {
    DoNotPrint('0'),
    Print('1'),
    PrintAndForward('2'),
    PrintAndReply('3'),
    Forward('F'),
    Reply('R');

    private static Map<Character, Action> map = new HashMap<Character, Action>() {{
        for (Action action : Action.values()) {
            put(action.getChar(), action);
        }
    }};

    private final char c;

    private Action(char c) {
        this.c = c;
    }

    public char getChar() {
        return c;
    }

    public static Action parse(char c) {
        if (!MapHolder.map.containsKey(c))
            throw new IllegalArgumentException("Invalid char: " + c);
        return MapHolder.map.get(c);
    }
}

以下是如何使用parse方法的步骤:
public static void main(String[] args) {
    System.out.println(Action.parse('2')); // "PrintAndForward"
    System.out.println(Action.parse('x')); // throws IllegalArgumentException
}

4
这几乎是实现常量的新标准。这种方法更好,因为它是类型安全的。 - Moonbeam
@Kit:这意味着即使在编译时,您也只能使用有效的值。 - Michael Borgwardt
@Kit Ho:“MyEnum.PRINT_CHARACTER”是一个唯一的标识符,它不等于任何其他东西。如果您使用“旧样式”的常量,如“int PRINT_CHARACTER = 42”,则会与产生整数值42的任何表达式匹配。在API中,这可能会导致混淆。 - Adriaan Koster
@Adriaan:这就是类型安全的意思吗? - TheOneTeam
我将值读取为char。如何将其转换为定义的枚举?message.setAction(c); // c是一个char - xelon
显示剩余2条评论

2

枚举(enum)是您想要用于此问题的。如果您还需要能够获取字符代码,则可以将其添加到枚举中,如下所示:

public enum Action {
    DO_NOT_PRINT('0'),
    PRINT('1'),
    PRINT_AND_FORWARD('2'),
    PRINT_AND_REPLY('3'),
    FORWARD('F'),
    REPLY('R');

    private final char code;

    private Action(char code) {
        this.code = code;
    }

    public char getCode() {
        return code;
    }
}

您只需在程序中使用枚举常量,当您需要字符代码时,调用枚举值上的getCode即可:

Action action = Action.DO_NOT_PRINT;
message.setAction(action);

// Suppose you need the char code:
char code = action.getCode();

1
您还可以更深入地考虑架构,创建一个Action类(这也将避免后来的大型switch语句并将一些代码与标准和消息解耦)。
然后,我会放弃操作类型,并通过简单地添加Action实现,使其易于扩展。
interface Action {
  public void performAction(Standard standard, OutgoingMessage msg);
}

class PrintAction implements Action {
  // Implement the interface methods properly...  
}

class ForwardAction implements Action {
  // Implement the interface methods properly...  
}

然后,您只需将操作实例添加到您的消息中:

msg.addAction(new PrintAction());
msg.addAction(new ForwardAction());

如果需要将操作与消息一起传递,请使它们可序列化(最好是让Action接口扩展Serializable接口)。

我知道我举的例子是错的 :) 当然,这是正确的,但有些字段只是愚蠢的数据字段。我无法将它们放入一个对象中。不管怎样,还是谢谢 ;) - xelon
是的,那么枚举(enum)就是一个不错的选择 :) - Vincent Mimoun-Prat

1

我相信这是可以的。但为了简单起见,如果您使用至少JDK1.5,也可以使用枚举。


0

你现在的做法不错,但如果你只是想声明常量,可以使用一个接口。

public class OutgoingMessage {
    private char action;

    public final interface ActionTypes {
        public static final char DO_NOT_PRINT = '0';
        public static final char PRINT = '1';
        ...

对的,枚举也很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接