官网地址:进入官网

JavaPoet 是一个用来生成 .java源文件的Java API。

当做如注解或者数据库模式、协议格式等事情时,生成源文件就比较有用处。

Example

HelloWorld 类为例:

package com.example.helloworld;public final class HelloWorld {public static void main(String[] args) {System.out.println("Hello, JavaPoet!");}
}

上面的代码就是使用javapoet用下面的代码进行生成的:

MethodSpec main = MethodSpec.methodBuilder("main").addModifiers(Modifier.PUBLIC, Modifier.STATIC).returns(void.class).addParameter(String[].class, "args").addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!").build();TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addModifiers(Modifier.PUBLIC, Modifier.FINAL).addMethod(main).build();JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld).build();javaFile.writeTo(System.out);

通过MethodSpec类来创建一个”main”方法,并配置了修饰符、返回值类型、参数以及代码语句。然后把这个main方法添加到 HelloWorld 类中,最后添加到 HelloWorld.java文件中。
这个例子中,我们将文件通过Sytem.out 进行输出,但是同样也可以使用(JavaFile.toString()) 得到string字符串,或者通过 (JavaPoet.writeTo()) 方法写入到文件系统中。

Javadoc 中包括了完整的JavaPoet API, 我们接着往下看。

Code & Control Flow

大多数JavaPoet的API使用的是简单的不可变的Java对象。通过建造者模式,链式方法,可变参数是的API比较友好。JavaPoet提供了(TypeSpec)用于创建类或者接口,(FieldSpec)用来创建字段,(MethodSpec)用来创建方法和构造函数,(ParameterSpec)用来创建参数,(AnnotationSpec)用于创建注解。

但是如果没有语句类,没有语法结点数,可以通过字符串来构建代码块:

MethodSpec main = MethodSpec.methodBuilder("main").addCode(""+ "int total = 0;\n"+ "for (int i = 0; i < 10; i++) {\n"+ "  total += i;\n"+ "}\n").build();

生成的代码如下:

void main() {int total = 0;for (int i = 0; i < 10; i++) {total += i;}
}

人为的输入分号、换行和缩进是比较乏味的。所以JavaPoet提供了相关API使它变的容易。
addStatement() 负责分号和换行,beginControlFlow() + endControlFlow() 需要一起使用,提供换行符和缩进。

MethodSpec main = MethodSpec.methodBuilder("main").addStatement("int total = 0").beginControlFlow("for (int i = 0; i < 10; i++)").addStatement("total += i").endControlFlow().build();

这个例子稍微有点差劲。生成的代码如下:

private MethodSpec computeRange(String name, int from, int to, String op) {return MethodSpec.methodBuilder(name).returns(int.class).addStatement("int result = 0").beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)").addStatement("result = result " + op + " i").endControlFlow().addStatement("return result").build();
}

调用computeRange(“multiply10to20”, 10, 20, “*”)就生成如下代码:

int multiply10to20() {int result = 0;for (int i = 10; i < 20; i++) {result = result * i;}
  return result;
}

方法生成方法!JavaPoet生成的是源代码而不是字节码,所以可以通过阅读源码确保正确。

$L for Literals

字符串连接的方法beginControlFlow() 和 addStatement是分散开的,操作较多。
针对这个问题, JavaPoet 提供了一个语法但是有违String.format()语法. 通过 $L 来接受一个 literal 值。 这有点像 Formatter’s %s:

private MethodSpec computeRange(String name, int from, int to, String op) {return MethodSpec.methodBuilder(name).returns(int.class).addStatement("int result = 0").beginControlFlow("for (int i = $L; i < $L; i++)", from, to).addStatement("result = result $L i", op).endControlFlow().addStatement("return result").build();
}

Literals 直接写在输出代码中,没有转义。 它的类型可以是字符串、primitives和一些接下来要说的JavaPoet类型。

$S for Strings

当输出的代码包含字符串的时候, 可以使用 $S 表示一个 string。 下面的代码包含三个方法,每个方法返回自己的名字:

public static void main(String[] args) throws Exception {TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addModifiers(Modifier.PUBLIC, Modifier.FINAL).addMethod(whatsMyName("slimShady")).addMethod(whatsMyName("eminem")).addMethod(whatsMyName("marshallMathers")).build();JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld).build();javaFile.writeTo(System.out);
}private static MethodSpec whatsMyName(String name) {return MethodSpec.methodBuilder(name).returns(String.class).addStatement("return $S", name).build();
}

输出结果如下:

public final class HelloWorld {String slimShady() {return "slimShady";}String eminem() {return "eminem";}String marshallMathers() {return "marshallMathers";}
}

$T for Types

使用Java内置的类型会使代码比较容易理解。JavaPoet极大的支持这些类型,通过 $T 进行映射,会自动import声明。

MethodSpec today = MethodSpec.methodBuilder("today").returns(Date.class).addStatement("return new $T()", Date.class).build();TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addModifiers(Modifier.PUBLIC, Modifier.FINAL).addMethod(today).build();JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld).build();javaFile.writeTo(System.out);

自动完成import声明,生成代码如下:

package com.example.helloworld;import java.util.Date;public final class HelloWorld {Date today() {return new Date();}
}

再举一个相似的例子,但是应用了一个不存在的类:

ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");MethodSpec today = MethodSpec.methodBuilder("tomorrow").returns(hoverboard).addStatement("return new $T()", hoverboard).build();

类不存在,但是代码是完整的:

package com.example.helloworld;import com.mattel.Hoverboard;public final class HelloWorld {Hoverboard tomorrow() {return new Hoverboard();}
}

ClassName 这个类非常重要, 当你使用JavaPoet的时候会频繁的使用它。
它可以识别任何声明类。具体看下面的例子:

ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
ClassName list = ClassName.get("java.util", "List");
ClassName arrayList = ClassName.get("java.util", "ArrayList");
TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);MethodSpec beyond = MethodSpec.methodBuilder("beyond").returns(listOfHoverboards).addStatement("$T result = new $T<>()", listOfHoverboards, arrayList).addStatement("result.add(new $T())", hoverboard).addStatement("result.add(new $T())", hoverboard).addStatement("result.add(new $T())", hoverboard).addStatement("return result").build();

JavaPoet将每一种类型进行分解,并尽可能的导入其声明.

package com.example.helloworld;import com.mattel.Hoverboard;
import java.util.ArrayList;
import java.util.List;public final class HelloWorld {List<Hoverboard> beyond() {List<Hoverboard> result = new ArrayList<>();result.add(new Hoverboard());result.add(new Hoverboard());result.add(new Hoverboard());return result;}
}

Import static

JavaPoet支持import static。它显示的收集类型成员的名称。例子如下:

ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards");MethodSpec beyond = MethodSpec.methodBuilder("beyond").returns(listOfHoverboards).addStatement("$T result = new $T<>()", listOfHoverboards, arrayList).addStatement("result.add($T.createNimbus(2000))", hoverboard).addStatement("result.add($T.createNimbus(\"2001\"))", hoverboard).addStatement("result.add($T.createNimbus($T.THUNDERBOLT))", hoverboard, namedBoards).addStatement("$T.sort(result)", Collections.class).addStatement("return result.isEmpty() $T.emptyList() : result", Collections.class).build();TypeSpec hello = TypeSpec.classBuilder("HelloWorld").addMethod(beyond).build();JavaFile.builder("com.example.helloworld", hello).addStaticImport(hoverboard, "createNimbus").addStaticImport(namedBoards, "*").addStaticImport(Collections.class, "*").build();

JavaPoet将会首先添加 import static 代码块进行配置,当然也需要导入其他所需的类型引用。

package com.example.helloworld;import static com.mattel.Hoverboard.Boards.*;
import static com.mattel.Hoverboard.createNimbus;
import static java.util.Collections.*;import com.mattel.Hoverboard;
import java.util.ArrayList;
import java.util.List;class HelloWorld {List<Hoverboard> beyond() {List<Hoverboard> result = new ArrayList<>();result.add(createNimbus(2000));result.add(createNimbus("2001"));result.add(createNimbus(THUNDERBOLT));sort(result);return result.isEmpty() ? emptyList() : result;}
}

$N for Names

使用 $N 可以引用另外一个通过名字生成的声明。

public String byteToHex(int b) {char[] result = new char[2];result[0] = hexDigit((b >>> 4) & 0xf);result[1] = hexDigit(b & 0xf);return new String(result);
}public char hexDigit(int i) {return (char) (i < 10 ? i + '0' : i - 10 + 'a');
}

生成的代码如下,在byteToHex()方法中通过$N来引用 hexDigit()方法作为一个参数:

MethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit").addParameter(int.class, "i").returns(char.class).addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')").build();MethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex").addParameter(int.class, "b").returns(String.class).addStatement("char[] result = new char[2]").addStatement("result[0] = $N((b >>> 4) & 0xf)", hexDigit).addStatement("result[1] = $N(b & 0xf)", hexDigit).addStatement("return new String(result)").build();

Methods

上面的例子中的方法都有方法体。 使用 Modifiers.ABSTRACT 创建的方法是没有方法体的。通常用来创建一个抽象类或接口。

