AutoValue_How do I...

我怎么...


这页回答公共的how-to问题,这些问题可能来自于AutoValue的使用过程中。你应该首先阅读并理AutoValue介绍 /(简单翻译)

具体builder option的使用单独一篇,在阅读这篇之前先阅读 AutoValue with builders /简单翻译

内容


我怎么...

  • 为我的value class 生成构建者
  • 内部类中使用AutoValue?
  • 使用(不使用)JavaBean样式的前缀
  • 使用nullable属性?
  • 属性验证
  • 使用复杂类型的属性?
  • 使用自定义的<code>equals</code>等等?
  • 在<code>equals</code>里面忽略明确的属性等等?
  • 含有多个Create方法,或给它命不同名?
  • AutoValue会实现那些超类的方法么?
  • 普通类上使用AutoValue?
  • 使我的类实现Java或者GWT序列化
  • 在生成的字段上面添加注解?
  • 让AutoValue实现注解类型
  • 包含setter(突变)方法?
  • 生成compareTo
  • 使用原始数组做为属性的值?
  • 使用Object 数组做为属性的值?
  • 使一个@AutoValue类继承另外一个?
  • 使访问器方法private
  • 暴露一个构造器而不是工厂方法作为创建的API?
  • 在接口上使用AutoValue而不是抽象类?

为我的value class 生成构建者

--
请查看AutoValue with builders。 /简单翻译

内部类中使用AutoValue?


AutoValue 的命名组成:<code>AutoValue_Outer_Middle_Inner</code>,在内部类中使用需要按照这种命名方式,<code>toString</code>方法只会输出简单类名。

class Outer {
    static class Middle {
        abstract static class Inner {
            static Inner create(String foo) {
                return new AutoValue_Outer_Middle_Inner(foo);
            }
        }
    }
}

使用(不使用)JavaBean样式的前缀


一些开发者更倾向于在访问器前面加<code>get-</code>或者<code>is</code>前缀,但是在构造器和<code>toString</code>中只使用属性名。

AutoValue will do exactly this, but only if you are using these prefixes consistently. In that case, it infers your intended property name by first stripping the get-
or is-
prefix, then adjusting the case of what remains as specified byIntrospector.decapitalize.

AutoValue会自动识别这些,但是你必选始终如一的使用这些前缀。在这种情况下AutoValue会剥离你的<code>get-</code>,<code>is</code>前缀,然后适应在Introspector.decapitalize规定的情况。

注意:为了保持与JavaBean的规范一致,<code>is</code>前缀只能使用在<code>boolean</code>返回值的方法,<code>get</code>前缀可以使用在返回值是任何类型的方法。

使用nullable属性?


一般情况下生成的构造器将拒绝所有的空值。如果你想接受空值,只需为访问方法的参数中添加一个<code>@Nullable</code>注解。这样AutoValue就会移除空检测并为<code>equals</code>,<code>hashCode</code>,<code>toString</code>方法处理空问题。例子:

@AutoValue
public abstract class Foo {
    public static Foo create (@Nullable Bar bar) {
        return new AutoValue_Foo(bar);
    }

    @Nullable abstract Bar bar();
}

这个例子也展示了在<code>create</code>方法中的中对应的参数添加<code>@Nullable</code>。AutoValue实际上不需要这个注解,它只用在访问器上,但是我们还是建议让它作为调用者有用的文档。

属性验证


空检查会被自动的添加,就像下面这样。对于其他类型的运行前检查只需要添加在你的工厂方法里面:

static MyType create(String first, String second) {
    checkArgument(!first.isEmpty());
    return new AutoValue_MyType(first, second.trim());
}

使用复杂类型的属性?


首先,检查是否这个复杂类型是否有对应的不可变复杂类型。例如,<code>List<String></code>和<code>String[]</code>对应Guava不可变类型是<code>ImmutableList<String></code>。如果这样使用不可变类型作为你的属性,并且只在构造时接收复杂类型:

@AutoValue
public abstract class ListExample {
    public static ListExample create (String [] mutableNames) {
        return new AutoValue_ListExample(ImmutableList.copyOf(mutableNames));
    }
    
    public abstract ImmutableList<String> names ();
}

注意:这是一个非常明智的做法,不是一个丑陋的实现方式!

如果没有合适的不可变类型使用,你需要处理警告。你的静态工厂需要给构造器传入一个参数的副本,你的访问器应该添加一个明显的注释绝对不要修改这个返回值。

@AutoValue
public abstract class Mutable Example {
    public static MutableExample create(MutablePropertyType ouch) {
        // Replace '.clone' below with the right copying code for this type
        return new AutoValue_MutableExammple(ouch.clone);
    }

