【问题标题】:Java Annotation - array of Objects or toString valuesJava Annotation - 对象数组或 toString 值
【发布时间】:2015-07-06 11:36:03
【问题描述】:

我需要编写一个注释来从结果集中排除某些值。

背景:

从字段中选择不同的值并在组合框中列出。一些遗留值已被弃用,我不想展示它们,即使它们是由 JDBC 的 SELECT DISTINCT() 返回的。它就像一个迷你框架,人们可以通过单击 ComboBox 中的值来构建选择查询。

我尝试了以下方法(代码无法编译 - 注释行是我尝试解决问题的方法):

public enum JobType {
    //...
    S,
    //...
}

public @interface Exclude {
    Object[] values(); // Invalid type
    Enum[] values(); // Invalid type again
    String[] values(); // Accepts but see the following lines
}

@Table(name = "jobs_view")
public class JobSelectionView extends View {
    //...
    @Exclude(values = {JobType.S.toString()}) // Not a constant expression
    @Exclude(values = {JobType.S.name()}) // Not a constant expression ?!?!?!
    @Exclude(values = {"S"}) // Works but... come on!
    @Enumerated(value = EnumType.STRING)
    @Column(name = "type")
    private JobType type;
    //...
}

我不喜欢使用{"S"},有什么建议吗?

【问题讨论】:

  • 必须使用编译时间常数。这意味着 没有 方法。您可以使用JobType[]
  • 但是如果声明 JobType[] values() 那么我将无法将 @Exclude 重用于其他类型的枚举。
  • 你可以使用public static final常量。
  • 我试图用“public static final String S = JobType.S.name();”来欺骗 Java但它比这更聪明。 :-(

标签: java annotations coding-style


【解决方案1】:

但如果声明JobType[] values(),那么我将无法将@Exclude 重用于其他类型的Enum

不过,这是做你想做的事的最佳方式。事情是这样的:

Enum 类本身毫无意义。

它只有在子类化时才有意义。假设您要添加另一个过滤器,例如 Color(您自己的自定义 Color 枚举,而不是 java.awt.Color)。显然,您的过滤类所做的事情与过滤掉 JobType 和过滤掉 Color 的做法大不相同!

因此,最好的办法是让 enum 的每个不同时间您都尝试过滤它自己的论点,例如

public @interface Exclude {
    JobType[] jobs;
    Color[] colors;
    Foo[] foos;
    Quux[] quuxes;
}

这将完成两件事:

  1. 让您轻松针对每种不同的过滤器类型执行不同的过滤行为。
  2. 通过将不同的参数分类为不同的组,使@Excludes 注释更清晰。

Enum.name() 的 Javadoc 说:

返回此enum 常量的名称,与其enum 声明中的声明完全相同。大多数程序员应该优先使用toString() 方法而不是这个方法,因为toString 方法可能会返回一个对用户更友好的名称。 此方法主要设计用于正确性取决于获取确切名称的特殊情况,该名称不会因版本而异。

我建议您尝试告诉您公司的人员阅读Open/Closed principle 并解释为什么在这种情况下违反它会特别有害。

【讨论】:

  • 对我来说,重要的是如果有人使用 IDE 重构 Enum 的成员(或他们的名字),那么最终的字符串不会包含正确的 name()-s。但是有了你的解决方案,它就不会发生。谢谢你的回答!
  • @AdamHorvath Javadoc 明确指出,他们认为人们不太可能重命名枚举常量...参见Enum.name()。也就是说,如果您对此感到担心,可以使用toString() 而不是name(),当然这有其自身的风险。
  • 正确,应用合理。但在我们“疯狂”的公司中,我们广泛使用枚举。 toString() 变化更频繁,因为我们将人类可读的名称附加到它上面;像 JobType.S.toString() 是“样本”。如果您在列上指定 EnumType.STRING,那么它仍然可以管理。
  • 你可以要求所有的枚举都实现一个interface ImmutableName { String immutableName(); },它保证在IDE重构时不会改变......但是没有办法强制人们实现这个接口,也没有真正保证@ 987654345@ 不变。我现在正在修改我的答案。
猜你喜欢
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多