类型别名

时间:2016-08-29 10:55:35

标签: java android types annotations type-alias

只要我记得,我总是错过Java中的类型别名(例如c ++中的typedef或haskell中的type / newtype)。

在Android SDK中,我们有support annotations,其中包含@IntDef@StringDef和各种资源类型注释,这有助于我们在编译时找出可能滥用整数/字符串值的问题。我正在从Android文档中插入一段代码,为您提供简短的想法:

@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

实际上,95%我想要类型别名的情况有点相同:当我得到某种数据库行ID时,通常是longString,这导致必须对类型信息进行编码名称中的变量(例如long folderIdlong messageId)。但是,StringDef / IntDef注释存在恼人的限制:由于某种原因,它们需要一组预定义的常量,因此您只能描述一组有限的值,这显然不足以数据库标识符。

我想要的是某种类似的注释说@TypeAlias和Lint检查,所以我可以这样做:

@TypeAlias
@Retention(RetentionPolicy.SOURCE)
public @interface FolderId { }

@FolderId
public long getFolderIdByName(Database db, String name) {
    long id = db.foldersTable().findByName(name).getId();
    return id;
    /*
      we might need to suppress the check here
      (because we pass long as a @FolderId long),
      but that's okay, since we are aware of
      what we are doing here, and it's the only
      possible injection point for @FolderId
    */
}

public void deleteMessagesIn(Database db, @FolderId long folder) {
   // whatever
}

public void deleteMessagesInInbox(Database db) {
    deleteMessagesIn(db, 1); // rejected by Lint, trying to pass long as @FolderId long
    deleteMessagesIn(db, getFolderIdByName(db, "Inbox")); // ok, passes Lint check
}

我没有看到将类型别名注释限制为一组有限值的任何充分理由,我们可以通过如上所述的抑制来解决它,或者可能通过专门为提供类型别名的函数引入另一个注释来解决它。

更重要的是,这不仅限于Android注释的限制:任何普通的Java应用程序也可以从这些类型的别名中受益,而且我没有设法远程类似地谷歌。我们也可以从使用TYPE_PARAMETER目标中受益,这将使它看起来几乎像真正的类型别名。

所以问题是:

  • 是否有静态分析仪实施这些检查?
  • 如果没有,我是否有任何基本限制,以防止它被实施?再说一遍,我觉得这非常有用,所以如果没有,有人会这样做。

P.S。 @mernst将我指向Checker框架,我设法以相对无痛的方式将其与Android集成:https://github.com/karlicoss/checker-fenum-android-demo

1 个答案:

答案 0 :(得分:2)

检查类型别名(typedef)的正确使用的静态分析器是与Fake Enum Checker一起分发的Checker Framework。它已被用于查找Swing和JabRef中的错误。