通过注解的方式,在编译时生成代码

类型推导

val

不可变,相当于加了 final

val str = "Hello World";

等价于

final String str = "Hello World";

如果尝试修改

val str = "Hello World";
str = "Hello World ~";

会报错

error: cannot assign a value to final variable str

var

仅类型推导,可变

注解

@NonNull

private void test(@NonNull String str) {
    System.out.println(str);
}

编译后

private void test(@NonNull String str) {
    if (str == null) {
        throw new NullPointerException("str is marked @NonNull but is null");
    } else {
        System.out.println(str);
    }
}

@Cleanup

自动化关闭流

private void test(String inputFile, String outputFile) throws Exception {
    @Cleanup val in = new FileInputStream(inputFile);
    @Cleanup val out = new FileOutputStream(outputFile);
    byte[] b = new byte[10000];
    while (true) {
        int r = in.read(b);
        if (r == -1) break;
        out.write(b, 0, r);
    }
}

编译后

private void test(String inputFile, String outputFile) throws Exception {
    FileInputStream in = new FileInputStream(inputFile);
    try {
        FileOutputStream out = new FileOutputStream(outputFile);
        try {
            byte[] b = new byte[10000];
            while(true) {
                int r = in.read(b);
                if (r == -1) {
                    return;
                }
                out.write(b, 0, r);
            }
        } finally {
            if (Collections.singletonList(out).get(0) != null) {
                out.close();
            }
        }
    } finally {
        if (Collections.singletonList(in).get(0) != null) {
            in.close();
        }
    }
}

只有对象中有 clese() 方法就可以用 @Cleanup

@Getter/@Setter

自动添加 set get 方法

在类上添加

@Setter
@Getter
public class Student {
    private String name;
    private int age;
}

编译后

public class Student {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return this.name;
    }
    public int getAge() {
        return this.age;
    }
}

也可以在单独的属性上加

public class Student {
    @Getter
    private String name;
    @Setter(AccessLevel.PROTECTED)
    private int age;
}

编译后

public class Student {
    private String name;
    private int age;

    public String getName() {
        return this.name;
    }
    protected void setAge(int age) {
        this.age = age;
    }
}

@ToString

@ToString
public class Student {
    private String name;
    
    //排除age属性
    @ToString.Exclude
    private int age;
}

编译后

public class Student {
    private String name;
    private int age;

    public String toString() {
        return "T.Student(name=" + this.name + ")";
    }
}

其他选项:

callSuper: 是否调用父类的 toString()

includeFieldNames: toString()是否包含属性的名字

@EqualsAndHashCode

@EqualsAndHashCode
public class Student {
    private String name;
    private int age;
    private Family family;
}

编译后

public class Student {
    private String name;
    private int age;
    private Family family;
    
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Student)) {
            return false;
        } else {
            Student other = (Student)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label39: {
                    Object this$name = this.name;
                    Object other$name = other.name;
                    if (this$name == null) {
                        if (other$name == null) {
                            break label39;
                        }
                    } else if (this$name.equals(other$name)) {
                        break label39;
                    }
                    return false;
                }
                if (this.age != other.age) {
                    return false;
                } else {
                    Object this$family = this.family;
                    Object other$family = other.family;
                    if (this$family == null) {
                        if (other$family != null) {
                            return false;
                        }
                    } else if (!this$family.equals(other$family)) {
                        return false;
                    }
                    return true;
                }
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Student;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $name = this.name;
        int result = result * 59 + ($name == null ? 43 : $name.hashCode());
        result = result * 59 + this.age;
        Object $family = this.family;
        result = result * 59 + ($family == null ? 43 : $family.hashCode());
        return result;
    }
}

构造方法

@NoArgsConstructor

无参数

@RequiredArgsConstructor

构造方法里的参数是@Nonnull的属性

