public class Person {
private String name;
private int age;
private String city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
// 使用
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.setName("张三");
person.setAge(20);
person.setCity("北京");
System.out.println(person.getName());
}
}
Kotlin 普通代码
kotlin复制代码
data class Person(
var name: String = "",
var age: Int = 0,
var city: String = ""
)
// 使用
fun main() {
val person = Person()
person.name = "张三"
person.age = 20
person.city = "北京"
println(person.name)
}
Kotlin DSL 风格
kotlin复制代码
data class Person(
var name: String = "",
var age: Int = 0,
var city: String = ""
)
// DSL 构建函数
fun person(block: Person.() -> Unit): Person {
return Person().apply(block)
}
// 使用
fun main() {
val person = person {
name = "张三"
age = 20
city = "北京"
}
println(person.name)
}
2.2 条件判断
Java 普通代码
java复制代码
public class Release {
private String releaseStatus;
private String releaseRemark;
public String getReleaseStatus() {
return releaseStatus;
}
public void setReleaseStatus(String releaseStatus) {
this.releaseStatus = releaseStatus;
}
public String getReleaseRemark() {
return releaseRemark;
}
public void setReleaseRemark(String releaseRemark) {
this.releaseRemark = releaseRemark;
}
}
public class ConditionUtils {
public static boolean checkCondition(Release release) {
return "1".equals(release.getReleaseStatus()) && release.getReleaseRemark() != null;
}
}
// 使用
public class Main {
public static void main(String[] args) {
Release release = new Release();
release.setReleaseStatus("1");
release.setReleaseRemark("备注内容");
boolean result = ConditionUtils.checkCondition(release);
System.out.println(result);
}
}
Kotlin 普通代码
kotlin复制代码
data class Release(
var releaseStatus: String? = null,
var releaseRemark: String? = null
)
// 使用
fun main() {
val release = Release(
releaseStatus = "1",
releaseRemark = "备注内容"
)
val result = release.releaseStatus == "1" && release.releaseRemark != null
println(result)
}
Kotlin DSL 风格
kotlin复制代码
data class Release(
var releaseStatus: String? = null,
var releaseRemark: String? = null
)
// DSL 条件构建器
class ConditionBuilder<T> {
private val conditions = mutableListOf<(T) -> Boolean>()
fun field(property: kotlin.reflect.KProperty1<T, *>, value: Any?) {
conditions.add { data -> property.get(data) == value }
}
fun fieldIsNotNull(property: kotlin.reflect.KProperty1<T, *>) {
conditions.add { data -> property.get(data) != null }
}
fun build(): (T) -> Boolean = { data ->
conditions.all { it(data) }
}
}
// DSL 函数
fun <T> condition(block: ConditionBuilder<T>.() -> Unit): (T) -> Boolean {
val builder = ConditionBuilder<T>()
builder.block()
return builder.build()
}
// 使用
fun main() {
val release = Release(
releaseStatus = "1",
releaseRemark = "备注内容"
)
val checkCondition = condition<Release> {
field(Release::releaseStatus, "1")
fieldIsNotNull(Release::releaseRemark)
}
val result = checkCondition(release)
println(result) // true
}
2.3 构建列表
Java 普通代码
java复制代码
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("苹果");
list.add("香蕉");
list.add("橙子");
for (String item : list) {
System.out.println(item);
}
}
}
Kotlin 普通代码
kotlin复制代码
fun main() {
val list = mutableListOf<String>()
list.add("苹果")
list.add("香蕉")
list.add("橙子")
for (item in list) {
println(item)
}
}
import java.util.ArrayList;
import java.util.List;
public class Address {
private String province;
private String city;
private String street;
public String getProvince() { return province; }
public void setProvince(String province) { this.province = province; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
}
public class User {
private String name;
private int age;
private Address address;
private List<String> hobbies;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
public List<String> getHobbies() { return hobbies; }
public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }
}
// 使用
public class Main {
public static void main(String[] args) {
User user = new User();
user.setName("张三");
user.setAge(25);
Address address = new Address();
address.setProvince("广东省");
address.setCity("深圳市");
address.setStreet("科技路");
user.setAddress(address);
List<String> hobbies = new ArrayList<>();
hobbies.add("游泳");
hobbies.add("阅读");
user.setHobbies(hobbies);
System.out.println(user.getName());
}
}
Kotlin DSL 风格
kotlin复制代码
data class Address(
var province: String = "",
var city: String = "",
var street: String = ""
)
data class User(
var name: String = "",
var age: Int = 0,
var address: Address = Address(),
var hobbies: MutableList<String> = mutableListOf()
)
// DSL 构建函数
fun user(block: User.() -> Unit): User = User().apply(block)
fun User.address(block: Address.() -> Unit) {
address = Address().apply(block)
}
// 使用
fun main() {
val user = user {
name = "张三"
age = 25
address {
province = "广东省"
city = "深圳市"
street = "科技路"
}
hobbies = mutableListOf("游泳", "阅读")
}
println(user.name)
println(user.address.city)
}
// Java 只有普通 Lambda(Java 8+)
// 没有带接收者的 Lambda
// Java 实现
public class Person {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
public class PersonBuilder {
public static void withPerson(Person person, Consumer<Person> block) {
block.accept(person);
}
}
// 使用
public class Main {
public static void main(String[] args) {
Person person = new Person();
PersonBuilder.withPerson(person, p -> {
p.setName("张三"); // 必须用参数名 p
p.setAge(20);
});
}
}
Kotlin 实现
kotlin复制代码
data class Person(
var name: String = "",
var age: Int = 0
)
fun person(block: Person.() -> Unit): Person {
return Person().apply(block)
}
// 使用
fun main() {
val person = person {
name = "张三" // 直接访问,不需要参数名
age = 20
}
}
对比总结
特性
Java
Kotlin
Lambda 类型
(T) -> Unit
T.() -> Unit
调用方式
block.accept(receiver)
receiver.block()
内部访问
p.setName("张三")
name = "张三"
语法糖
❌ 无
✅ this 可省略
3.2 扩展函数(Extension Function)
Java 对比
java复制代码
// Java:必须写工具类
public class StringUtils {
public static boolean isNotEmpty(String str) {
return str != null && !str.isEmpty();
}
}
// 使用
public class Main {
public static void main(String[] args) {
String name = "张三";
boolean result = StringUtils.isNotEmpty(name);
}
}
Kotlin 实现
kotlin复制代码
// Kotlin:扩展函数
fun String.isNotEmpty(): Boolean {
return this != null && this.isNotEmpty()
}
// 使用
fun main() {
val name = "张三"
val result = name.isNotEmpty() // 像调用成员方法一样
}
在 DSL 中的应用
kotlin复制代码
// 为 String 添加 DSL 风格的扩展函数
fun String.ifNotEmpty(block: (String) -> Unit) {
if (this.isNotEmpty()) {
block(this)
}
}
// 使用
fun main() {
val name = "张三"
name.ifNotEmpty {
println("名字是: $it")
}
}
对比总结
特性
Java
Kotlin
实现方式
工具类静态方法
扩展函数
调用方式
Utils.method(obj)
obj.method()
语法体验
函数调用
像成员方法
3.3 Lambda 在括号外
Java 对比
java复制代码
// Java:Lambda 必须在括号内
public class Main {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
// Lambda 必须在括号内
list.forEach(item -> System.out.println(item));
}
}
Kotlin 实现
kotlin复制代码
fun main() {
val list = listOf("a", "b", "c")
// 方式1:Lambda 在括号内
list.forEach({ item -> println(item) })
// 方式2:Lambda 在括号外(语法糖)
list.forEach { item ->
println(item)
}
// 方式3:如果只有一个参数,可用 it
list.forEach { println(it) }
}
在 DSL 中的应用
kotlin复制代码
data class Person(var name: String = "", var age: Int = 0)
// 如果最后一个参数是 Lambda,可以放在括号外
fun person(block: Person.() -> Unit): Person = Person().apply(block)
fun main() {
// 这些写法都等价
val p1 = person({ name = "张三" }) // Lambda 在括号内
val p2 = person() { name = "张三" } // Lambda 在括号外
val p3 = person { name = "张三" } // 括号可省略
}
对比总结
特性
Java
Kotlin
Lambda 位置
必须在括号内
可在括号外
空括号处理
必须写 ()
可省略 ()
DSL 友好度
❌ 一般
✅ 非常友好
3.4 中缀函数(Infix Function)
Java 对比
java复制代码
// Java:只能用普通方法调用
public class Pair {
private String first;
private String second;
public Pair(String first, String second) {
this.first = first;
this.second = second;
}
public String getFirst() { return first; }
public String getSecond() { return second; }
}
// 使用
public class Main {
public static void main(String[] args) {
Pair pair = new Pair("key", "value");
System.out.println(pair.getFirst());
}
}
Kotlin 实现
kotlin复制代码
// 中缀函数
infix fun String.to(that: String): Pair<String, String> {
return Pair(this, that)
}
// 使用
fun main() {
// 普通调用
val pair1 = "key".to("value")
// 中缀调用(更接近自然语言)
val pair2 = "key" to "value"
println(pair2.first) // key
}
在 DSL 中的应用
kotlin复制代码
// Map 构建
fun main() {
// 普通写法
val map1 = mapOf(Pair("name", "张三"), Pair("age", "20"))
// 中缀函数 DSL 风格
val map2 = mapOf(
"name" to "张三",
"age" to "20"
)
println(map2["name"])
}
对比总结
特性
Java
Kotlin
调用语法
obj.method(arg)
obj method arg
自然语言感
❌ 无
✅ 像 "key to value"
DSL 友好度
❌ 一般
✅ 非常友好
3.5 操作符重载(Operator Overloading)
Java 对比
java复制代码
// Java:不支持操作符重载
public class Money {
private int amount;
public Money(int amount) {
this.amount = amount;
}
public int getAmount() { return amount; }
// 只能用普通方法
public Money add(Money other) {
return new Money(this.amount + other.amount);
}
}
// 使用
public class Main {
public static void main(String[] args) {
Money m1 = new Money(100);
Money m2 = new Money(50);
Money total = m1.add(m2); // 只能调用方法
}
}
Kotlin 实现
kotlin复制代码
data class Money(val amount: Int) {
// 操作符重载
operator fun plus(other: Money): Money {
return Money(this.amount + other.amount)
}
operator fun minus(other: Money): Money {
return Money(this.amount - other.amount)
}
}
// 使用
fun main() {
val m1 = Money(100)
val m2 = Money(50)
val total = m1 + m2 // 使用 + 操作符
val diff = m1 - m2 // 使用 - 操作符
println(total.amount) // 150
}
在 DSL 中的应用
kotlin复制代码
data class Path(val segments: MutableList<String> = mutableListOf()) {
operator fun String.unaryPlus() {
segments.add(this)
}
operator fun plus(other: Path): Path {
return Path((segments + other.segments).toMutableList())
}
}
fun path(block: Path.() -> Unit): Path = Path().apply(block)
// 使用
fun main() {
val p = path {
+"home"
+"user"
+"documents"
}
println(p.segments) // [home, user, documents]
}
对比总结
特性
Java
Kotlin
操作符重载
❌ 不支持
✅ 支持
调用方式
m1.add(m2)
m1 + m2
DSL 友好度
❌ 差
✅ 好
四、Java vs Kotlin 实现 DSL 完整对比
4.1 场景:构建 HTML
Java 实现
java复制代码
import java.util.ArrayList;
import java.util.List;
// HTML 标签基类
public abstract class HtmlElement {
protected String tagName;
protected List<HtmlElement> children = new ArrayList<>();
protected String textContent;
public void addChild(HtmlElement element) {
children.add(element);
}
public void setText(String text) {
this.textContent = text;
}
public abstract String render();
}
// Div 标签
public class Div extends HtmlElement {
public Div() {
this.tagName = "div";
}
@Override
public String render() {
StringBuilder sb = new StringBuilder();
sb.append("<").append(tagName).append(">");
if (textContent != null) {
sb.append(textContent);
}
for (HtmlElement child : children) {
sb.append(child.render());
}
sb.append("</").append(tagName).append(">");
return sb.toString();
}
}
// P 标签
public class P extends HtmlElement {
public P() {
this.tagName = "p";
}
@Override
public String render() {
return "<p>" + (textContent != null ? textContent : "") + "</p>";
}
}
// HTML 构建器
public class HtmlBuilder {
private Div root;
public HtmlBuilder() {
this.root = new Div();
}
public HtmlBuilder div(Consumer<Div> block) {
Div div = new Div();
block.accept(div);
root.addChild(div);
return this;
}
public HtmlBuilder p(String text) {
P p = new P();
p.setText(text);
root.addChild(p);
return this;
}
public String build() {
return root.render();
}
}
// 使用
public class Main {
public static void main(String[] args) {
HtmlBuilder builder = new HtmlBuilder();
String html = builder
.div(div -> {
div.addChild(new P());
// 很难继续嵌套...
})
.p("Hello World")
.build();
System.out.println(html);
}
}
Kotlin DSL 实现
kotlin复制代码
// HTML 标签基类
open class Tag(val name: String) {
val children = mutableListOf<Tag>()
val attributes = mutableMapOf<String, String>()
fun <T : Tag> initTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
override fun toString(): String {
val attrs = if (attributes.isEmpty()) "" else attributes.entries.joinToString(" ") { "${it.key}=\"${it.value}\"" }
val content = children.joinToString("")
return "<$name $attrs>$content</$name>"
}
}
// 具体标签
class HTML : Tag("html") {
fun head(init: HEAD.() -> Unit) = initTag(HEAD(), init)
fun body(init: BODY.() -> Unit) = initTag(BODY(), init)
}
class HEAD : Tag("head") {
fun title(init: TITLE.() -> Unit) = initTag(TITLE(), init)
}
class TITLE : Tag("title")
class BODY : Tag("body") {
fun div(init: DIV.() -> Unit) = initTag(DIV(), init)
fun p(init: P.() -> Unit) = initTag(P(), init)
}
class DIV : Tag("div") {
fun p(init: P.() -> Unit) = initTag(P(), init)
fun span(init: SPAN.() -> Unit) = initTag(SPAN(), init)
}
class P : Tag("p") {
operator fun String.unaryPlus() {
children.add(Text(this))
}
}
class SPAN : Tag("span")
class Text(private val text: String) : Tag("") {
override fun toString() = text
}
// DSL 入口函数
fun html(init: HTML.() -> Unit): HTML {
return HTML().apply(init)
}
// 使用
fun main() {
val result = html {
head {
title {
// 标题内容
}
}
body {
div {
p {
+"Hello World"
}
p {
+"This is a paragraph"
}
}
div {
p {
+"Another paragraph"
}
}
}
}
println(result)
}
4.2 场景:构建 SQL 查询
Java 实现
java复制代码
import java.util.ArrayList;
import java.util.List;
public class SqlBuilder {
private String tableName;
private List<String> columns = new ArrayList<>();
private List<String> whereConditions = new ArrayList<>();
private String orderBy;
private Integer limit;
public SqlBuilder select(String... cols) {
for (String col : cols) {
columns.add(col);
}
return this;
}
public SqlBuilder selectAll() {
columns.add("*");
return this;
}
public SqlBuilder from(String table) {
this.tableName = table;
return this;
}
public SqlBuilder where(String condition) {
whereConditions.add(condition);
return this;
}
public SqlBuilder orderBy(String column) {
this.orderBy = column;
return this;
}
public SqlBuilder limit(int n) {
this.limit = n;
return this;
}
public String build() {
StringBuilder sb = new StringBuilder();
sb.append("SELECT ");
if (columns.isEmpty()) {
sb.append("*");
} else {
sb.append(String.join(", ", columns));
}
sb.append(" FROM ").append(tableName);
if (!whereConditions.isEmpty()) {
sb.append(" WHERE ");
sb.append(String.join(" AND ", whereConditions));
}
if (orderBy != null) {
sb.append(" ORDER BY ").append(orderBy);
}
if (limit != null) {
sb.append(" LIMIT ").append(limit);
}
return sb.toString();
}
}
// 使用
public class Main {
public static void main(String[] args) {
String sql = new SqlBuilder()
.select("id", "name", "age")
.from("users")
.where("age > 18")
.where("status = 'active'")
.orderBy("name")
.limit(10)
.build();
System.out.println(sql);
// SELECT id, name, age FROM users WHERE age > 18 AND status = 'active' ORDER BY name LIMIT 10
}
}
Kotlin DSL 实现
kotlin复制代码
class SqlBuilder {
private var tableName = ""
private val columns = mutableListOf<String>()
private val whereConditions = mutableListOf<String>()
private var orderByClause: String? = null
private var limitValue: Int? = null
fun select(vararg cols: String) {
columns.addAll(cols)
}
fun selectAll() {
columns.add("*")
}
fun from(table: String) {
tableName = table
}
fun where(condition: String) {
whereConditions.add(condition)
}
fun orderBy(column: String) {
orderByClause = column
}
fun limit(n: Int) {
limitValue = n
}
fun build(): String {
val cols = if (columns.isEmpty()) "*" else columns.joinToString(", ")
val where = if (whereConditions.isNotEmpty()) {
" WHERE ${whereConditions.joinToString(" AND ")}"
} else ""
val order = orderByClause?.let { " ORDER BY $it" } ?: ""
val lim = limitValue?.let { " LIMIT $it" } ?: ""
return "SELECT $cols FROM $tableName$where$order$lim"
}
}
// DSL 函数
fun sql(block: SqlBuilder.() -> String): String {
val builder = SqlBuilder()
builder.block()
return builder.build()
}
// DSL 扩展函数
fun SqlBuilder.select(block: SelectBuilder.() -> Unit) {
val selectBuilder = SelectBuilder()
selectBuilder.block()
columns.addAll(selectBuilder.columns)
}
class SelectBuilder {
val columns = mutableListOf<String>()
operator fun String.unaryPlus() {
columns.add(this)
}
}
// 使用
fun main() {
// 简单 DSL
val sql1 = sql {
select("id", "name", "age")
from("users")
where("age > 18")
where("status = 'active'")
orderBy("name")
limit(10)
build()
}
println(sql1)
// 更优雅的 DSL(使用 + 操作符)
val sql2 = sql {
select {
+"id"
+"name"
+"age"
}
from("users")
where("age > 18")
where("status = 'active'")
orderBy("name")
limit(10)
build()
}
println(sql2)
}