IntelliJ为Java类创建自定义警告

时间:2016-01-21 01:30:59

标签: java intellij-idea

我创建了一个Either<A,B>类来表示和类型。每个实例都包含AB。这由扩展程序Left<A>Right<B>表示。这些类型对用户是隐藏的,仅用于存储对AB的引用,并在Either中实现抽象方法。这是代码的相关部分:

/**
 * 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());
  }

}

asLeft()asRight()的预期用途很简单,如下所示:

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

在我的其他项目中非常有用。

现在我的问题 - 我主要使用IntelliJ(并喜欢它),并注意到它有一个功能可以阻止你做可能出错的事情,例如将字符串与==进行比较。

Warning generated by IntelliJ when comparing strings with ==

是否可以为我的Either课程创建这样的自定义警告,以便在未事先检查Either::asLeft()的情况下调用Either::isLeft()会产生警告?假设IntelliJ(社区版)中有自定义警告功能,是否允许这种复杂性?

1 个答案:

答案 0 :(得分:0)

是的,理论上可以通过开发插件来实现。但是,在实践中,我建议不要这样做,因为实施此类检查可能需要付出很多努力。但是,您可以通过更改类来使用IntelliJ的空检查,并创建一个标记为getLeftOrNull()的方法@Nullable,并返回null而不是抛出异常。然后IntelliJ会警告你,如果你在解除引用之前没有检查null。

另一种选择是使用java 8 Optional并创建一个方法getLeftOptional(),该方法将包装返回值并强制调用者处理它为空时的情况(即Either是{{ 1}})。