@RequiredArgsConstructor(staticName = "of")
public class Student {
    @NonNull
    private String name;
    private int age;
    @NonNull
    private Family family;
}

编译后

public class Student {
    @NonNull
    private String name;
    private int age;
    @NonNull
    private Family family;

    private Student(@NonNull String name, @NonNull Family family) {
        if (name == null) {
            throw new NullPointerException("name is marked @NonNull but is null");
        } else if (family == null) {
            throw new NullPointerException("family is marked @NonNull but is null");
        } else {
            this.name = name;
            this.family = family;
        }
    }

    public static Student of(@NonNull String name, @NonNull Family family) {
        return new Student(name, family);
    }
}

@AllArgsConstructor

参数是所有属性

@Data

多个注解的汇总,适用于属性可变的数据类

@ToString

@EqualsAndHashCode

所有属性的 @Getter

非 final 属性的 @Setter

@RequiredArgsConstructor

@Data
public class Point {
    private float x;
    private float y;
    private float z;
}

编译后

public class Point {
    private float x;
    private float y;
    private float z;

    public float getX() {
        return this.x;
    }

    public float getY() {
        return this.y;
    }

    public float getZ() {
        return this.z;
    }

    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }

    public void setZ(float z) {
        this.z = z;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Point)) {
            return false;
        } else {
            Point other = (Point)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (Float.compare(this.getX(), other.getX()) != 0) {
                return false;
            } else if (Float.compare(this.getY(), other.getY()) != 0) {
                return false;
            } else {
                return Float.compare(this.getZ(), other.getZ()) == 0;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Point;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + Float.floatToIntBits(this.getX());
        result = result * 59 + Float.floatToIntBits(this.getY());
        result = result * 59 + Float.floatToIntBits(this.getZ());
        return result;
    }

    public String toString() {
        return "Point(x=" + this.getX() + ", y=" + this.getY() + ", z=" + this.getZ() + ")";
    }
}

@Value

多个注解的汇总,适用于属性不可变的数据类

@ToString

@EqualsAndHashCode

@AllArgsConstructor

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)

@Getter

@Value
public class Point {
    private float x;
    private float y;
    private float z;
}

编译后

public final class Point {
    private final float x;
    private final float y;
    private final float z;

    public Point(float x, float y, float z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public float getX() {
        return this.x;
    }

    public float getY() {
        return this.y;
    }

    public float getZ() {
        return this.z;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Point)) {
            return false;
        } else {
            Point other = (Point)o;
            if (Float.compare(this.getX(), other.getX()) != 0) {
                return false;
            } else if (Float.compare(this.getY(), other.getY()) != 0) {
                return false;
            } else {
                return Float.compare(this.getZ(), other.getZ()) == 0;
            }
        }
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + Float.floatToIntBits(this.getX());
        result = result * 59 + Float.floatToIntBits(this.getY());
        result = result * 59 + Float.floatToIntBits(this.getZ());
        return result;
    }

    public String toString() {
        return "Point(x=" + this.getX() + ", y=" + this.getY() + ", z=" + this.getZ() + ")";
    }
}

@Builder

builder 模式构建对象

@Builder
public class Student {
    private String name;
    private int age;
    @Singular
    private List<Float> scores;
}

编译后

public class Student {
    private String name;
    private int age;
    private List<Float> scores;

    Student(String name, int age, List<Float> scores) {
        this.name = name;
        this.age = age;
        this.scores = scores;
    }

    public static Student.StudentBuilder builder() {
        return new Student.StudentBuilder();
    }

    public static class StudentBuilder {
        private String name;
        private int age;
        private ArrayList<Float> scores;

        public Student.StudentBuilder name(String name) {
            this.name = name;
            return this;
        }

        public Student.StudentBuilder age(int age) {
            this.age = age;
            return this;
        }

        public Student.StudentBuilder score(Float score) {
            if (this.scores == null) {
                this.scores = new ArrayList();
            }

            this.scores.add(score);
            return this;
        }