MethodSpec flux = MethodSpec.methodBuilder("flux").addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED).build();TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).addMethod(flux).build();

生成如下代码:

public abstract class HelloWorld {protected abstract void flux();
}

当执行修饰符的时。JavaPoet用的是
javax.lang.model.element.Modifier类,这个类在android平台上不可用. 这只限制与生成代码阶段;输出的代码可运行在任何平台上: JVMs, Android,
and GWT。

方法可能会有参数,异常,可变参数,注释,注解,类型变量和一个返回类型。这些都可以通过 MethodSpec.Builder 来进行配置。

Constructors

MethodSpec 也可以用来创建构造函数:

MethodSpec flux = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addParameter(String.class, "greeting").addStatement("this.$N = $N", "greeting", "greeting").build();TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addModifiers(Modifier.PUBLIC).addField(String.class, "greeting", Modifier.PRIVATE, Modifier.FINAL).addMethod(flux).build();

生成如下代码:

public class HelloWorld {private final String greeting;public HelloWorld(String greeting) {this.greeting = greeting;}
}

多数情况下,构造方法同普通方法一样。当生成代码时,构造函数会先于其他方法生成。

Parameters

通过 ParameterSpec.builder() 可以创建参数,或者直接调用 MethodSpec类的 addParameter() 方法添加参数:

ParameterSpec android = ParameterSpec.builder(String.class, “android”)

    .addModifiers(Modifier.FINAL).build();MethodSpec welcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords").addParameter(android).addParameter(String.class, "robot", Modifier.FINAL).build();

虽然上面的代码生成android 和 robot这两个参数是不同的方式,但是输出是一样的:

void welcomeOverlords(final String android, final String robot) {
}

当参数有注解(比如 @Nullable)的时候,通过扩展的 Builder 方式创建参数是比较方便的。

Fields

字段通参数一样通过 build 方式创建:

FieldSpec android = FieldSpec.builder(String.class, "android").addModifiers(Modifier.PRIVATE, Modifier.FINAL).build();TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addModifiers(Modifier.PUBLIC).addField(android).addField(String.class, "robot", Modifier.PRIVATE, Modifier.FINAL).build();

生成如下代码:

public class HelloWorld {private final String android;private final String robot;
}

通关 Builder 方式很容易生成带注释、注解或者初始化的字段。
Field的初始化代码如下:

FieldSpec android = FieldSpec.builder(String.class, "android").addModifiers(Modifier.PRIVATE, Modifier.FINAL).initializer("$S + $L", "Lollipop v.", 5.0d).build();

生成代码:

private final String android = "Lollipop v." + 5.0;

Interfaces

JavaPoet同样可以生成接口。注意接口的方法必须是 PUBLIC
ABSTRACT 类型,接口的变量必须是 PUBLIC STATIC FINAL 类型。
创建接口的时候必须要添加上这些修饰符。

TypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld").addModifiers(Modifier.PUBLIC).addField(FieldSpec.builder(String.class, "ONLY_THING_THAT_IS_CONSTANT").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("$S", "change").build()).addMethod(MethodSpec.methodBuilder("beep").addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).build()).build();

但是这些修饰符在生成的java文件中是找不到的。这些都是缺省值。

public interface HelloWorld {String ONLY_THING_THAT_IS_CONSTANT = "change";void beep();
}

Enums

通过 enumBuilder 可以创建枚举类型, 调用 addEnumConstant() 可添加枚举变量:

TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo").addModifiers(Modifier.PUBLIC).addEnumConstant("ROCK").addEnumConstant("SCISSORS").addEnumConstant("PAPER").build();

生成如下代码:

public enum Roshambo {ROCK,SCISSORS,PAPER
}

Fancy enums 也是支持的。

TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo").addModifiers(Modifier.PUBLIC).addEnumConstant("ROCK", TypeSpec.anonymousClassBuilder("$S", "fist").addMethod(MethodSpec.methodBuilder("toString").addAnnotation(Override.class).addModifiers(Modifier.PUBLIC).addStatement("return $S", "avalanche!").build()).build()).addEnumConstant("SCISSORS", TypeSpec.anonymousClassBuilder("$S", "peace").build()).addEnumConstant("PAPER", TypeSpec.anonymousClassBuilder("$S", "flat").build()).addField(String.class, "handsign", Modifier.PRIVATE, Modifier.FINAL).addMethod(MethodSpec.constructorBuilder().addParameter(String.class, "handsign").addStatement("this.$N = $N", "handsign", "handsign").build()).build();

生成代码:

