优雅的Java工具库Lombok
最近在公司的项目中看到了对于Lombok的应用,经过@Data注解标注POJO,省略了大量的getter/setter代码,原先冗长的POJO在瘦身以后直接变得干净、清爽,程序员不再须要去关注那些长长的方法,只须要集中注意力于字段field之中java
Lombok简介
Lombok是一个很是实用的Java工具库,有效地简化Java代码的冗长。它经过注解如@Data能够直接为Java bean在编译期动态地生成字段的getter/setter方法,使用注解@NoArgsConstructor 和@AllArgsConstructor 为Java bean添加无参构造器和有参构造器,甚至能够在Java代码中使用val和var声明一个动态变量,而无需再指定具体的变量类型,区别只是val声明的变量为final。Lombok还提供了delombok供生成Javadoc,delombok在运行时会将注解@Data转换成getter/setter方法,而后移除@Data注解,若是哪天再也不须要Lombok,也只须要简单运行delombok便可。Lombok的构建支持maven和gradle,同时eclipse、myeclipse和idea等主流IDE也都和lombok兼容,因此能够放心大胆地使用Lombok,不用担忧IDE的编译检查问题。程序员
Lombok栗子
若是想学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。apache
Eclipse安装Lombok支持
官网Lombok https://projectlombok.org/download 下载jar包或者经过构建工具maven,gradle下载jar包api
双击jar包,jar包内的安装器会自动运行寻找eclipseeclipse
点击【Install/Update】maven
引入Lombok依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
Lombok注解使用
Lombok的注解分为稳定版本和试验版本,这里主要介绍稳定版本,由于试验版本的支持目前和IDE不是很好分布式
@Getter/@Setter注解ide
@Getter/@Setter注解的做用就是为字段添加getter/setter方法,可标注在类上,也可标注在字段上。标注在类上表示全部的非静态(no-static)字段都会生成相应的getter/setter方法,标注在字段上表示只为这个字段生成,且会覆盖标注在类上的注解。可设置访问级别,默认为public。@Setter不能够标注final字段函数
@Getter@Setter
public class SetterExample {
@Getter(value=AccessLevel.PRIVATE)@Setter
private String name;
//onMethod=@__({@AnnotationsHere})
@Setter(onMethod=@__({@Deprecated}))
private String age;
//onParam=@__({@AnnotationsHere})
@Setter(onParam=@__({}))
private String sex;
public static void main(String[] args) {
SetterExample se = new SetterExample();
se.setName("zhangsan");
se.setAge("16");
System.out.println(se.getAge());
System.out.println(se.getName());
}
}
Lombok提供了onX的试验属性,分别为:onMethod, onParam, onConstructor,用于向生成的方法,构造器,参数添加注解微服务
反编译后结果
@NonNull注解
@NonNull注解标注方法和构造器的参数,若是参数为null,则会抛出空指针异常,不须要在代码中进行null检测
public class NonNullExample {
@Getter
private String name;
public NonNullExample(@NonNull String name){
this.name = name;
}
public static void main(String[] args){
String name = null;
NonNullExample nne = new NonNullExample(name);
System.out.println(nne.getName());
}
}
@ToString注解
@ToString注解生成toString()方法
@ToString
public class ToStringExample {
@ToString.Exclude
private String name;
@ToString.Include
private String age;
private String sex;
public static void main(String[] args) {
ToStringExample tse = new ToStringExample();
System.out.println(tse.toString());
}
}
属性includeFieldNames,默认为true,包含属性值
属性callSuper,默认为false,调用父类实现
属性onlyExplicitlyIncluded,默认为false,仅包含明确包含的属性
若是想学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。
@ToString.Exclude 标注属性值不包含在toString()方法中
@ToString.Include标注属性值包含在toString()方法中
@EqualsAndHashCode
@EqualsAndHashCode注解生成equals()和hashcode()方法,注解的属性和@ToString相似
@EqualsAndHashCode
public class EqualsAndHashcodeExample {
private String name;
private String age;
private String sex;
public static void main(String[] args) {
EqualsAndHashcodeExample ehe1 = new EqualsAndHashcodeExample();
EqualsAndHashcodeExample ehe2 = new EqualsAndHashcodeExample();
System.out.println(ehe1.equals(ehe2));
System.out.println(ehe1.hashCode());
System.out.println(ehe2.hashCode());
}
}
@NoArgsConstructor@RequiredArgsConstructor@AllArgsConstructor
@NoArgsConstructor : 生成一个无参数的构造方法
@NoArgsConstructor(force=true, staticName="newInstance")
public class NoArgsConstructorExample {
//包含的final字段若是没有初始化,须要加上force=true强制初始化,不然编译错误
private final String name;
//不会进行null检查
@NonNull
@Getter
private String age;
private String sex;
public static void main(String[] args) {
NoArgsConstructorExample nace1 = new NoArgsConstructorExample();
System.out.println(nace1.getAge());
NoArgsConstructorExample nace2 = NoArgsConstructorExample.newInstance();
System.out.println(nace2.getAge());
}
}
@RequiredArgsConstructor:会生成一个包含常量,和标识了NotNull的变量 的构造方法。
@RequiredArgsConstructor(staticName="newInstance")
public class RequiredArgsConstructorExample {
private final String name;
@NonNull
@Getter
private String age;
private String sex;
public static void main(String[] args) {
RequiredArgsConstructorExample race1 = new RequiredArgsConstructorExample("lisi", "18");
System.out.println(race1.getAge());
RequiredArgsConstructorExample race2 = RequiredArgsConstructorExample.newInstance("zhangsan", "16");
System.out.println(race2.getAge());
}
}
@AllArgsConstructor:会生成一个包含全部变量,同时若是变量使用了NotNull annotation , 会进行是否为空的校验
@AllArgsConstructor(staticName="newInstance")
public class AllArgsConstructorExample {
private final String name;
@NonNull
@Getter
private String age;
private String sex;
public static void main(String[] args) {
AllArgsConstructorExample aace1 = new AllArgsConstructorExample("zhangsan", "18", "female");
System.out.println(aace1.getAge());
AllArgsConstructorExample aace2 = AllArgsConstructorExample.newInstance("lisi", "16", "male");
System.out.println(aace2.getAge());
}
}
注意:三个注解生成的构造器均可以指定访问权限,同时也能够提供一个静态方法来供调用。三个注解的区别在于对final和@NonNull字段的处理不一样
另外关于staticName属性,Lombok源码注释以下:
If set, the generated constructor will be private, and an additional static 'constructor' is generated with the same argument list that wraps the real constructor.
很明显三个注解都是能够使用构造器直接建立对象的,也能够使用静态方法建立对象,不知道这段注释是什么意思???
@Data注解
若是想学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。
等同于@ToString, @EqualsAndHashcode, @Getter, @Setter和@RequiredArgsConstructor一块儿使用
@Value
@Value注解为不可变类型的@Data,是@Data的一个变种。它标注的类和字段都会被声明为final
@Builder注解
@Builder注解为类生成builder api以供调用。Builder是一种解决包含数量巨大且繁杂的字段的类的一种构建方式。
假如一个类有几十个字段,那么该如何设计这个类呢?
方法一:将几十个字段都添加在构造函数中。简单粗暴,并且在构造函数中为字段初始化也可以保证对象可以正确建立。缺点就是几十个参数只会致使你在建立对象时记错参数的位置,致使没必要要的麻烦。
方法二:依赖注入。Spring的核心功能之一就是依赖注入,借助这种思想,咱们经过无参构造建立一个对象,而后经过setter方法设置必需的属性。这种方式能够根据需求初始化相关属性,且逻辑清晰,但也会形成代码繁琐,须要调用屡次setter方法。
方法三:Builder模式。建造者模式的思想就是将一个大的类的构建分为几部分建立,从而简化建立的复杂性。
@Builder
public class BuilderExample {
private String name;
private String age;
private String sex;
public static void main(String[] args) {
BuilderExample be = BuilderExample.builder().name("zhangsan").age("16").sex("male").build();
System.out.println(BuilderExample.builder().name("zhangsan").age("16").sex("male"));
}
}
@Log
若是想学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。
@Log注解为类添加一个日志对象log,类型为java.util.logging.Logger
这个类有不少变种,详情以下:
@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@Flogger
private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
@CleanUp注解
@CleanUp注解用于关闭资源,调用资源的close()方法
public class CleanUpExample {
@SneakyThrows({FileNotFoundException.class, Exception.class})
public static void main(String[] args) {
File file = new File("C:/Users/wang2/Desktop/11.jpg");
@Cleanup
FileInputStream is = new FileInputStream(file);
@Cleanup
FileOutputStream os = new FileOutputStream(new File("C:/Users/wang2/Desktop/111.jpg"));
byte[] buffer = new byte[1024];
int length = 0;
while((length = is.read(buffer)) != -1){
os.write(buffer, 0, length);
}
}
}
注意:抛出的异常被@SneakyThrows捕获了
若是想学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。
@SneakyThrows注解
若是想学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。
Sneaky的意思是偷偷摸摸地,@SneakyThrows注解的做用就是取代try...catch代码块,自动生成相应的try...catch代码块