简体   繁体   English

如何在java中摆脱过多的空值检查?

[英]How can I get rid of excessive null checking in java?

Suppose I have some code like this: 假设我有一些像这样的代码:

Vehicle vehicle = vehicleRepostory.findByIdInitialized(vehicleId);

If the Vehicle cannot be found this method will return null . 如果找不到Vehicle则此方法将返回null The specification says in this case I must throw a MyObjectNotFoundException so the code becomes something like this: 规范说在这种情况下我必须抛出一个MyObjectNotFoundException所以代码变成这样:

Vehicle vehicle = vehicleRepostory.findByIdInitialized(vehicleId);
MyObjectNotFoundException.throwIfNull(vehicle, Vehicle.class, vehicleId);

What can I do if I want to get rid of calls to throwIfNull . 如果我想摆脱对throwIfNull的调用,我该怎么办? It is not really DRY and a poor design choice anyway. 无论如何,它并不是真正的DRY和糟糕的设计选择。 There must be some design pattern unbeknownst to me. 必须有一些我不知道的设计模式。 I searched on the web but it did not turn up anything really usable. 我在网上搜索,但它没有发现任何真正有用的东西。

A straightforward solution might be putting the code into my Repository but I use SpringData for this so it is just an interface: 一个简单的解决方案可能是将代码放入我的存储库,但我使用SpringData,因此它只是一个接口:

public interface VehicleRepository extends Repository<Vehicle, Long>

// ...

@Query("select v from Vehicle v LEFT JOIN FETCH v.technicalData td LEFT JOIN FETCH v.registrationData rd"
    + " where v.vehicleId = ?")
Vehicle findByIdInitialized(Long vehicleId);

It sounds like basically you want your repository to support this: 听起来基本上你希望你的存储库支持这个:

Vehicle vehicle = vehicleRepository.loadExisting(vehicleId);

where the difference between loadExisting and findByIdInitialized would be that the former expects the entity to be present and will throw an a exception if it's not. loadExistingfindByIdInitialized之间的区别在于前者期望实体存在,如果不存在则抛出异常。

That way all repository clients can make a decision as to whether when they perform a lookup, they want the lack of an entity to result in an exception or not. 这样,所有存储库客户端都可以决定何时执行查找,他们是否希望缺少实体来导致异常。 You may even find that all lookups by ID should throw an exception - in which case you can go back to having a single method. 您甚至可能会发现ID的所有查找都会引发异常 - 在这种情况下,您可以返回使用单个方法。

EDIT: If the repository is autogenerated, I'd take one of three approaches: 编辑:如果存储库是自动生成的,我将采取以下三种方法之一:

  • Wrap it 包裹它
  • Extend it 扩展它
  • Modify the generator 修改生成器

Which of these choices would be most appropriate would depend on the exact details. 哪种选择最合适取决于具体细节。

You could look into @NotNull annotations in Java. 您可以在Java中查看@NotNull注释。 There are several flavours of it, some of them which do their validation compile-time and some of them at runtime. 它有几种风格,其中一些在编译时进行验证,其中一些在运行时进行。 Some editors (like IntelliJ IDEA) can warn you when you're doing an operation which could result in an NPE. 某些编辑器(如IntelliJ IDEA)可以在您进行可能导致NPE的操作时向您发出警告。

Which @NotNull Java annotation should I use? 我应该使用哪个@NotNull Java注释? Avoiding != null statements http://docs.oracle.com/javaee/6/api/javax/validation/constraints/NotNull.html 避免!= null语句 http://docs.oracle.com/javaee/6/api/javax/validation/constraints/NotNull.html

It would of course be best if you could redesign the repository itself to throw the exception you need. 如果您可以重新设计存储库本身以抛出所需的异常,那当然是最好的。 Without that, you need workarounds that patch the behavior. 没有它,您需要修补该行为的变通方法。

One approach would be reflection: wrap calls to repository in a method that receives findByIdInitialized as a string and calls it reflectively. 一种方法是反射:在一个方法中调用repository ,该方法接收findByIdInitialized作为字符串并反射调用它。 The method can then throw the appropriate exception. 然后该方法可以抛出适当的异常。

Another way could be to involve some AOP to do the same thing, but perhaps with more type safety. 另一种方法可能是让一些AOP做同样的事情,但也许有更多的类型安全。

I suggest that you add a nullable parameter to findByIdInitialized, and it will be like: 我建议你为findByIdInitialized添加一个可以为null的参数,它将是:

Vehicle findByIdInitialized(int vehicleId, boolean throwException) {
   // implementation behavior...

   if (throwException) {
       MyObjectNotFoundException.throwIfNull(vehicle, Vehicle.class, vehicleId);
   }
}

Use this: 用这个:

import static java.util.Objects.requireNonNull;

.
.
.

Object o = requireNonNull(obj);

听起来你想“在方法返回后”AOP建议,拦截空值并抛出异常。

You can use NullObject dessign pattern, but thwroing an exception IMHO is the best choice. 你可以使用NullObject dessign模式,但是提示异常恕我直言是最好的选择。

To keep in DRY, you should put that throw in findbyIdInitialized . 要保持DRY,你应该把它放在findbyIdInitialized

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM