Android上使用Lombok
来源:互联网 发布:android 棋牌游戏源码 编辑:程序博客网 时间:2024/06/03 19:48
Android上使用Lombok
- Android上使用Lombok
- 简介
- 注解简介
- Android 集成
- 注解说明
- val
- NonNull
- Cleanup
- GetterSetter
- ToString
- EqualsAndHashCode
- NoArgsConstructor RequiredArgsConstructor and AllArgsConstructor
- Builder
- SneakyThrows
- Synchronized
- Getterlazytrue
- Log
- 原理
- 总结
- 相关链接
简介
最近几天尝试了一把后端的工作,发现后端同学使用了一个第三库——Lombok,用了一下,感觉还不错,特来介绍一下,感觉和以前介绍过的AutoValue挺像的。
Lombok 官网上面有个几分钟的视频,接单介绍了Lombok的用途,使用方法很简单,只需要依赖对应的jar文件,然后在对应的Java文件上使用注解即可。
先看个例子,下面是常见的一个Java一个实体类,含有field、setter、getter、equals、hashcode、toString方法。
public class User { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (id != user.id) return false; return name != null ? name.equals(user.name) : user.name == null; } @Override public int hashCode() { int result = id; result = 31 * result + (name != null ? name.hashCode() : 0); return result; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; }}
如果使用了Lombok,就很简单了,直接定义好字段,然后添加一个注解@Data
即可,其他方法,工具自动生成,虽然上面的方法我们也是用工具生成的,但是如果要添加或者删除字段,还是要修改代码的,如果直接使用注解的方式,那么还是简单的,无需修改任何方法。
@Datapublic class UserLombok { private int id; private String name;}
注解简介
Lombok 主要使用就是通过添加注解,来自动生成代码,主要包含两类,一种是Stable类型,一种是Experimental。前面表示稳定的注解,后面表示实验类型的,可能会被移除。本文主要介绍Stable类型,Experimental由于使用较少,不做讲解。
Stable
- val
Finally! Hassle-free final local variables.
- @NonNull
or: How I learned to stop worrying and love the NullPointerException.
- @Cleanup
Automatic resource management: Call your close() methods safely with no hassle.
- @Getter/@Setter
Never write public int getFoo() {return foo;} again.
- @ToString
No need to start a debugger to see your fields: Just let lombok generate a toString for you!
- @EqualsAndHashCode
Equality made easy: Generates hashCode and equals implementations from the fields of your object..
- @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
Constructors made to order: Generates constructors that take no arguments, one argument per final / non-nullfield, or one argument for every field.
- @Data
All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!
- @Value
Immutable classes made very easy.
- @Builder
… and Bob’s your uncle: No-hassle fancy-pants APIs for object creation!
- @SneakyThrows
To boldly throw checked exceptions where no one has thrown them before!
- @Synchronized
synchronized done right: Don’t expose your locks.
- @Getter(lazy=true)
Laziness is a virtue!
- @Log
Captain’s Log, stardate 24435.7: “What was that line again?”
Experimental
- var
Modifiable local variables with a type inferred by assigning value.
- @Accessors
A more fluent API for getters and setters.
- @ExtensionMethod
Annoying API? Fix it yourself: Add new methods to existing types!
- @FieldDefaults
New default field modifiers for the 21st century.
- @Delegate
Don’t lose your composition.
- @Wither
Immutable ‘setters’ - methods that create a clone but with one changed field.
- onMethod= / onConstructor= / onParam=
Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you’re annotating.
- @UtilityClass
Utility, metility, wetility! Utility classes for the masses.
- @Helper
With a little help from my friends… Helper methods for java.
Android 集成
项目根目录下面新建配置文件 lombok.config,同时填上对应的配置项,Java项目不需要,Android和Java还是有点区别的,不配置有的注解使用不了,编译不过。
lombok.config
lombok.anyConstructor.suppressConstructorProperties=true
然后在对应的项目中添加gradle依赖就行了。
dependencies { provided "org.projectlombok:lombok:1.16.18" compile 'org.glassfish:javax.annotation:10.0-b28'}
可以在Android Studio中安装lombok插件。
这样可以很方便的看到类中生成的方法
注解说明
下面简单说明注解的使用方法(如需了解详细使用,请参阅官方文档),以及使用注解后类中生成的方法。
val
定义一个final类型的变量,并且可以不写类型。
如:
public class ValExample { public String example() { val example = new ArrayList<String>(); example.add("Hello, World!"); val foo = example.get(0); return foo.toLowerCase(); } public void example2() { val map = new HashMap<Integer, String>(); map.put(0, "zero"); map.put(5, "five"); for (val entry : map.entrySet()) { System.out.printf("%d: %s\n", entry.getKey(), entry.getValue()); } }}
class字节码:
public class ValExample { public ValExample() { } public String example() { ArrayList<String> example = new ArrayList(); example.add("Hello, World!"); String foo = (String)example.get(0); return foo.toLowerCase(); } public void example2() { HashMap<Integer, String> map = new HashMap(); map.put(Integer.valueOf(0), "zero"); map.put(Integer.valueOf(5), "five"); Iterator var2 = map.entrySet().iterator(); while(var2.hasNext()) { Entry<Integer, String> entry = (Entry)var2.next(); System.out.printf("%d: %s\n", new Object[]{entry.getKey(), entry.getValue()}); } }}
@NonNull
非空值判断,如果为空,则抛出异常
如:
public class NonNullExample { public static int length(@NonNull String string) { return string.length(); }}
class字节码
public class NonNullExample { public NonNullExample() { } public static int length(@NonNull String string) { if(string == null) { throw new NullPointerException("string"); } else { return string.length(); } }}
@Cleanup
可以自动调用close方法
如
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); } }}
class字节码
public class CleanupExample { public CleanupExample() { } public static void main(String[] args) throws IOException { FileInputStream in = new FileInputStream(args[0]); try { FileOutputStream out = new FileOutputStream(args[1]); 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(); } } }}
@Getter/@Setter
自动生成setter、getter方法
// GetterSetterExample.javapublic class GetterSetterExample { @Getter @Setter private int age; @Setter(AccessLevel.PROTECTED) private String name;}// GetterSetterExample.classpublic class GetterSetterExample { private int age; private String name; public GetterSetterExample() { } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } protected void setName(String name) { this.name = name; }}
@ToString
自动生成toString方法
// ToStringExample.java@ToString(exclude = "id")public class ToStringExample { private int id; private String name; private String passwd; public ToStringExample(int id, String name, String passwd) { this.id = id; this.name = name; this.passwd = passwd; }}// ToStringExample.classpublic class ToStringExample { private int id; private String name; private String passwd; public ToStringExample(int id, String name, String passwd) { this.id = id; this.name = name; this.passwd = passwd; } public String toString() { return "ToStringExample(name=" + this.name + ", passwd=" + this.passwd + ")"; }}
@EqualsAndHashCode
自动生成equals和hashcode方法。
// EqualsAndHashCodeExample.java@EqualsAndHashCodepublic class EqualsAndHashCodeExample { private int id; private String name; public EqualsAndHashCodeExample(int id, String name) { this.id = id; this.name = name; }}// EqualsAndHashCodeExample.classpublic class EqualsAndHashCodeExample { private int id; private String name; public EqualsAndHashCodeExample(int id, String name) { this.id = id; this.name = name; } public boolean equals(Object o) { if(o == this) { return true; } else if(!(o instanceof EqualsAndHashCodeExample)) { return false; } else { EqualsAndHashCodeExample other = (EqualsAndHashCodeExample)o; if(!other.canEqual(this)) { return false; } else if(this.id != other.id) { return false; } else { Object this$name = this.name; Object other$name = other.name; if(this$name == null) { if(other$name != null) { return false; } } else if(!this$name.equals(other$name)) { return false; } return true; } } } protected boolean canEqual(Object other) { return other instanceof EqualsAndHashCodeExample; } public int hashCode() { int PRIME = true; int result = 1; int result = result * 59 + this.id; Object $name = this.name; result = result * 59 + ($name == null?43:$name.hashCode()); return result; }}
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
自动生成相关的构造函数
// ConstructorExample.java@ToString@NoArgsConstructor@AllArgsConstructor(access = AccessLevel.PUBLIC)public class ConstructorExample<T> { private String args; @ToString @RequiredArgsConstructor(staticName = "of") public static class StaticMethodsExample { @NonNull private String field; }}// ConstructorExample.classpublic class ConstructorExample<T> { private String args; public String toString() { return "ConstructorExample(args=" + this.args + ")"; } public ConstructorExample() { } public ConstructorExample(String args) { this.args = args; } public static class StaticMethodsExample { @NonNull private String field; public String toString() { return "ConstructorExample.StaticMethodsExample(field=" + this.field + ")"; } private StaticMethodsExample(@NonNull String field) { if(field == null) { throw new NullPointerException("field"); } else { this.field = field; } } public static ConstructorExample.StaticMethodsExample of(@NonNull String field) { return new ConstructorExample.StaticMethodsExample(field); } }}
@Builder
自动生成构造者模式方法
// BuilderExample.java@Builder@Datapublic class BuilderExample { private String name; private int age; @Singular private Set<String> occupations;}
class文件太长,就不贴了,下面是调用方式。
// test builderBuilderExample builderExample = BuilderExample.builder() .name("admin") .age(10) .occupation("aaa") .occupation("bbb") .build();Log.i(TAG, "onCreate: " + builderExample);
@SneakyThrows
自动生成异常抛出代码
// SneakyThrowsExample.javapublic 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(); }}// SneakyThrowsExample.classpublic class SneakyThrowsExample implements Runnable { public SneakyThrowsExample() { } public String utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException var3) { throw var3; } } public void run() { try { throw new Throwable(); } catch (Throwable var2) { throw var2; } }}
@Synchronized
自动生成线程同步代码
// SynchronizedExample.javapublic 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"); }}// SynchronizedExample.classpublic class SynchronizedExample { private static final Object $LOCK = new Object[0]; private final Object $lock = new Object[0]; private final Object readLock = new Object(); public SynchronizedExample() { } public static void hello() { Object var0 = $LOCK; synchronized($LOCK) { System.out.println("world"); } } public int answerToLife() { Object var1 = this.$lock; synchronized(this.$lock) { return 42; } } public void foo() { Object var1 = this.readLock; synchronized(this.readLock) { System.out.println("bar"); } }}
@Getter(lazy=true)
延迟初始化
// GetterLazyExample.javapublic 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; }}// GetterLazyExample.classpublic class GetterLazyExample { private final AtomicReference<Object> cached = new AtomicReference(); public GetterLazyExample() { } 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) { AtomicReference var2 = this.cached; 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[])((double[])(value == this.cached?null:value)); }}
@Log
自动生成日志对象,不过都是J2EE方面的,Android端用途不大。
官方示例
原理
自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。
举例来说,现在有一个实现了”JSR 269 API”的程序A,那么使用javac编译源码的时候具体流程如下:
javac对源代码进行分析,生成一棵抽象语法树(AST)
运行过程中调用实现了”JSR 269 API”的A程序
此时A程序就可以完成它自己的逻辑,包括修改第一步骤得到的抽象语法树(AST)
javac使用修改后的抽象语法树(AST)生成字节码文件
详细的流程图如下:
总结
综上所述,使用了lombok可以简化Java代码,因为是在编译期处理所以可能会增加点时间,不过对于Android来说,可以尝试一下,不过17年Google IO已经推荐使用Kotlin开发Android了,lombok中好多功能在Kotlin中已经实现了,如果项目暂时还不想使用Kotlin开发,继续使用Java的可以尝试一下。
缺点:
使用lombok虽然能够省去手动创建代码的麻烦,但是却大大降低了源代码文件的可读性和完整性,降低了阅读源代码的舒适度。
相关链接
Lombok官网
AutoValue相关
android基础之依赖注入问题
Lombok的使用和原理
- Android上使用Lombok
- Android Studio 使用 lombok
- Android Stduio 使用Lombok
- Intellij Idea 上使用 Lombok
- 在IDEA上使用lombok
- 【Lombok】lombok使用教程
- 在Android中使用Lombok减少编码
- lombok 使用
- lombok使用
- lombok使用
- 使用lombok
- Lombok使用
- lombok使用
- Lombok使用
- lombok使用
- Android Studio使用Lombok消除冗长的 java代码
- eclipse中使用Lombok
- lombok的使用
- Linux下安装android studio
- React-Native|AsyncStorage缓存网络数据
- Rabbitmq 整合Spring,SpringBoot与Docker
- 第一章 Shiro简介——《跟我学Shiro》
- 【服务器】Nginx 作为应用服务器映射服务
- Android上使用Lombok
- Socket 进行UDP广播数据(GCDAsyncUdpSocket)
- 你的机器人只差双眼睛
- [云路由器] 设置了虚拟服务器,外网无法访问服务器怎么办?
- Android开源库V
- php下pgsql扩展安装
- typeof、undefined,一个易犯的错误
- 远程操作SDR实现
- MyBatis--第三天