AutoValue
AutoValue ์ ์ฉํด๋ณด๊ธฐ
AutoValue๋ ์ฝ๋ ์๋ ์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์๋ฐ ์ฝ๋๋ฅผ ์ค์ผ ์ ์์ผ๋ฉฐ, AutoValue๋ Reflection์ ์ด์ฉํ ๋ฐํ์ ๋ฐฉ์์ด ์๋ apt๋ฅผ ์ด์ฉํ์ฌ ์ปดํ์ผ ํ์์ ์ฝ๋๋ฅผ ์์ฑํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์์ ๋ถ์ด์ต์ ์๋ค.
google AutoValue์์ jarํ์ผ์ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์๋ค.
๋ง์ฝ maven์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ pom.xml
์ dependency๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
<dependencies>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
<version>1.3</version>
</dependency>
</dependencies>

๋ค์ด๋ก๋ ๋ฐ์ jarํ์ผ์ intellij project settings > Libraries์ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
์ฐ์ @AutoValue
๋ฅผ ์ดํด๋ณด๋ฉด, ๋ด๋ถ์ ์์์ ํจ๊ป AutoValue github ์ฃผ์๋ฅผ ์๋ ค์ฃผ๊ณ ์๋ค.
/**
* Specifies that <a href="https://github.com/google/auto/tree/master/value">AutoValue</a> should
* generate an implementation class for the annotated abstract class, implementing the standard
* {@link Object} methods like {@link Object#equals equals} to have conventional value semantics. A
* simple example: <pre>
*
* @AutoValue
* abstract class Person {
* static Person create(String name, int id) {
* return new AutoValue_Person(name, id);
* }
*
* abstract String name();
* abstract int id();
* }</pre>
*
* @see <a href="https://github.com/google/auto/tree/master/value">AutoValue User's Guide</a>
*
* @author รamonn McManus
* @author Kevin Bourrillion
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface AutoValue {
/**
* Specifies that AutoValue should generate an implementation of the annotated class or interface,
* to serve as a <i>builder</i> for the value-type class it is nested within. As a simple example,
* here is an alternative way to write the {@code Person} class mentioned in the {@link AutoValue}
* example: <pre>
*
* @AutoValue
* abstract class Person {
* static Builder builder() {
* return new AutoValue_Person.Builder();
* }
*
* abstract String name();
* abstract int id();
*
* @AutoValue.Builder
* interface Builder {
* Builder name(String x);
* Builder id(int x);
* Person build();
* }
* }</pre>
*
* @author รamonn McManus
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Builder {}
/**
* Specifies that AutoValue should copy any annotations from the annotated element to the
* generated class. This annotation supports classes and methods.
*
* <p>The following annotations are excluded:
*
* <ol>
* <li>AutoValue and its nested annotations;
* <li>any annotation appearing in the {@link AutoValue.CopyAnnotations#exclude} field;
* <li>any class annotation which is itself annotated with the
* {@link java.lang.annotation.Inherited} meta-annotation.
* </ol>
*
* <p>When the <i>type</i> of an {@code @AutoValue} property method has annotations, those are
* part of the type, so they are always copied to the implementation of the method.
* {@code @CopyAnnotations} has no effect here. For example, suppose {@code @Confidential} is a
* {@link java.lang.annotation.ElementType#TYPE_USE TYPE_USE} annotation: <pre>
*
* @AutoValue
* abstract class Person {
* static Person create(@Confidential String name, int id) {
* return new AutoValue_Person(name, id);
* }
*
* abstract @Confidential String name();
* abstract int id();
* }</pre>
*
* Then the implementation of the {@code name()} method will also have return type
* {@code @Confidential String}.
*
* @author Carmi Grushko
*/
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface CopyAnnotations {
Class<? extends Annotation>[] exclude() default {};
}
}
๊ฐ์ด๋๋ผ์ธ์ ๊ธฐ์ค์ผ๋ก ํด๋์ค ํ๊ฐ๋ฅผ ์์ฑํด ๋ณผ ๊ฒ์ด๋ค.
@AutoValue
public abstract class Product {
public abstract String name();
public abstract BigDecimal price();
@AutoValue.Builder
public abstract static class Builder{
public abstract Builder name(String name);
public abstract Builder price(BigDecimal price);
public abstract Product build();
}
public static Product.Builder builder(){
return new AutoValue_Product.Builder();
}
}

AutoValue ์ด๋ ธํ ์ด์ ์ ์ค์ ํ์ง ์์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.