        public Student.StudentBuilder scores(Collection<? extends Float> scores) {
            if (this.scores == null) {
                this.scores = new ArrayList();
            }

            this.scores.addAll(scores);
            return this;
        }

        public Student.StudentBuilder clearScores() {
            if (this.scores != null) {
                this.scores.clear();
            }

            return this;
        }

        public Student build() {
            List scores;
            switch(this.scores == null ? 0 : this.scores.size()) {
            case 0:
                scores = Collections.emptyList();
                break;
            case 1:
                scores = Collections.singletonList(this.scores.get(0));
                break;
            default:
                scores = Collections.unmodifiableList(new ArrayList(this.scores));
            }

            return new Student(this.name, this.age, scores);
        }

        public String toString() {
            return "Student.StudentBuilder(name=" + this.name + ", age=" + this.age + ", scores=" + this.scores + ")";
        }
    }
}

调用时

Student.builder()
        .age(20)
        .name("Victor")
        .score(100f)
        .scores(Arrays.asList(90f,80f))
        .build();

@SneakyThrows

抛出异常时,在当前方法上调用,不用显示的在方法名后面写 throw

private String test(byte[] bytes) throws UnsupportedEncodingException {
    return new String(bytes, "GBK");
}

使用注解

@SneakyThrows(UnsupportedEncodingException.class)
private String test(byte[] bytes) {
    return new String(bytes, "GBK");
}

编译后

private String test(byte[] bytes) {
    try {
        return new String(bytes, "GBK");
    } catch (UnsupportedEncodingException var3) {
        throw var3;
    }
}

@Synchronized

自动加锁,不建议使用

public class T {
    private final Object lock = new Object();

    @Synchronized
    public static void test() {
        System.out.println("test");
    }

    @Synchronized
    public int test2() {
        return 20;
    }

    @Synchronized("lock")
    public void test3() {
        System.out.println("test2");
    }
}

编译后

public class T {
    private static final Object $LOCK = new Object[0];
    private final Object $lock = new Object[0];
    private final Object lock = new Object();

    public static void test() {
        synchronized($LOCK) {
            System.out.println("test");
        }
    }

    public int test2() {
        synchronized(this.$lock) {
            return 20;
        }
    }

    public void test3() {
        synchronized(this.lock) {
            System.out.println("test2");
        }
    }
}

@Getter(lazy=true)

懒加载

public class T {
    @Getter(lazy = true)
    private final double[] cached = expensive();

    private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
            result[i] = Math.asin(i);
        }
        return result;
    }
}

编译后

public class T {
    private final AtomicReference<Object> cached = new AtomicReference();

    private double[] expensive() {
        double[] result = new double[1000000];
        for(int i = 0; i < result.length; ++i) {
            result[i] = Math.asin((double)i);
        }
        return result;
    }

    public double[] getCached() {
        Object value = this.cached.get();
        if (value == null) {
            synchronized(this.cached) {
                value = this.cached.get();
                if (value == null) {
                    double[] actualValue = this.expensive();
                    value = actualValue == null ? this.cached : actualValue;
                    this.cached.set(value);
                }
            }
        }
        return (double[])(value == this.cached ? null : value));
    }
}

Log

包含常用的日志工具类

@CommonsLog

org.apache.commons.logging.Log

@Flogger

com.google.common.flogger.FluentLogger

@JBossLog

org.jboss.logging.Logger

@Log

java.util.logging.Logger

@Log4j

org.apache.log4j.Logger

@Log4j2

org.apache.logging.log4j.Logger

@Slf4j

org.slf4j.Logger

@XSlf4j

org.slf4j.ext.XLogger

@Slf4j
public class T {
    private void test() {
        log.info("test");
    }
}

编译后

public class T {
    private static final Logger log = LoggerFactory.getLogger(T.class);

    private void test() {
        log.info("test");
    }
}