Lombok插件注解

在使用lombok注解的时候记得要导入lombok.jar包到工程,如果使用的是Maven的工程项目的话,要在其pom.xml中添加依赖如下:

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<version>1.16.8</version>

</dependency>

@AllArgsConstructor
会生成一个包含所有变量,同时如果变量使用了NotNull annotation , 会进行是否为空的校验,
全部参数的构造函数的自动生成,该注解的作用域也是只有在实体类上,参数的顺序与属性定义的顺序一致。
@AllArgsConstructor:注解在类上;为类提供一个全参的构造方法

@AllArgsConstructor
public class Demo {

private String name;
private int age;
}

@AllArgsConstructor
class Parent {
private Integer id;
} 

编译后的两个class文件如下

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

    public Demo(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

//第二个类
class Parent {
    private Integer id;

    public Parent(Integer id) {
        this.id = id;
    }
} 

此注解并不会把父类的属性id拿到Demo的构造器里面去,这是需要注意的地方。并且它也没有默认的构造器了

@AllArgsConstructor(access = AccessLevel.PROTECTED, staticName = "test")
public class Demo {
    private final int finalVal = 10;
    private String name;
    private int age;
}  

生成如下:

public class Demo {
    private final int finalVal = 10;
    private String name;
    private int age;

    private Demo(String name, int age) {
        this.name = name;
        this.age = age;
    }

    protected static Demo test(String name, int age) {
        return new Demo(name, age);
    }
}

看出来的效果为:可以指定生成的构造器的访问权限。但是,但是如果指定了一个静态方法,那么构造器会自动会被private,只通过静态方法对外提供反问,并且我们发现final的属性值,是不会放进构造函数里面的。

@NoArgsConstructor:注解在类上;为类提供一个无参的构造方法
@NoArgsConstructor:无参构造函数

@RequiredArgsConstructor
会生成一个包含常量(final),和标识了@NotNull的变量 的构造方法。

@RequiredArgsConstructor
public class Demo {
    private final int finalVal = 10;

    @NonNull
    private String name;
    @NonNull
    private int age;
} 

编译后:

public class Demo {
    private final int finalVal = 10;
    @NonNull
    private String name;
    @NonNull
    private int age;

    public Demo(@NonNull String name, @NonNull int age) {
        if (name == null) {
            throw new NullPointerException("name is marked @NonNull but is null");
        } else {
            this.name = name;
            this.age = age;
        }
    }
} 

解释:该注解会识别@nonNull字段,然后以该字段为元素产生一个构造函数。备注:如果所有字段都没有@nonNull注解,那效果同NoArgsConstructor

@Log、CommonsLog、Slf4j、XSlf4j、Log4j、Log4j2等日志注解
这个注解用在类上,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用topic来指定生成log对象时的类名。不同的日志注解总结如下(上面是注解,下面是实际作用):

@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@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);

这个注解还是非常有用的,特别是Slf4j这个,在平时开发中挺有用的

@Slf4j
class Parent {
}

编译后:

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

    Parent() {
    }
}

也可topic的名称:

@Slf4j
@CommonsLog(topic = "commonLog")
class Parent {
}

编译后:

class Parent {
    private static final Logger log = LoggerFactory.getLogger("commonLog");

    Parent() {
    }
}

@Data注解作用比较全,其包含注解的集合 @ToString, @EqualsAndHashCode,所有字段的 @Getter和所有非final字段的 @Setter, @RequiredArgsConstructor。其示例代码可以参考上面几个注解的组合
@Data 强悍的组合功能包
相当于注解集合。效果等同于**@Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor** 由于生成的代码篇幅太长,这里就不给demo了,反正效果同上5个注解的效果,强悍
@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

所以@Value更适合只读性更强的类,所以特殊情况下,还是可以使用的。
需要注意的是,这里不包括@NoArgsConstructor和@AllArgsConstructor
@Builder : 注解在类上, 为类提供一个内部的 Builder
@Builder 提供了一种比较推崇的构建值对象的方式
非常推荐的一种构建值对象的方式。缺点就是父类的属性不能产于builder

@Builder
public class Demo {
    private final int finalVal = 10;

    private String name;
    private int age;
}

编译后:

public class Demo {
    private final int finalVal = 10;
    private String name;
    private int age;

