java 幻数问题的解决方案......?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15539435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 19:59:01  来源:igfitidea点击:

Solution for Magic Number issue......?

javaswitch-statementsonarqubemagic-numbers

提问by Ruchira Gayan Ranaweera

Consider the following code segment...

考虑以下代码段...

 public static UserStatus getEnum(int code) {
    switch (code) {
        case 0:
            return PENDING;
        case 1:
            return ACTIVE;
        case 2:
            return SUSPENDED;
        case 3:
            return DELETED;
        case 4:
            return LOGIN_DISABLED;
        default:
            return null;
        }

}

Now number 3 and 4 in cases(case 3 and case 4) are detected as magic numbers by SONAR.

现在,案例(案例 3 和案例 4)中的数字 3 和 4 被 SONAR 检测为幻数。

To avoid that issue I changed my code segment as follows...

为了避免这个问题,我改变了我的代码段如下......

 public static UserStatus getEnum(int code) {        
    final int Pending=0;
    final int Active=1;
    final int Suspended=2;
    final int Deleted= 3;
    final int Login_details=4;

    switch (code) {
        case Pending:
            return PENDING;
        case Active:
            return ACTIVE;
        case Suspended:
            return SUSPENDED;
        case Deleted:
            return DELETED;
        case Login_details:
            return LOGIN_DISABLED;
        default:
            return null;
    }
}

Is this a good way to solve the magic number issue in this kind of scenario ?.

这是在这种情况下解决幻数问题的好方法吗?。

回答by Ted Hopp

I gather that you want to avoid using integer literals in the code. Your solution is not particularly effective because it simply moves the literals to the top of the method. It gains a little bit because it gives meaningful names to the constants, but these names are private to the method.

我认为您想避免在代码中使用整数文字。您的解决方案并不是特别有效,因为它只是将文字移动到方法的顶部。它获得了一些好处,因为它为常量提供了有意义的名称,但这些名称对方法来说是私有的。

A better approach would be to define the numbers as fields in an interface. You can then statically import the fields and use them as symbolic names for the constants.

更好的方法是将数字定义为接口中的字段。然后,您可以静态导入字段并将它们用作常量的符号名称。

If the enum is declared in the same order as the constants:

如果枚举以与常量相同的顺序声明:

enum UserStatus {PENDING, ACTIVE, SUSPENDED, DELETED, LOGIN_DISABLED}

you can do another trick:

你可以做另一个技巧:

public static UserStatus getEnum(int code) {
    UserStatus[] values = UserStatus.values();
    return (code >= 0 && code < values.length) ? values[code] : null;
}

However, this creates a linkage between the constant values and the declaration of the enum. This may be okay, depending on where the actual parameter values are generated in calls to getEnum.

然而,这会在常量值和枚举的声明之间创建一个链接。这可能没问题,具体取决于在调用getEnum.

回答by Adrian Shum

The problem is straight-forward and obvious: when people is reading your code, it is not obvious why 1 will give PENDING. What is the meaning of 1?

问题很直接也很明显:当人们阅读你的代码时,为什么 1 会给出 PENDING 并不明显。1的含义是什么?

You should give semantic meaning to that. Using constants is what normally should be done:

你应该赋予语义意义。使用常量是通常应该做的:

(Assume the getEnum()is part of the UserService, the code should look something like)

(假设getEnum()是 UserService 的一部分,代码应该类似于)

public interface UserService {
   public static final int USER_STATUS_VAL_PENDING = 1;
   public static final int USER_STATUS_VAL_ACTIVE = 2;

   UserStatus getUserStatus(int userStatusVal);
}

public class SimpleUserService implements UserService {
   public UserStatus getUserStatus(int userStatusVal) {
      switch userStatusVal {
      case USER_STATUS_VAL_PENDING:
         return UserStatus.PENDING;
      case USER_STATUS_VAL_ACTIVE:
         return UserStatus.ACTIVE;
      //.....
   }
}

As suggested by another answer, you may rely on the ordinal value of enum to do the int-enum mapping. However you have to be aware that, such way can lead to problem if you rearraged the values of enum, or added new values at position apart from the end. The ordinal values will be changed and you have no way to override that.

正如另一个答案所建议的那样,您可能会依赖 enum 的序数值来进行 int-enum 映射。但是您必须注意,如果您重新排列枚举的值,或者在远离末尾的位置添加新值,这种方式可能会导致问题。序号值将被更改,您无法覆盖它。

Another thing to pay attention is, there are something you are not done right in your code:

另一件要注意的事情是,您的代码中有些地方做得不对:

  1. As the purpose is to give semantic meaning to the integer literal by making it a constant, it should be something visible to the caller, therefore local final variable is not the right way to do.
  2. you should use ALL_CAP_UNDERSCORE_DELIMITED for constants name
  1. 由于目的是通过使其成为常量来赋予整数文字语义意义,因此它应该对调用者可见,因此局部最终变量不是正确的方法。
  2. 您应该使用 ALL_CAP_UNDERSCORE_DELIMITED 作为常量名称