public enum Roshambo {ROCK("fist") {@Overridepublic void toString() {return "avalanche!";}},SCISSORS("peace"),PAPER("flat");private final String handsign;Roshambo(String handsign) {this.handsign = handsign;}
}

Anonymous Inner Classes

在上面的枚举代码汇总,使用了 Types.anonymousInnerClass()。匿名内部类也可以在代码块中使用。 通过 $L 引用匿名内部类:

TypeSpec comparator = TypeSpec.anonymousClassBuilder("").addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class)).addMethod(MethodSpec.methodBuilder("compare").addAnnotation(Override.class).addModifiers(Modifier.PUBLIC).addParameter(String.class, "a").addParameter(String.class, "b").returns(int.class).addStatement("return $N.length() - $N.length()", "a", "b").build()).build();TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").addMethod(MethodSpec.methodBuilder("sortByLength").addParameter(ParameterizedTypeName.get(List.class, String.class), "strings").addStatement("$T.sort($N, $L)", Collections.class, "strings", comparator).build()).build();

生成的代码包含一个类和一个方法:

void sortByLength(List<String> strings) {Collections.sort(strings, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return a.length() - b.length();}});
}

定义匿名内部类的一个特别棘手的问题是参数的构造。在上面的代码中我们传递了不带参数的空字符串。TypeSpec.anonymousClassBuilder(“”)。

Annotations

对方法添加注解非常简单:

MethodSpec toString = MethodSpec.methodBuilder("toString").addAnnotation(Override.class).returns(String.class).addModifiers(Modifier.PUBLIC).addStatement("return $S", "Hoverboard").build();

生成如下代码:

 @Overridepublic String toString() {return "Hoverboard";}

通过 AnnotationSpec.builder() 可以对注解设置属性:

MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent").addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).addAnnotation(AnnotationSpec.builder(Headers.class).addMember("accept", "$S", "application/json; charset=utf-8").addMember("userAgent", "$S", "Square Cash").build()).addParameter(LogRecord.class, "logRecord").returns(LogReceipt.class).build();

生成如下代码:

@Headers(accept = "application/json; charset=utf-8",userAgent = "Square Cash"
)
LogReceipt recordEvent(LogRecord logRecord);

注解同样可以注解其它的注解。通过 $L 进行引用:

MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent").addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).addAnnotation(AnnotationSpec.builder(HeaderList.class).addMember("value", "$L", AnnotationSpec.builder(Header.class).addMember("name", "$S", "Accept").addMember("value", "$S", "application/json; charset=utf-8").build()).addMember("value", "$L", AnnotationSpec.builder(Header.class).addMember("name", "$S", "User-Agent").addMember("value", "$S", "Square Cash").build()).build()).addParameter(LogRecord.class, "logRecord").returns(LogReceipt.class).build();

生成如下代码:

@HeaderList({@Header(name = "Accept", value = "application/json; charset=utf-8"),@Header(name = "User-Agent", value = "Square Cash")
})
LogReceipt recordEvent(LogRecord logRecord);

addMember() 可以调用多次。

Javadoc

变量方法和类都可以添加注释:

MethodSpec dismiss = MethodSpec.methodBuilder("dismiss").addJavadoc("Hides {@code message} from the caller's history. Other\n"+ "participants in the conversation will continue to see the\n"+ "message in their own history unless they also delete it.\n").addJavadoc("\n").addJavadoc("<p>Use {@link #delete($T)} to delete the entire\n"+ "conversation for all participants.\n", Conversation.class).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).addParameter(Message.class, "message").build();

生成如下:

/*** Hides {@code message} from the caller's history. Other* participants in the conversation will continue to see the* message in their own history unless they also delete it.** <p>Use {@link #delete(Conversation)} to delete the entire* conversation for all participants.*/void dismiss(Message message);

使用 $T 可以自动导入类型的引用。

Download

下载最新的 the latest .jar

或者添加Maven依赖:

<dependency><groupId>com.squareup</groupId><artifactId>javapoet</artifactId><version>1.9.0</version>
</dependency>

或者Gradle依赖:

compile 'com.squareup:javapoet:1.9.0'

引用地址:
http://blog.csdn.net/crazy1235/article/details/51876192 翻译
https://square.github.io/javapoet/1.x/javapoet/ javapoet Api
Demo 地址 https://github.com/taoweiji/DemoAPT/tree/master/app/src/main studio 3.0 以下
studio 3.0 以上版本 https://github.com/yatou252303/AnnotationDemo

