【问题标题】:Using class annotations or static properties使用类注解或静态属性
【发布时间】:2013-07-23 10:16:04
【问题描述】:

我是 Java 新手,想了解这里的最佳实践。

假设我有一个通用类(例如Car)和一些共享某些属性的继承类(Honda、Subaru)。

public abstract class Car {
  public static short id;
}

public class Honda extends Car {
  public static final short id = 1;
}

public class Subaru extends Car {
  public static final short id = 2;
}

这不是违反 DRY 原则吗?那么使用注解呢?

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Id {
  public short value();
}

public abstract class Car {
}

@Id(1)
public class Honda extends Car {
}

@Id(2)
public class Subaru extends Car {
}

【问题讨论】:

  • 您的Car 既不是通用的,也不是您的其他类继承自它。
  • 您的课程已经有一个 ID。它们被称为Car、Honda 和Subaru。可以使用反射检索这些名称。您可能需要的唯一额外 ID 是 serialVersionUID,但它是特定于类实现的,因此不会违反 DRY 原则。
  • 请注意,您不能继承static 成员(字段和方法)。 (好吧,之前评论中的“您可能需要的唯一额外 ID”是夸大其词)
  • @RohitJain 我忘了扩展我的示例中的类,我的错。 @owlstead id 只是一个例子,可能是 nbSeats。另外,虽然我知道该示例由于继承了静态成员而应该失败,但它似乎运行得很好。我要问的是:我的用例可以使用注释吗?

标签: java annotations static-members


【解决方案1】:

这当然是一个品味问题。我不会向你推荐那个。 注释是元信息,用于标记字段、方法和类。 id(或 nbSeats)更像是一个字段而不是注释。

在你的情况下我更喜欢这个:

public abstract class Car {
  protected static short id;

  public static short getId() {
      return id;
  }
}

class Honda extends Car {
    static {
         id = 1;
    }
}

class Subaru extends Car {
    static {
         id = 2;
    }
}

编辑:抱歉:这个解决方案存在严重缺陷:-( Car、Honda 和 Subaru 共享相同的字段。 看看那个:

public static void main(String[] args) {
        new Honda();
        new Subaru();
        System.out.println(Honda.getId());
        System.out.println(Subaru.getId());
}

结果

2
2

我认为这个解决方案可能会更好:

public abstract class Car {
    protected abstract short id();

    public static short getIdOf(Class<? extends Car> carClass)
            throws InstantiationException, IllegalAccessException {
        return carClass.newInstance().id();
    }

    public static void main(String[] args) throws InstantiationException,
            IllegalAccessException {
        System.out.println(Car.getIdOf(Honda.class));
        System.out.println(Car.getIdOf(Subaru.class));
    }
}

class Honda extends Car {
    protected short id() {
        return 1;
    }
}

class Subaru extends Car {
    protected short id() {
        return 2;
    }
}

它有一些优点:

  • 它强制 Car 的每个具体子类都有一个 id(通过实现 id())。
  • 它将 Car 的子类隐藏到超类 Car
  • 编译器可以检查只有 Car 的子类被传递给 getIdOf()
  • 它强制类加载器加载类(静态初始化器仅在加载类时执行!)
  • 许多其他人

它有一些缺点:

  • 需要java反射
  • id() 方法是非静态的
  • 调用 id() 需要实例
  • 它要求所有子类中都有一个默认的公共构造函数
  • 您可以将抽象子类传递给 getIdOf()
  • 许多其他

注意注解的参数类型仅限于原始类型、String、Class、注解、枚举和一维数组!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-10
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-28
    相关资源
    最近更新 更多