Java :Lombok-入门学习笔记

Lombok 介绍

Lombok官网:https://projectlombok.org/

Lombok项目是一个Java库,它会自动插入您的编辑器和构建工具中。

说大白话就是:让我们少敲点代码,从而提高编码效率。

lombok.jar

下载网址: https://projectlombok.org/download

Maven配置Lombox

  <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
 </dependency>

IDEA:Lombok插件

说明一下:Lombok插件并不是提供Lombok功能,功能是有jar实现。插件只是便于提示代码等辅助性功能。

具体使用

JavaBeanDemo

public class User {
    private Integer userId;
    private String username;
    private Character sex;
}

生成get/set方法

@Getter/Setter修饰属性,在编译期会生成该属性get/set方法。

@Getter
@Setter
private Integer userId;

@Getter/Setter修饰类,在编译期会生成该类的实例成员get/set方法(不会去生成静态成员的get/set)。

    @Getter
    @Setter
    public class User{
    		// ... 
    }

如果我不想生成sex的get方法,怎么办?

@Getter/Setter的注解提供参数AccessLevel value()

AccessLevel是个枚举类,作用是选择生成get/set方法的访问权限,有以下级别:

  1. AccessLevel.PUBLIC (默认)
public Character getSex(){}
  1. AccessLevel.MODULE
Character getSex(){}
  1. AccessLevel.PROTECTED
protected getSex(){}
  1. AccessLevel.PRIVATE
private getSex(){}
  1. AccessLevel.NONE
// 不生成get方法!!!
@Getter
@Setter
public class User{
		// ...
  	// AccessLevel.NONE:不生成getSex()方法
  	@Getter(AccessLevel.NONE)
  	private Character sex;
}

编译后的字节码文件 User.class:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.example;

public class User {
    private Integer userId;
    private String username;
    private Character sex;

    public User() {
    }

    public Integer getUserId() {
        return this.userId;
    }

    public String getUsername() {
        return this.username;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setSex(Character sex) {
        this.sex = sex;
    }
}

生成toString方法

@ToString 修饰类,生成该类的toString方法,默认将所有成员变量加入toString方法中。

@ToString
public class User{
		// ...
  	// 编译后将会在class文件中生成toString,如下:
  	public String toString(){
        return "User(userId=" + this.userId + ", username=" + this.username + ", sex=" + this.sex + ")";
    }
}

当然,也可以选择性的将成员变量加入toString方法中

@ToString提供字段参数:

String[] exclude() default {} 其作用是将exclude={}中的属性过滤掉不加入toString方法。

举个例子,将sex属性不加入到toString中:

@ToString(exclude = {"sex"})
public class User {
		// ...
  	// 编译后将会在class文件中生成toString,如下:
 		public String toString() {
        return "User(userId=" + this.userId + ", username=" + this.username + ")";
    }
}

此外@ToString还提供了参String[] of() default{} 作用是指定成员变量加入toString方法中

只将sex属性加入到toString中

@ToString(of = {"sex"})
public class User{
  	// ...
  	// 编译后将会在class文件中生成toString,如下: 
  	public String toString() {
        return "User(sex=" + this.sex + ")";
    }
}

生成equals和hashCode方法

@EqualsAndHashCode修饰类,会生成3个方法:equals,hashCode和canEquals方法,用于比较该类对象是否相等(默认将所成员变量加入equals和hashCode方法中)。

@EqualsAndHashCode也提供了String[] exclude() default {}String[] of() default{} ,作用分别是将某属性过滤和指定某属性加入equals和hashCode方法中。

@EqualsAndHashCode
public class User{
  	// ...
  	// 编译后将会在class文件中生成equals,hashCode,canEquals三个方法,如下: 
  	public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$userId = this.userId;
                    Object other$userId = other.userId;
                    if (this$userId == null) {
                        if (other$userId == null) {
                            break label47;
                        }
                    } else if (this$userId.equals(other$userId)) {
                        break label47;
                    }

                    return false;
                }

