是否有一些轻量级技术用于向标识符属性添加类型安全性?

时间:2010-05-24 09:33:46

标签: java generics

在使用C ++之后,我习惯了Identifier的概念,它可以与类的类一起使用,提供类型安全性并且没有运行时开销(实际大小是基元的大小)。我想做类似的事情,所以我不会犯错误:

personDao.find(book.getId());//I want compilation to fail  
personDao.find(book.getOwnerId());//I want compilation to succeed

我不喜欢可能的解决方案:

  1. 每个实体都有一个实体id类包装id原语。我不喜欢代码臃肿。
  2. 创建通用标识符类。像这样的代码将无法编译:

    void foo(Identifier<Book> book);
    void foo(Identifier<Person> person);

  3. 有谁知道更好的方法?
    有没有像这样的实用程序的库?
    实施这个是一种矫枉过正吗? 最重要的是,这可以在Java中完成而不需要像C ++那样的对象开销吗?

5 个答案:

答案 0 :(得分:2)

更多Java-equese和更正确的面向对象版本。

personDao.findByBookOwner(book);

在每个方法中,他们将提取他们需要的id。这是创建API的最主要的面向对象方式。

答案 1 :(得分:0)

当使用对象关系映射器(如hibernate)时,从数据库加载的(尚未)对象通常用延迟加载代理表示。这些实现了实际实体的接口,并在调用任何方法时从数据库透明地加载实体。

例如,可以按如下方式使用这些:

Person person = session.get(Person.class, someId);
Person spouse = person.getSpouse(); // proxy, unless configured otherwise

Task t = new TalkToSpouseTask(spouse);
session.save(t);

使用此代码,配偶不会从数据库加载。

  

最重要的是,这可以做到   在没有对象开销的Java中   比如C ++?

不,你总是用Java支付对象税(除非你使用基本类型,这不是类型安全的)。但是,我还没有看到业务应用程序的开销很重要。

答案 2 :(得分:0)

Java在尊重OO时非常严格,我认为没有任何等同于typedef,C ++似乎从C继承了。我能想到的唯一方法就是使用包装器。

至于:

void foo(Identifier<Book> book);
void foo(Identifier<Person> person);

它不起作用,因为泛型仅在编译器级别使用。它们在编译步骤后被删除,因此这两个函数都将成为:

void foo(Identifier param);

其中Identifier是原始类型(没有泛型),它们是无法区分的。

答案 3 :(得分:0)

简短的回答是否定的,如果你想要类型安全,你需要对象开销(如果可能的话,除了改变基元之外(例如,一个是浮点数,另一个是整数)。)

当您使用Java编程时,在重要之前不要担心对象开销 - 也就是当您看到分析实现的问题时。大多数情况下JIT摆脱了问题,或者开始时它不是问题。

有时它确实很重要,但不要过早地猜测过哪里 - 你很可能会错。

答案 4 :(得分:0)

我看到没有好办法做我想做的事。即使我使用类层次结构,我也必须手动将它与自动id生成器(如JPA注释)集成。太多的工作。只需要小心这一点。一个可能的解决方案是Annotation +检查,就像intellij对@Nullable和@NotNull所做的那样,但我不会自己实现这样的东西。