Compiler > Annotation Processors์์ Enable annotation processing์ ์ฒดํฌํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ modules์ dependencies์ auto-value ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํฌํจ๋์ด์์ง ์๋ค๋ฉด ๋ณ๋๋ก ์ถ๊ฐํด์ค์ผํ๋ค.

๋ชจ๋ ์ถ๊ฐํ ๋ค์ project rebuild๋ฅผ ํ๋ฉด AutoValue_Product๊ฐ ์์ฑ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.

๋ค์ ์ฝ๋๋ฅผ ํ๋ํ๋ ์ง์ด๋ณผ ๊ฒ์ด๋ค.
@AutoValue
public abstract class Product {
public abstract String name();
public abstract BigDecimal price();
@AutoValue.Builder
public abstract static class Builder{
public abstract Builder name(String name);
public abstract Builder price(BigDecimal price);
public abstract Product build();
}
public static Product.Builder builder(){
return new AutoValue_Product.Builder();
}
}
@AutoValue
๋ฅผ ์ฌ์ฉํ๋ ํด๋์ค๋ abstract(์ถ์) ํด๋์ค์ด๋ฉฐ, ์ค์ ๋ก ๊ตฌํํ๋ ํด๋์ค๋ builder() ๋ถ๋ถ์AutoValue_Product
์ด๋ค.์์ ํด๋์ค ๋ฉค๋ฒ ๋ณ์๋ abstract ์ถ์ํจ์๋ก ์ ์ธ๋์ด์๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๋ค์๊ณผ ๊ฐ์ด ์ ์ธํด์ฃผ๋ฉด
AutoValue_Product
ํด๋์ค์ ๋ณ์๊ฐ ์์ฑ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
import java.math.BigDecimal;
final class AutoValue_Product extends Product {
private final String name;
private final BigDecimal price;
private AutoValue_Product(String name, BigDecimal price) {
this.name = name;
this.price = price;
}
public String name() {
return this.name;
}
public BigDecimal price() {
return this.price;
}
public String toString() {
return "Product{name=" + this.name + ", price=" + this.price + "}";
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Product)) {
return false;
} else {
Product that = (Product)o;
return this.name.equals(that.name()) && this.price.equals(that.price());
}
}
public int hashCode() {
int h = 1;
int h = h * 1000003;
h ^= this.name.hashCode();
h *= 1000003;
h ^= this.price.hashCode();
return h;
}
static final class Builder extends ch3.dahye.item11.Product.Builder {
private String name;
private BigDecimal price;
Builder() {
}
public ch3.dahye.item11.Product.Builder name(String name) {
if (name == null) {
throw new NullPointerException("Null name");
} else {
this.name = name;
return this;
}
}
public ch3.dahye.item11.Product.Builder price(BigDecimal price) {
if (price == null) {
throw new NullPointerException("Null price");
} else {
this.price = price;
return this;
}
}
public Product build() {
String missing = "";
if (this.name == null) {
missing = missing + " name";
}
if (this.price == null) {
missing = missing + " price";
}
if (!missing.isEmpty()) {
throw new IllegalStateException("Missing required properties:" + missing);
} else {
return new AutoValue_Product(this.name, this.price);
}
}
}
}
public class item11 {
public static void main(String[] args) {
Product product = Product.builder().price(new BigDecimal(990000)).name("autoValue").build();
System.out.println(product); // Product{name=autoValue, price=990000}
}
}

๋ค์๊ณผ ๊ฐ์ด Product ํด๋์ค๋ฅผ builder๋ก ์์ฑํ๋ฉด, AutoValue_Product
์ธ์คํด์ค๋ก ์์ฑ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. AutoValue๋ ๋ถ๋ณ์ ๋ณด(Immutable)๋ฅผ ์ ๋ฌํ๋ ํด๋์ค ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ ์ฌ์ฉํ ์ ์๋ค. AutoValue_Product
๋ฅผ ๋ณด๋ฉด final
ํด๋์ค์ด๋ฉด์ ๋ณ์๋ final
์ธ ๊ฒ์ ๋ณผ ์ ์๋ค. ๊ทธ๋ฌ๋ฏ๋ก, AutoValue
๋ ๋ฉค๋ฒ ๋ณ์ ๊ฐ์ด ํญ์ ๋ฐ๋ ์ ์๋ ์ธ์คํด์ค์์๋ ์ฌ์ฉํ๋ฉด ์๋๋ค.
์ฐธ์กฐ
Last updated
Was this helpful?