在使用C ++之后,我习惯了Identifier的概念,它可以与类的类一起使用,提供类型安全性并且没有运行时开销(实际大小是基元的大小)。我想做类似的事情,所以我不会犯错误:
personDao.find(book.getId());//I want compilation to fail
personDao.find(book.getOwnerId());//I want compilation to succeed
我不喜欢可能的解决方案:
创建通用标识符类。像这样的代码将无法编译:
void foo(Identifier<Book> book);
void foo(Identifier<Person> person);
有谁知道更好的方法?
有没有像这样的实用程序的库?
实施这个是一种矫枉过正吗?
最重要的是,这可以在Java中完成而不需要像C ++那样的对象开销吗?
答案 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所做的那样,但我不会自己实现这样的东西。