                Object this$username = this.username;
                Object other$username = other.username;
                if (this$username == null) {
                    if (other$username != null) {
                        return false;
                    }
                } else if (!this$username.equals(other$username)) {
                    return false;
                }

                Object this$sex = this.sex;
                Object other$sex = other.sex;
                if (this$sex == null) {
                    if (other$sex != null) {
                        return false;
                    }
                } else if (!this$sex.equals(other$sex)) {
                    return false;
                }

                return true;
            }
        }
    }

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

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

举个例子,现在只需要比较username是否相等就代表对象相等:

@EqualsAndHashCode(of = {"username"})
public class User{
  	// ...
  	// 编译后将会在class文件中生成equals,hashCode,canEquals三个方法,如下: 
  	public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$username = this.username;
                Object other$username = other.username;
                if (this$username == null) {
                    if (other$username != null) {
                        return false;
                    }
                } else if (!this$username.equals(other$username)) {
                    return false;
                }

                return true;
            }
        }
    }

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

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

参数非空验证

@NonNull 作用是判断变量是否为空,若为空则抛出空指针异常。

它可以修饰:

  1. 修饰类
  2. 修饰成员变量
  3. 修饰方法参数
  4. 修饰方法返回值
public class User{
  	// ... 
  	@NonNull
  	private Character sex;
  
 		public void method01(@NonNull Integer val) {
      		System.out.println(val);
    }
 		
  	@NonNull
  	public String method02(Integer val) {
      	return val.toString
    }  
}

上面代码所生成的class文件

public class User{
  	// ... 
  	@NonNull
  	private Character sex;
  	
    @NonNull
    public Character getSex() {
        return this.sex;
    }
  	
  	 public void setSex(@NonNull Character sex) {
        if (sex == null) {
            throw new NullPointerException("sex is marked non-null but is null");
        } else {
            this.sex = sex;
        }
    	}
  	
 		public void method01(@NonNull Integer val) {
        if (val == null) {
            throw new NullPointerException("val is marked non-null but is null");
        } else {
            System.out.println(val);
        }
    }
 		
  	@NonNull
    public String method02(Integer val) {
        return val.toString();
    }
}

生成构造方法

  1. @NoArgsConstructor :修饰类生成无参构造方法

    @NoArgsConstructor
    public class User{
      	// ...
      	// 编译后将会在class文件中生成如下: 
        public User() {
        }
    }
    
  2. @RequiredArgsConstructor : 生成指定属性构造方法

    ​ 修饰标有final和@NonNull的成员变量声称构造参数(并且这些变量都没有赋值)。

    @RequiredArgsConstructor
    public class User{
       		private final Integer userId;
      		@NonNull private String username;
      		private Character sex;
      	
      		// 编译后class文件中生成如下:
      		public User(Integer userId, @NonNull String username) {
              if (username == null) {
                  throw new NullPointerException("username is marked non-null but is null");
              } else {
                  this.userId = userId;
                  this.username = username;
            }
        }
      	
    }
    
  3. @AllArgsConstructor : 生成所有属性构造方法

    @AllArgsConstructor
    public class User{
        private Integer userId;
        private String username;
        private Character sex;
      	
      	// 编译后class文件中生成如下:
        public User(Integer userId, String username, Character sex) {
            this.userId = userId;
            this.username = username;
            this.sex = sex;
        }
    }
    

@Data

@Data修饰类,集成@Getter/Setter + @ToString + @EqualsAndHashCode

@Data
public class User{
  	// ... 
  	// 编译后class文件中生成如下:
  	public Integer getUserId(){
      	return this.userId;
    }
  	
  	public void setUserId(Integer userId){
      	this.userId = userId;
    }
  	
  	public boolean equals(Object o) {
      	//	... 
    }
  	
 		public boolean canEquals(Object o) {
      	// ... 
    }
  
  	public int hashCode(){
   			// ... 
    }
  
  	public String toString(){
      	// ... 
    }
}

@Builder

@Builder 修饰类,会生成一个内部类: 构造者模式,方便我们链式(流式)编程。

