IntelliJ为Java类创建自定义警告

IntelliJ为Java类创建自定义警告,java,intellij-idea,Java,Intellij Idea,我也创建了一个 是否可以为我的other类创建这样的自定义警告,以便在不首先选中other::isLeft()的情况下调用other::asLeft()将生成警告?假设IntelliJ(社区版)中有自定义警告功能,它是否允许这种复杂性?是的,通过开发插件,理论上这是可能的。然而,实际上,我建议不要这样做,因为实施这种检查可能需要很多努力。但是,您可以通过更改类并创建一个方法getLeftOrNull()来利用IntelliJ的null检查,该方法将被标记为@Nullable,并将返回null而不

我也创建了一个


是否可以为我的
other
类创建这样的自定义警告,以便在不首先选中
other::isLeft()
的情况下调用
other::asLeft()
将生成警告?假设IntelliJ(社区版)中有自定义警告功能,它是否允许这种复杂性?

是的,通过开发插件,理论上这是可能的。然而,实际上,我建议不要这样做,因为实施这种检查可能需要很多努力。但是,您可以通过更改类并创建一个方法
getLeftOrNull()
来利用IntelliJ的null检查,该方法将被标记为
@Nullable
,并将返回null而不是引发异常。然后IntelliJ会警告您,如果您在取消引用之前没有检查null

另一个选项是使用java 8 Optional并创建一个方法
getLeftOptional()
,该方法将包装返回值,并在返回值为空时强制调用方处理大小写(即

/**
 * A simple SumType implementation. Allows the creation of the Sum Type
 * A + B. Every instance of Either is either (haha.. tomatoes, rocks)
 * an instance of Left, with a value of type A, or an instance of Right,
 * with a value of type B.
 * <br><br>
 * The types and constructors for Left and Right are not exposed.
 * Instead, to construct new instance of Left and Right, the createLeft and createRight
 * methods of class Either should be used.
 * <br><br>
 * The types can be the same, but in that case there isn't much use to using Either.
 *
 * @param <A> The first type to sum
 * @param <B> The second type to sum
 * @author Mshnik
 */
public abstract class Either<A, B> {

  private final boolean isLeft;

  /**
   * Constructs a new Either
   *
   * @param isLeft - true if this is a Left, false if this is a Right
   */
  Either(boolean isLeft) {
    this.isLeft = isLeft;
  }

  /** Creates a Either instance of the given A */
  public static <A, B> Either<A, B> createLeft(A a) {
    return new Left<>(a);
  }

  /** Creates a Either instance of the given B */
  public static <A, B> Either<A, B> createRight(B b) {
    return new Right<>(b);
  }

  /**
   * Returns true if this is a Left, false if this is a Right
   */
  public boolean isLeft() {
    return isLeft;
  }

  /**
   * Returns the value of this Either as an an instance of A.
   * If the wrapped value is an instance of B, throws a RuntimeException
   */
  public A asLeft() {
    if (isLeft())
      return ((Left<A,B>)this).getVal();
    throw new RuntimeException();
  }

  /**
   * Returns the value of this Either as an an instance of B.
   * If the wrapped value is an instance of A, throws a RuntimeException
   */
  public B asRight() {
    if (!isLeft())
      return ((Right<A,B>)this).getVal();
    throw new RuntimeException();
  }

  /**
   * Returns the Object stored within this Either.
   * Should have a stricter type bound (A or B) when implemented by subclasses.
   */
  public abstract Object getVal();

  /**
   * Returns the type of the Object stored within this Either
   */
  public abstract Class<?> getType();

  /**
   * Two Eithers are equal iff:
   * <br>- They are both Left or both Right, the only two direct subclasses
   * <br>- The objects they store are equivalent using Objects.equals.
   */
  @Override
  public boolean equals(Object o) {
    if(this == o) return true;
    if(o == null) return false;
    try {
      @SuppressWarnings("unchecked")
      Either<A, B> e = (Either<A, B>) o;
      return (!(isLeft ^ e.isLeft)) && Objects.equals(getVal(), e.getVal());
    } catch (ClassCastException e) {
      return false;
    }
  }

  /**
   * Hashes an either based on the value it stores.
   * This maintains the hash invariant (two equal objects have the same hashcode),
   * but is not a perfect hashcode because a Left(a) and Right(a) will have the
   * same hashcode but are not equivalent.
   */
  @Override
  public int hashCode() {
    return Objects.hashCode(getVal());
  }

}
Either<A,B> e = ....; //Take an either reference
if(e.isLeft()) {
    A a = e.asLeft();
    //Handle a
} else {
    B b = e.asRight();
    //Handle b
}