    /**
     * Returns the ouch associated with this object;  <b>do not mutate </b> the
     * returned object.
     * /
    public abstract MutablePropertyType outh();
}

注意:这是一个一个丑陋的实现方式,不是明智的做法!

使用自定义的<code>equals</code>等等?

可以,AutoValue会识别这些并且跳过生成这些方法的代码。你写的代码逻辑会遗传到实现类,我们称它为underriding the method。

注意一旦你自定义这些方法你就失去了AutoValue的保护。记住下面这些关于hash code的基本规则:相同的对象的必须hash code一致,并且一致的hash code 也暗示相同的对象。你现在需要使用 guava-testlibEqualsTester
更透彻理想化的测试你的类。

最佳实践:标记你的俯冲方法(underriding methods)为 <code>final</code>类型来让以后阅读代码的人知道这些方法没有被AutoValue重写。

注意:如果俯冲方法(underriding methods)定义在抽象类的父类中也是起作用的,如果你想AutoValue重新覆盖这个方法,只需要在你的类中重新把这个方法设置为抽象就可以。

@AutoValue
class PleaseOverrideExample extends SuperclassThatDefinesToString {
    ...

    // cause AutoValue to generate this even though the superclass has it
    @Override public abstract String toString();
}

含有多个Create方法,或给它命不同名?

放心大胆的做!AutoValue 不关心这些。best practice item可能相关。

在<code>equals</code>里面忽略明确的属性等等?

假设你的value class有一个额外的字段不应该包含在<code>equals</code><code>hashCode</code>方法中。一个通常的原因是因为这个字段是一个其他属性的“缓存”或者派生值。这种情况下,你直接在你的抽象类里面定义就可以,AutoValue会直接忽略:

@AutoValue
abstract class DerivedExample {
    static DerivedExample create(String realProperty) {
        return new AutoValue_DerivedExample(realproperty);
    }

    abstract String realProperty;

    private String derviedProperty;

    final String dervedProperty() {
        // non-thread- safe Example
        if(derivedProperty == null) {
            derviedProperty = realProperty().toLowerCase();
        }
    }
}

另一方面,如果这个值是用户指定,不是派生的,这种情况稍微更复杂(但仍旧合理):

@AutoValue
abstract class IgnoreExample {
    static IgnoreExample create(String normalProperty, String ignoredProperty) {
        IgnoreExample ie = new AutoValue_IgnoreExample(normalProperty);
        ie.ignoredProperty = ignoreProperty;
        return ie;
    }

    abstract String normalProperty();

    private String ignoredProperty; // sadly, it can't be 'final'

    private String ignoredProperty() {
        return ignoredProperty;
    }
}

这两种情况的字段都会在<code>equals</code><code>hashCode</code><code>toString</code>方法中忽略,对AutoValue来说这个字段根本不存在。

AutoValue会实现那些超类的方法么?

AutoValue会注意到每个抽象访问器,无论他被定义在你的类还是超类中。

普通类上使用AutoValue?

There's nothing to it: just add type parameters to your class and to your call to the generated constructor.

没有什么不可以:只需要在你的类和生成的构造器中上添加类型参数

使我的类实现Java或者GWT序列化

只需要让你的类添加<code>implements Serializable</code>或者<code>@GwtCompatible(serializable = true)</code>注解(分别);这些信息(包括<code>serialVersionUID</code>)都会复制到生成类中。

在生成的字段上面添加注解?

目前还不支持;然而你抽象访问器上面的注解同样会出现在AutoValue生成的实现类上。

让AutoValue实现注解类型

大部分的用户都应该不需要通过编程生成假的注解实例,但是如果你有,使用<code>@AutoValue</code>将导致失败,因为<code>Annocation.hashCode</code>的规范和AutoValue的行为不兼容。
然而,我们无论如何也会满足你!假如注解是这样定义的:

public @interface Named {
    String value();
}

你需要做的只是这些:

public class Names {
    @AutoAnnatation public static Named named(String value) {
        return new AutoAnnotaion_Name_named(value);
    }
}

查看AutoAnnotation javadoc获取更多细节

包含setter(突变)方法?

不可以;AutoValue只生成不可变 value class;

Note that giving value semantics to a mutable type is widely considered a questionable practice in the first place. Equal instances of a value class are treated as interchangeable, but they can't truly be interchangeable if one might be mutated and the other not.

生成compareTo

AutoValue 有意不支持这个特性。使用Java8添加的Comparator
方法或者GuavaComparisonChain
方法根据实际的比较逻辑来实现会更好。

因为这些机制更易用,代码量小,更灵活,所以AutoValue没有必要提供。

使用原始数组做为属性的值?

请便!AutoValue会生成代码作用于存储在数组中的值,而不是数组对象本身,这正式你所需要的。注意 mutable properties.给出的警告信息。

使用Object 数组做为属性的值?

这是不允许的,Object数表现很差不像原始数组,它不能被一个恰当的<code>List</code>实现用较少的代码替换。

在构造期访问访问Object数表是很重要的,参考这里的第一个例子。

使一个@AutoValue类继承另外一个?

这个特性是有意不支持的,因为没有正确的实现方法。参看 Effective Java, 2nd Edition Item 8。

使访问器方法private

sorry!这是AutoValue几个不常见的限制你的API的方式之一。你的访问器方法可以不是public 的但至少要是包访问权限的。

暴露一个构造器而不是工厂方法作为创建的API?

sorry!这是AutoValue几个不常见的限制你的API的方式之一。然而Effective Java, Item 1相对于公共构造器更推荐静态工厂方法。

在接口上使用AutoValue而不是抽象类?

接口是不允许的,我们意识到接口的唯一好处就是你可以不用写<code>public abstract</code>。仅此而已,另一方面你将不能保证不可变性,而且会导致坏的行为(描述在最佳实践)。总的来说,我们认为这是不值得的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容