在Java
中通常定义一个模型类时,需要定义一堆不同类型的成员变量,而且为了满足面向对象的基本特征,又要定义一堆相应的Getter
和Setter
等方法,这个过程是非常枯燥的要写一堆样板代码。虽然现在 IDE 可以很好的帮我们生成这些样板代码,但是如果看到一个模型类里面有这么一堆的方法,总觉是会觉得不够清晰。
我只想知道这个模型有哪些属性,以及特殊的方法,并不想知道大家都有的东西,你却非要让我看。。。
好了,现在有办法可以解决这个问题了,使用 Google 开源的 AutoValue 就可以解决上述烦恼,而且最近AutoValue
项目支持了大家期待已久的Extension API
,使得AutoValue
更加灵活,至于这个Extension API
是干啥的后面会讲到,现在暂时不用去关心他。
普通的 Java 模型
我们这里举个故事(Story)的例子,一个故事模型拥有一个id
,以及一个title
。下面我们来看下用Java
代码来表示该模型的写法。
不太严谨的写法
我们先来看下一般情况下我们是怎么定义这个 POJO 的业务模型的。
public class Story{
public int id;
public String title;
}
上面的写法非常简单,不过有些情况下可能会有问题,比如对象比较时,而且也不符合封装的要求,不过一般情况下业务逻辑简单,还处在快速迭代的时候这样写也没什么问题,而且重点是他 只有4行代码!
比较规范的写法
下面看下正常情况下的写法:
public class Story{
private int id;
private String title;
public Story(int id, String title){
this.id = id;
this.title = title;
}
public int id(){
return this.id;
}
public int title(){
return this.title;
}
}
这样写符合了面向对象的基本特征封装
的要求,但是如果这个Story
是在列表或者集合中有用到比较的时候,这么写是有问题的,应该继续覆盖hashCode()
和equals()
方法,如果有特殊格式的输出,还得覆盖toString()
方法。
把这些东西都补全的写法如下:
public class Story{
private int id;
private String title;
public Story(int id, String title){
this.id = id;
this.title = title;
}
public int id(){
return this.id;
}
public int title(){
return this.title;
}
@Override
public String toString(){
return id + title;
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.id;
hash = 31 * hash + (null == title ? 0 : title.hashCode());
return hash;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Stroy)) return false;
Story s = (Story) o;
if (s.id != s.id) return false;
return s.title.equals(s.title);
}
}
上面的版本是一个比较完整的模型写法,相比起最初的版本,代码多了不少从原来的4
行变成了现在的39
行!
OMG!现在的版本还没有实现Parcelable
接口,如果再在他的基础上实现Parcelable
接口,那代码又得增加十几行,想想都心累啊。
使用AutoValue拯救你的代码
我本想要一个只有几行的模型类,但是出于各方面原因,我得到了一个几十行代码的模型类,为了解决这个问题伟大的Google
开发了AutoValue
这个库来自动生成这些样板代码,解放我们的双手,让我们把更多的精力放在更重要的事情上。
使用AutoValue
使用方法很简单,只需要在你的项目中引入AutoValue
的插件即可
dependencies {
apt 'com.google.auto.value:auto-value:1.2'
}
然后在代码中使用@AutoValue
注解来指定哪个类需要生成类似于上面的样板代码。下面我们使用AutoValue
来重新实现一下Story
模型。
@AutoValue
public abstract class Story{
public abstract int id();
public abstract String title();
}
使用@AutoValue
注解后,AutoValue
会生成一个AutoValue_你的类名
为名称的类,这个类是包级私有
的,他里面有私有的成员变量,对应的构造函数,以及重写的hashCode()
、equals()
和toString()
方法,而且这些方法都是被测试过的确保无误的,你可以放心的使用。由于这个生成的子类是包级私有
的,所以这里在给Story
提供构造方法的时候需要提供一个静态的构造方法,代码如下:
@AutoValue
public abstract class Story{
public abstract int id();
public abstract String title();
public static Story create(int id, String title){
new AutoValue_Story(id,title);
}
}
好了,使用AutoValue后,这短短几行代码就完成了上面几十行代码干的事,而且这样生成出来的代码都是被测试过准确无误的,这也避免了一些因为手误或者逻辑错误导致的BUG的产生,是不是很爽?必须很爽啊!
But... 我们要更爽一点!
AutoValue Extension API
大家注意到没有上面使用AutoValue
实现的Story
模型并没有实现Parcelable
接口,那如果要实现这个接口是不是又得一堆代码呢?当然不会,因为我们有Extension API
,因为有了他我们可以使用基于他实现出来的AutoValue: Parcel Extension来实现Parcelable
接口。
使用 Parcel Extension 实现 Parcelable 接口
首先我们需要在项目中集成 AutoValue Parcel Extension
dependencies {
provided 'com.google.auto.value:auto-value:1.2'
apt 'com.google.auto.value:auto-value:1.2'
apt 'com.ryanharter.auto.value:auto-value-parcel:0.2.1'
}
然后再在代码中加入implements Parcelable
即可
@AutoValue
public abstract class Story implements Parcelable{
public abstract int id();
public abstract String title();
public static Story create(int id, String title){
new AutoValue_Story(id,title);
}
}
是不是已经体会到了AutoValue Extension
的厉害了?反正我是觉得碉堡了!
有了这个扩展功能,能干的事情就多了,常规的像对象序列化成 JSON 字符串,将 JSON 字符串解析成对象等这些事情就不用自己再去动手去写了,直接用AutoValue
生成就可以了,再也不用去写那些toJson()
和fromJson
之类的方法了,真是爽歪歪啊!
更多的 AutoValue Extension
目前已经有人实现了一些 AutoValue 的扩展了,具体的可以看这里。如果这些都无法满足你的需求,那你可以使用 AutoValue Extension API
去自己实现一个 AutoValue 的扩展。
网友评论
这句话编译器不认识 咋办,有人说rebuild一下就行。但是我的没成功