类 对包私有构造函数和通过 Guice 实例化的相应对象的积极副作用?

Positive side effect of classes with package-private constructors and the corresponding objects instantiated via Guice?

想知道这是否是 Guice 实例化对象的包私有构造函数的副作用。

我有一个 class 看起来像

class Foo { //note the access specifier

 private Bar1 iCannotBeNull;
 private Bar2 iCannotBeNullEither;  

 @Inject
 Foo(Bar1 bar1, Bar2 bar2) {//note the access specifier
      this.iCannotBeNull = Objects.requireNonNull(bar1, "null injected");
      this.iCannotBeNullEither = Objects.requireNonNull(bar2, "null injected");
  }   

}

按照 https://github.com/google/guice/wiki/UseNullable,看起来我可以在技术上摆脱空检查,因为我通过包私有构造函数(当然还有位于同一包中的 Guice 模块)确保 Foo 的对象是仅由 Guice 创建,Guice 永远不会注入 null。

@Inject
 Foo(Bar1 bar1, Bar2 bar2) {//note the access specifier
      this.iCannotBeNull = bar1;
      this.iCannotBeNullEither = bar2;
  }   

我的理解是否正确,还是我忽略了这里非常明显的东西?

不,你不应该去掉空检查,因为正如它所说,检查代表一般,与 Guice 无关, 快速失败机制:

Preconditions.checkNotNull can be used to fast-fail if a null reference is found, <…>

UseNullable · google/guice Wiki · GitHub.

另外,Guice 有它的特定机制 使用适当的注解来处理可空和不可空的依赖关系:

Guice forbids null by default. It will refuse to inject null, failing with a ProvisionException instead. If null is permissible by your class, you can annotate the field or parameter with @Nullable. Guice recognizes any @Nullable annotation, like edu.umd.cs.findbugs.annotations.Nullable or javax.annotation.Nullable.

UseNullable · google/guice Wiki · GitHub.

Google 的敏捷教练 Miško Hevery 声称,这些 checkNotNull 断言略微抑制了 this blog 中的测试。

例如,对于测试不关心的依赖项,传入 null 通常很有用:

testSecureHouse() {
  Door door = new Door();
  Window window = new Window();
  House house = new House(door, window,
             null, null, null, null);

  house.secure();

  assertTrue(door.isLocked());
  assertTrue(window.isClosed());
}

如果您订阅此视图,checkNotNull 的替代方法是使用 @Nullable@NonNull@ParametersAreNonnullByDefault 注释:

@Inject
Foo(@NonNull Bar1 bar1, @NonNull Bar2 bar2) {
    //
}  

如果您这样做,当开发人员试图将 null 传递给 Foo 的 ctor 时,大多数 IDE 或 lint 检查都会发出警告。

但总的来说,您似乎必须在方便性和开发人员通过传入 null 犯错的风险之间取得平衡。由于您已经很好地组织了您的包并且正在使用访问修饰符来防止意外使用,因此您的特定情况的风险(包私有构造函数将仅由 Guice 模块调用)似乎很低。

如果你的 Foo class 是 public API 的一部分,这将是完全不同的, class 肯定会从断言中受益,并且快速失败。