Java:类型别名支持注释处理工具(APT)?

时间:2014-11-27 07:41:38

标签: java type-safety annotation-processing type-alias

我从未使用过类型别名,但是这个概念似乎是一个非常有用的功能,它可以在相同类型的对象上添加语义并防止常见的拼写错误。

我们说,有void foo(float volume, float weight)。如果它被调用的话可以这样做:foo(v, m),但foo(m, v)不是一个明显的拼写错误。 void process(Iterable<File> javaPath, Iterable<File> classPath)可以是另一个用例。不幸的是,Java中没有类型别名,并且一些解决方法是真正的过度杀伤:

  • 将单个字段聚合到一个类中(将一个基元装入一个对象;一个具有额外引用的对象中的对象;更复杂的序列化/反序列化规则)
  • 从另一个类扩展一个类(如how do i create some variable type alias in Java - 基元不可能;类可能是最终的或具有不可访问的构造函数)。

因此,它们都有缺点和运行时间/性能成本。

据我所知,在Java中,基于运行时的&#34;类型别名&#34;可能会被编译时检查所取代,例如@NotNull和@Nullable被处理。是否有任何静态类型别名检查器/ APT工具支持void foo(@Volume float volume, @Weight float weight)之类的结构,以便检查器可以验证这样的&#34;类型安全&#34;在编译时,需要传递变量/常量和文字进行注释(分别在声明和调用站点)?


这个问题也有人提出,因为我目前正在研究一种可以使用多个后端的Java源代码处理工具(目前只有JDT)。只要我希望它与JDT无关,我想拥有类型,方法和字段的业务对象。尽管如此,我丢失了大量来自JDT AST的信息,我工具当前最好的方法是使用字符串(它允许执行一些对工具范围足够的分析)。但是像void process(String type, String field, String method)这样的方法令人困惑,因此我创建了代表域对象的TypeFieldMethod,并且与JDT无关。它们很好,但我不希望将来扩展它们(所有这三种类型都有单private final String name;字段+我必须覆盖hashCode/equals和{{1 }})。这让我想到再次对APT进行类型检查。只要处理原始数据是可以的,只需toString(我仍然可以使用单个对象)就足够了。

1 个答案:

答案 0 :(得分:0)

如果您的问题是,当您致电foo(v,m)时,人们可能会在没有任何警告或可见的错误线索的情况下错误地写foo(m,v)时看起来很模糊,您可以使用类似流利的建设者模式:

(代码未经过测试,只是为了证明这个想法而编写)

public class MyClass {
    public class FooStub {
        int volume;
        int weight;
        public FooStub withVolume(int v) {
            this.volume = v;
            return this;
        }
        public FooStub withWeight(int w) {
            this.weight = w;
            return this;
        }
        public int run() {   // or call it getResult() or whatever you want
            Assert.notNull(volume);
            Assert.notNull(weight);
            return foo(volume,weight);  // calling method of outer class
        }
    }

    public int foo(int volume, int weight) {   // you even hide this if you want
        return volume * weight;
    }
    public FooStub foo() {
        return new FooStub();
    }

}

通过这样做,来电者可以

MyClass myObj = ....;
int result = myObj.foo().withVolume(a).withWeight(b).run();
// which is the same as result = myObject.foo(a,b);