    Demo(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static Demo.DemoBuilder builder() {
        return new Demo.DemoBuilder();
    }

    public static class DemoBuilder {
        private String name;
        private int age;

        DemoBuilder() {
        }

        public Demo.DemoBuilder name(String name) {
            this.name = name;
            return this;
        }

        public Demo.DemoBuilder age(int age) {
            this.age = age;
            return this;
        }

        public Demo build() {
            return new Demo(this.name, this.age);
        }

        public String toString() {
            String var10000 = this.name;
            return this.age;
        }
    }
}

因此我们构造一个对象就可以优雅的这么来:

public static void main(String[] args) {
        Demo demo = Demo.builder().name("aa").age(10).build();
        System.out.println(demo); 
    } 

里面有一些自定义参数,我表示,完全没有必要去自定义。

@Cleanup : 注释在引用变量前, 自动回收资源 默认调用 close() 方法
@Cleanup 能够自动释放资源
这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法。如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法,就用输入输出流来举个例子吧:

public static void main(String[] args) throws Exception {
        @Cleanup InputStream in = new FileInputStream(args[0]);
        @Cleanup OutputStream out = new FileOutputStream(args[1]);
        byte[] b = new byte[1024];
        while (true) {
            int r = in.read(b);
            if (r == -1) break;
            out.write(b, 0, r);
        }
    } 

编译后:

public static void main(String[] args) throws Exception {
        FileInputStream in = new FileInputStream(args[0]);

        try {
            FileOutputStream out = new FileOutputStream(args[1]);

            try {
                byte[] b = new byte[1024];

                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();
            }

        }
    } 

就这么简单的一个注解,就实现了优雅的关流操作哟。
@NonNull注解能够为方法或构造函数的参数提供非空检查
@NonNull : 注解在参数上, 如果该类参数为 null , 就会报出异常, throw new NullPointException(参数名),,如果参数为空,则抛出一个空指针异常

public void notNullExample(@NonNull String string) {

string.length();

}

//=>相当于

public void notNullExample(String string) {

if (string != null) {

string.length();

} else {

throw new NullPointerException("null");

}

}

@Cleanup注解能够自动释放资源
在这里插入图片描述
@Getter/@Setter注解可以针对类的属性字段自动生成Get/Set方法
这两个注解直接用在类上,可以为此类里的所有非静态成员变量生成对应的get和set方法。如果是final变量,那就只会有get方法
在这里插入图片描述
@ToString注解,为使用该注解的类生成一个toString方法,默认的toString格式为:ClassName(fieldName= fieleValue ,fieldName1=fieleValue)

@ToString(callSuper=true,exclude="someExcludedField")

public class Demo extends Bar {

private boolean someBoolean = true;

private String someStringField;

private float someExcludedField;

}

//上面代码相当于如下:

public class Demo extends Bar {

private boolean someBoolean = true;

private String someStringField;

private float someExcludedField;

@ Override

public String toString() {

return "Foo(super=" + super.toString() +

", someBoolean=" + someBoolean +

", someStringField=" + someStringField + ")";

}

}

我们发现静态字段它是不输出的。
有些关键的属性,可以控制toString的输出,我们可以了解一下:

@ToString(
        includeFieldNames = true, //是否使用字段名
        exclude = {"name"}, //排除某些字段
        of = {"age"}, //只使用某些字段
        callSuper = true //是否让父类字段也参与 默认false
) 

@SneakyThrows
这个注解用在方法上,可以将方法中的代码用try-catch语句包裹起来,捕获异常并在catch中用Lombok.sneakyThrow(e)把异常抛出,可以使用@SneakyThrows(Exception.class)的形式指定抛出哪种异常

@SneakyThrows(UnsupportedEncodingException.class)
    public String utf8ToString(byte[] bytes) {
        return new String(bytes, "UTF-8");
    } 

编译后:

@SneakyThrows(UnsupportedEncodingException.class)
    public String utf8ToString(byte[] bytes) {
        try{
            return new String(bytes, "UTF-8");
        }catch(UnsupportedEncodingException uee){
            throw Lombok.sneakyThrow(uee);
        }
    } 

@Val 很强的类型推断 var注解,在Java10之后就不能使用了

class Parent {

    //private static final val set = new HashSet<String>(); //编译不通过

    public static void main(String[] args) {
        val set = new HashSet<String>();
        set.add("aa");
        System.out.println(set); //[aa]
    }

} 

编译后:

class Parent {
    Parent() {
    }

    public static void main(String[] args) {
        HashSet<String> set = new HashSet();
        set.add("aa");
        System.out.println(set);
    }
} 

这个和Java10里的Var很像,强大的类型推断。并且不能使用在全局变量上,只能使用在局部变量的定义中。
@EqualsAndHashCode注解,为使用该注解的类自动生成equals和hashCode方法,还会生成一个canEqual方法,用于判断某个对象是否是当前类的实例。,生成方法时只会使用类中的非静态成员变量,这些都比较好理解。毕竟静态的东西并不属于对象本身 。
在这里插入图片描述
@Synchronized注解类似Java中的Synchronized 关键字,但是可以隐藏同步锁

public class SynchronizedExample {

private final Object readLock = new Object();

@Synchronized

public static void hello() {

System.out.println("world");

}

@Synchronized("readLock")

public void foo() {

System.out.println("bar");

}

//上面代码相当于如下:

public class SynchronizedExample {

private static final Object $LOCK = new Object[0];

private final Object readLock = new Object();

public static void hello() {

synchronized($LOCK) {

System.out.println("world");

}

}

public void foo() {

synchronized(readLock) {

System.out.println("bar");

}

}

}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页