android javapoet 翻译相关推荐

  1. Android中文翻译组 - 简介

    Android中文翻译组解散,感谢大家的支持!推荐关注由ImportNew团队发起并维护Android开发小组http://www.jobbole.com/groups/8/ Android中文翻译组 ...

  2. 浅入浅出 Android 安全 翻译完成!

    浅入浅出 Android 安全 翻译完成! 作者:Yury Zhauniarovich 译者:飞龙 来源:Yury Zhauniarovich | Publications 在线阅读 PDF格式 EP ...

  3. IntelliJ IDEA/Android Studio 翻译插件,可中英互译。

    TranslationPlugin 项目地址:YiiGuxing/TranslationPlugin 简介:IntelliJ IDEA/Android Studio 翻译插件,可中英互译.    In ...

  4. Android google翻译踩坑之旅

    # Android google翻译踩坑之旅   最近由于工作需求,需要为游戏Android平台接入Google翻译的SDK,由于关于翻译的文章非常少,访问官方文档又需要翻墙,更可气的是找到的博客写了 ...

  5. android布局翻译,android – 使用翻译动画将视图从一个布局转换为另一个布局

    我是 Android动画的新手,我的要求是在点击该视图时将视图从一个布局转换为单个xml文件中的布局. 场景: 假设我单击一个按钮,它出现在xml文件中标题的顶部,它应该向下移动/转换(它应该会产生一 ...

  6. go语言1.4版本将支持面向android开发,[翻译]Go语言1.4版本将支持面向Android开发

    Go语言将支持Android 概述 我们建议将Go语言引入Android平台,重点是用Go语言编写游戏程序,API将在Android NDK中定义. 背景 Android平台被设定为一个多应用操作系统 ...

  7. Embedded Android 协同翻译

    假设你有一定的Android的基础和英语基础. 有愿意贡献开源社区的心. 假设你对下面文件夹感兴趣, 欢迎增加我们协同翻译<Embedded Android> 此次协同翻译.将使用gith ...

  8. android 翻译功能开发,手把手教你开发Android studio翻译插件

    前言 由于我英语很烂,写代码的时候需要用英文命名,有些单词不知道,就只能切换到浏览器打开网页搜索,再拿到英文单词.这样每次都要切换出去,很麻烦,于是,就想着开发一个Android studio插件,在 ...

  9. android游戏翻译,百度翻译(Android)v2.5官方版最好的翻译官

    软件信息: 应用名称:百度翻译(Android)官方版最好的翻译官 应用大小:15M 应用版本:v2.5 软件介绍: 百度翻译是一款集翻译.词典.字典.情景例句于一身的翻译应用,支持离线翻译.语音翻译 ...

最新文章

  1. 为增进理解力而奋斗终身
  2. win10计算机拒绝访问,教你win10系统c盘拒绝访问怎么办
  3. python中的def语句_Python def 函数
  4. 对话亲历者|鲁肃:我在支付宝“拧螺丝“的日子
  5. python接口测试实战_Python接口测试实战01:七种武器
  6. html盒子中盒子排列,css3中弹性盒排布使用方法
  7. OpenGL和D3D11中的深度模版测试
  8. 从时分复用、频分复用到码分复用(CDMA)
  9. vue http get html模板,怎么用vue.js做异步请求?
  10. iOS开发之三方分享(shareSDK)
  11. Spring StringUtils类中几个有用的字符串处理方法
  12. 关于Oracle性能分析中 自动工作量资料档案库(AWR)的管理(Oracle10个/11g的新特点) 文平...
  13. word表格跨页断行不起作用
  14. 维多利亚计算机研究生,2020年惠灵顿维多利亚大学计算机信息硕士申请条件
  15. Win10更新失败的解决办法
  16. 我的读书笔记 -《鬼谷子》
  17. 让我们自己来破解命运外挂999
  18. ubuntu如何安装Mac OS X主题
  19. s3c2440 uboot 移植 (四)支持环境变量在nandflash 存储
  20. Wordpress 修改 mysql 插件_WordPress批量查找替换修改文章内容的插件和代码

热门文章

  1. EXCEL函数之“VLOOKUP”
  2. 用html5实现一个播放器,6 个基于 HTML5 实现的多媒体播放器
  3. 转:任正非寄语2010:开放、妥协与灰度
  4. Python网络爬虫爬淘宝无法爬取问题的解决方法
  5. 网页版电子表格控件tmlxSpreadsheet免费下载地址
  6. apache2 默认首页php,每天进步一点点:Ubuntu下修改Apache2默认网页(主页)
  7. SMT在生产时,对环境温度的要求有哪些?
  8. 如何构建一个大数据量的搜索引擎
  9. Acwing 378.骑士放置(二分图的最大独立集)
  10. Vue Video.js播放m3u8视频流格式(video+videojs-contrib-hl)