@Data
@Builder
public class User {
  	//	...
  	// 编译后class文件(User$UserBuilder.class)中生成如下:
  	public static class UserBuilder {
        private Integer userId;
        private String username;
        private Character sex;

        UserBuilder() {
        }

        public User.UserBuilder userId(Integer userId) {
            this.userId = userId;
            return this;
        }

        public User.UserBuilder username(String username) {
            this.username = username;
            return this;
        }

        public User.UserBuilder sex(Character sex) {
            this.sex = sex;
            return this;
        }

        public User build() {
            return new User(this.userId, this.username, this.sex);
        }

        public String toString() {
            return "User.UserBuilder(userId=" + this.userId + ", username=" + this.username + ", sex=" + this.sex + ")";
        }
    }
  
  	
}
@Test
public void test(){
    User user = User.builder().userId(4).username("王五").sex('M').build();
    System.out.println(user);	// User(userId=4, username=王五, sex=M)
}

@Log

​ @Log修饰类,会生成一个日志对象。

@Log 
public class User{
  	// ... 
  	// 编译后class文件(User$UserBuilder.class)中生成一个log对象 
  	private static final Logger log = Logger.getLogger(User.class.getName());
  	// 自己写的方法
  	public void logInfo(){
      	log.info("2020-05-24 21:47:05");
    }
}

关键字:val

​ val 是一个关键,用于修饰变量,可以泛指所有类型,实际上在编译期确定类型。

@Test
public void test(){
    val num = 123;
    val str = "张三";
    val	map = new HashMap<String,Integer>();
    System.out.println(num); // ok
    System.out.println(str); // ok
    System.out.println(map); // ok

    // ----------- JDK 10 增加关键字 var  (注意区分!!!)
    var n = 321;
    var s = "李四";
    var user = new User();
    System.out.println(n); // ok
    System.out.println(s); // ok
    System.out.println(user); // ok
}

关于JDK10关键字参考:https://developer.oracle.com/java/jdk-10-local-variable-type-inference.html

@Cleanup

@Cleanup 修饰属性,自动释放该属性资源。

 @Test
    public void test() throws IOException {
        @Cleanup  InputStream is = System.in;
        int len = 0;
        byte[] buf = new byte[1024];
        while((is.read(buf)) != -1) {
                // ...
        }
    }

编译后class文件

@Test
    public void test() throws IOException {
        InputStream is = System.in;

        try {
            int len = false;
            byte[] buf = new byte[1024];

            while(true) {
                if (is.read(buf) != -1) {
                    continue;
                }
            }
        } finally {
            if (Collections.singletonList(is).get(0) != null) {
                is.close();
            }

        }

    }

@SneakyThrows

@SneakyThrows 修饰方法,代表该方法的throws.....

@SneakyThrows
public void threadSleep01(int millis) {
 	 Thread.sleep(millis);
}

@SneakyThrows(InterruptedException.class)
public void threadSleep(int millis) {
  	Thread.sleep(millis);
}

// 编译后字节码文件
public void threadSleep01(long millis) {
    try {
      Thread.sleep((long)millis);
    } catch (Throwable var3) {
      throw var3;
    }
}

 public void threadSleep02(int millis) {
        try {
            Thread.sleep((long)millis);
        } catch (InterruptedException var3) {
            throw var3;
        }
    }

@Value

@Value修饰类,和@Data大概一致,集成@Getter/Setter + @ToString + @EqualsAndHashCode ,代码片段参考@Data。

@Synchronized

@Synchronized修饰方法(静态方法成员方法),给修饰的方法上锁

 @Synchronized
    public void instanceMethod(){
				// ... 
    }

    @Synchronized
    public static void staticMethod(){
				// ... 
    }
		
		// 编译后class文件
		private final Object $lock = new Object[0];
    private static final Object $LOCK = new Object[0];
		public void instanceMethod() {
        synchronized(this.$lock) {
            ;
        }
    }

    public static void staticMethod() {
        synchronized($LOCK) {
            ;
        }
    }

以上是Lombok基本入门,有待深入。

posted @ 2020-05-24 22:48  零二幺七  阅读(125)  评论(0)    收藏  举报