Lombok提供了简单的注解形式, 依赖编译时代码生成技术, 帮助咱们简化代码, 自动生成基于模板的Java代码.
看一个具体的例子.html
@Data注解, 会自动生成getter/setter方法, 以及重写equals(), hashcode()和toString()方法.java
使用Lombok的代码apache
import lombok.Data; @Data public class DataExample { private final String name; //final修饰的类型会自动加到生成的构造方法中 private double score; private String[] tags; }
等价的原生Java代码eclipse
public class DataExample { private final String name; private double score; private String[] tags; public DataExample(String name) { this.name = name; } public String getName() { return this.name; } public void setScore(double score) { this.score = score; } public double getScore() { return this.score; } public String[] getTags() { return this.tags; } public void setTags(String[] tags) { this.tags = tags; } @Override public String toString() { return "DataExample(" + this.getName() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")"; } protected boolean canEqual(Object other) { return other instanceof DataExample; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof DataExample)) return false; DataExample other = (DataExample) o; if (!other.canEqual((Object)this)) return false; if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false; if (Double.compare(this.getScore(), other.getScore()) != 0) return false; if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long temp1 = Double.doubleToLongBits(this.getScore()); result = (result*PRIME) + (this.getName() == null ? 0 : this.getName().hashCode()); result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32)); result = (result*PRIME) + Arrays.deepHashCode(this.getTags()); return result; } }
给方法参数增长这个注解会自动在方法内对该参数进行是否为空的校验,若是为空,则抛出NullPointerException
使用Lombok的代码ide
import lombok.NonNull; public class NonNullExample { private String name; public NonNullExample(@NonNull Person person) { this.name = person.getName(); } }
等价的原生Java代码ui
public class NonNullExample { private String name; public NonNullExample(Person person) { if (person == null) { throw new NullPointerException("person"); } this.name = person.getName(); } }
自动管理资源,用在局部变量以前,在当前变量范围内即将执行完毕退出以前会自动清理资源,自动生成try-finally这样的代码来关闭流
使用Lombok的代码this
import lombok.Cleanup; import java.io.*; public class CleanupExample { public static void main(String[] args) throws IOException { @Cleanup InputStream in = new FileInputStream(args[0]); @Cleanup OutputStream out = new FileOutputStream(args[1]); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } }
等价的原生Java代码atom
import java.io.*; public class CleanupExample { public static void main(String[] args) throws IOException { InputStream in = new FileInputStream(args[0]); try { OutputStream out = new FileOutputStream(args[1]); try { byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } finally { if (out != null) { out.close(); } } } finally { if (in != null) { in.close(); } } } }
自动生成setter和getter方法了,还能够指定访问范围
使用Lombok的代码spa
import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class GetterSetterExample { @Getter @Setter private int age = 10; @Setter(AccessLevel.PROTECTED) private String name; }
等价的原生Java代码插件
public class GetterSetterExample { private int age = 10; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } protected void setName(String name) { this.name = name; } }
用在类上,能够自动覆写toString方法,固然还能够加其余参数,例如@ToString(exclude=”id”)排除id属性,或者@ToString(callSuper=true, includeFieldNames=true)调用父类的toString方法,包含全部属性
使用Lombok的代码
import lombok.ToString; @ToString(exclude="id") public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private String[] tags; private int id; public String getName() { return this.getName(); } }
等价的原生Java代码
public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private String[] tags; private int id; public String getName() { return this.getName(); } @Override public String toString() { return "ToStringExample(" + this.getName() + ", " + Arrays.deepToString(this.tags) + ")"; } }
用在类上,自动生成equals方法和hashCode方法
使用Lombok的代码
import lombok.EqualsAndHashCode; @EqualsAndHashCode(exclude={"id"}) public class EqualsAndHashCodeExample { private transient int transientVar = 10; private String name; private double score; private String[] tags; private int id; public String getName() { return this.name; } }
等价的原生Java代码
import java.util.Arrays; public class EqualsAndHashCodeExample { private transient int transientVar = 10; private String name; private double score; private String[] tags; private int id; public String getName() { return this.name; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof EqualsAndHashCodeExample)) return false; EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o; if (!other.canEqual((Object)this)) return false; if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false; if (Double.compare(this.score, other.score) != 0) return false; if (!Arrays.deepEquals(this.tags, other.tags)) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long temp1 = Double.doubleToLongBits(this.score); result = (result*PRIME) + (this.name == null ? 0 : this.name.hashCode()); result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32)); result = (result*PRIME) + Arrays.deepHashCode(this.tags); return result; } protected boolean canEqual(Object other) { return other instanceof EqualsAndHashCodeExample; } }
@NoArgsConstructor
生成一个无参数的构造方法
@RequiredArgsConstructor
会生成一个包含常量,和标识了NotNull的变量 的构造方法。生成的构造方法是private,若是指定staticName = “of”参数,同时还会生成一个返回类对象的静态工厂方法
@AllArgsConstructor
会生成一个包含全部变量,同时若是变量使用了NotNull, 会进行是否为空的校验
使用Lombok的代码
@RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample<t> { private int x, y; @NonNull private T description; @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; } }
等价的原生Java代码
public class ConstructorExample<t> { private int x, y; private T description; private ConstructorExample(T description) { if (description == null) throw new NullPointerException("description"); this.description = description; } public static <t> ConstructorExample<t> of(T description) { return new ConstructorExample<t>(description); } protected ConstructorExample(int x, int y, T description) { if (description == null) throw new NullPointerException("description"); this.x = x; this.y = y; this.description = description; } public static class NoArgsExample { private String field; public NoArgsExample() { } } }
注解在类上,至关于同时使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstrutor这些注解
用在类上,是@Data的不可变形式,至关于为属性添加final声明,只提供getter方法,而不提供setter方法
使用Lombok的代码
import lombok.experimental.Value; @Value public class ValueExample { String name; double score; protected String[] tags; }
等价的原生Java代码
import java.util.Arrays; public final class ValueExample { private final String name; private final double score; protected final String[] tags; public ValueExample(String name, double score, String[] tags) { this.name = name; this.score = score; this.tags = tags; } public String getName() { return this.name; } public double getScore() { return this.score; } public String[] getTags() { return this.tags; } @java.lang.Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof ValueExample)) return false; final ValueExample other = (ValueExample)o; final Object this$name = this.getName(); final Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; if (Double.compare(this.getScore(), other.getScore()) != 0) return false; if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false; return true; } @java.lang.Override public int hashCode() { final int PRIME = 59; int result = 1; final Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); final long $score = Double.doubleToLongBits(this.getScore()); result = result * PRIME + (int)($score >>> 32 ^ $score); result = result * PRIME + Arrays.deepHashCode(this.getTags()); return result; } @java.lang.Override public String toString() { return "ValueExample(name=" + getName() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")"; } }
用在类、构造器、方法上,为你提供复杂的builder APIs,让你能够像以下方式同样调用Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build()
使用Lombok的代码
import lombok.experimental.Builder; import java.util.Set; @Builder public class BuilderExample { private String name; private int age; private Set<string> occupations; public static void main(String args[]) { BuilderExample builderExample = BuilderExample.builder().build(); } }
等价的原生Java代码
import java.util.Set; public class BuilderExample { private String name; private int age; private Set<string> occupations; BuilderExample(String name, int age, Set<string> occupations) { this.name = name; this.age = age; this.occupations = occupations; } public static BuilderExampleBuilder builder() { return new BuilderExampleBuilder(); } public static class BuilderExampleBuilder { private String name; private int age; private java.util.ArrayList<string> occupations; BuilderExampleBuilder() {} public BuilderExampleBuilder name(String name) { this.name = name; return this; } public BuilderExampleBuilder age(int age) { this.age = age; return this; } public BuilderExampleBuilder occupation(String occupation) { if (this.occupations == null) { this.occupations = new java.util.ArrayList<string>(); } this.occupations.add(occupation); return this; } public BuilderExampleBuilder occupations(Collection<? extends String> occupations) { if (this.occupations == null) { this.occupations = new java.util.ArrayList<string>(); } this.occupations.addAll(occupations); return this; } public BuilderExampleBuilder clearOccupations() { if (this.occupations != null) { this.occupations.clear(); } return this; } public BuilderExample build() { // complicated switch statement to produce a compact properly sized immutable set omitted. // go to https://projectlombok.org/features/Singular-snippet.html to see it. Set<string> occupations = ...; return new BuilderExample(name, age, occupations); } @java.lang.Override public String toString() { return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")"; } } }
自动抛受检异常,而无需显式在方法上使用throws语句
使用Lombok的代码
import lombok.SneakyThrows; public class SneakyThrowsExample implements Runnable { @SneakyThrows(UnsupportedEncodingException.class) public String utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); } @SneakyThrows public void run() { throw new Throwable(); } }
等价的原生Java代码
import lombok.Lombok; public class SneakyThrowsExample implements Runnable { public String utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { throw Lombok.sneakyThrow(e); } } public void run() { try { throw new Throwable(); } catch (Throwable t) { throw Lombok.sneakyThrow(t); } } }
用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性$lock或$LOCK,而java中的synchronized关键字锁对象是this,锁在this或者本身的类对象上存在反作用,就是你不能阻止非受控代码去锁this或者类对象,这可能会致使竞争条件或者其它线程错误
使用Lombok的代码
import lombok.Synchronized; public class SynchronizedExample { private final Object readLock = new Object(); @Synchronized public static void hello() { System.out.println("world"); } @Synchronized public int answerToLife() { return 42; } @Synchronized("readLock") public void foo() { System.out.println("bar"); } }
等价的原生Java代码
public class SynchronizedExample { private static final Object $LOCK = new Object[0]; private final Object $lock = new Object[0]; private final Object readLock = new Object(); public static void hello() { synchronized($LOCK) { System.out.println("world"); } } public int answerToLife() { synchronized($lock) { return 42; } } public void foo() { synchronized(readLock) { System.out.println("bar"); } } }
能够替代经典的Double Check Lock样板代码
使用Lombok的代码
public class GetterLazyExample { @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; } }
等价的原生Java代码
import java.util.concurrent.atomic.AtomicReference; public class GetterLazyExample { private final AtomicReference<java.lang.Object> cached = new AtomicReference<>(); public double[] getCached() { java.lang.Object value = this.cached.get(); if (value == null) { synchronized (this.cached) { value = this.cached.get(); if (value == null) { final double[] actualValue = expensive(); value = actualValue == null ? this.cached : actualValue; this.cached.set(value); } } } return (double[]) (value == this.cached ? null : value); } private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } }
根据不一样的注解生成不一样类型的log对象,可是实例名称都是log,有六种可选实现类
@CommonsLog Creates log = org.apache.commons.logging.LogFactory.getLog(LogExample.class); @Log Creates log = java.util.logging.Logger.getLogger(LogExample.class.getName()); @Log4j Creates log = org.apache.log4j.Logger.getLogger(LogExample.class); @Log4j2 Creates log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class); @Slf4j Creates log = org.slf4j.LoggerFactory.getLogger(LogExample.class); @XSlf4j Creates log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
使用Lombok的代码
import lombok.extern.java.Log; import lombok.extern.slf4j.Slf4j; @Log public class LogExample { public static void main(String... args) { log.error("Something's wrong here"); } } @Slf4j public class LogExampleOther { public static void main(String... args) { log.error("Something else is wrong here"); } } @CommonsLog(topic="CounterLog") public class LogExampleCategory { public static void main(String... args) { log.error("Calling the 'CounterLog' with a message"); } }
等价的原生Java代码
public class LogExample { private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName()); public static void main(String... args) { log.error("Something's wrong here"); } } public class LogExampleOther { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class); public static void main(String... args) { log.error("Something else is wrong here"); } } public class LogExampleCategory { private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog"); public static void main(String... args) { log.error("Calling the 'CounterLog' with a message"); } }
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> </dependency>
Lombok官网地址:https://projectlombok.org/