多年以前我看到一篇神奇的文章 Java for Everything, 其中提出了一个大胆的想法:就连脚本小工具都用 Java 来写。
我读了这篇文章,但并没有立即使用 Java, 而是写了一段时间 Go, 又写了一段时间 Python, 最近想起这篇文章,就想用 Java 写点东西。
本来 Java 是很啰嗦的,这是它最被诟病的地方了。
但现在 Java 有了 record, lambda, Stream API, var(类型推断) 等等, 已经变得不是太啰嗦了,根据我狭隘的个人经验,甚至认为比 Go, Python 更简洁。
if err != nil
, 代码是很简明易懂,
但论代码的简短,也是经常比不上 Java 。以前我喜欢用 Go 来做一些自用的小软件,做一个本地网站通过访问网页来使用, 最近想做一个叫 monostich 的小工具,就尝试用 Java 来做。
monostich 的功能非常简单。
这次我用 Javalin 来做本地网站,并且采用了以前我写 Go 时的代码组织方式, 因此两种语言可以做个对比。
可见, Go 与 Java 的代码几乎一模一样:
// github.com/ahui2016/dictplus/blob/main/main.go
func main() {
e := echo.New()
e.Static("/public", "public")
e.File("/", "public/index.html")
api := e.Group("/api", sleep)
api.POST("/get-word", getWordHandler)
api.POST("/add-word", addWordHandler)
api.POST("/update-word", updateWordHandler)
api.POST("/delete-word", deleteWordHandler)
api.POST("/search-words", searchHandler)
e.Logger.Fatal(e.Start(*addr))
}
// github.com/ahui2016/monostich/.../App.java
public class App {
public static void main(String[] args) {
Javalin app = Javalin.create(config ->
config.addStaticFiles(staticFiles -> {
staticFiles.hostedPath = "/";
staticFiles.directory = "/public";
staticFiles.location = Location.CLASSPATH;
})).start(port);
app.post("/api/insert-poem", Handle.insertPoem);
app.post("/api/update-poem", Handle.updatePoem);
app.post("/api/delete-poem", Handle.deletePoem);
app.post("/api/get-poem", Handle.getPoem);
app.post("/api/search-poems", Handle.searchPoems);
}
}
可见, Go 比 Java 多了一些 if err != nil
, 其余代码几乎一模一样:
// github.com/ahui2016/dictplus/blob/main/handler.go
func addWordHandler(c echo.Context) error {
w := new(Word)
if err := c.Bind(w); err != nil {
return err
}
if err := db.InsertNewWord(w); err != nil {
return err
}
return c.JSON(OK, Text{w.ID})
}
// github.com/ahui2016/monostich/.../Handle.java
static Handler insertPoem = ctx -> {
var form = ctx.bodyAsClass(PoemForm.class);
var poem = db.insertPoem(form);
ctx.json(poem);
};
在上面 Handler 的代码中, db.InsertNewWord() 与 db.insertPoem() 的具体实现如下所示。
可以看到, Go 的代码还是受到了 if err != nil
的困扰,显得很啰嗦,
而 Java 采用 Stream API 的好处是非常明显的,代码简洁了很多。
// github.com/ahui2016/dictplus/.../database.go
func (db *DB) InsertNewWord(w *Word) (err error) {
tx := db.mustBegin()
defer tx.Rollback()
if w.ID, err = getNextID(tx, word_id_key); err != nil {
return
}
w.CTime = util.TimeNow()
if err = insertWord(tx, w); err != nil {
return
}
err = tx.Commit()
return
}
// github.com/ahui2016/monostich/.../DB.java
Poem insertPoem(PoemForm form) {
return jdbi.withHandle(handle -> handle.inTransaction(h -> {
var poem = new Poem(getNextId(h), form.title(), form.stich(), Util.now());
h.createUpdate(Stmt.INSERT_POEM)
.bindMap(poem.toMap())
.execute();
return poem;
}));
}
本软件后端采用 Javalin, 前端采用 mj.js, 相关介绍请看以下链接。
1
qW7bo2FbzbC0 2022-08-31 18:12:31 +08:00 4
你说的这些优点是确实存在的,你用的这个 lin 框架比 spring 简洁, 同时我觉得 C#比 Java 走更多一步。甚至不需要额外的三方 web 框架
https://docs.microsoft.com/en-us/aspnet/core/tutorials/min-web-api ``` var builder = WebApplication.CreateBuilder(args); // Add services to the container. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; app.MapGet("/weatherforecast", () => { var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast ( DateTime.Now.AddDays(index), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)] )) .ToArray(); return forecast; }) .WithName("GetWeatherForecast"); app.Run(); internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary) { public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); } ``` |
2
lisongeee 2022-08-31 18:24:16 +08:00 3
呃呃,既然追求代码简洁,为什么不试试神奇的 kotlin 呢?
![image]( https://user-images.githubusercontent.com/38517192/187657094-4f610b00-e0fb-4e7c-a5e1-914a06ce019e.png) |
3
zbatman 2022-08-31 18:32:00 +08:00 3
有请双方辩手入场
|
4
hccsoul 2022-08-31 18:38:10 +08:00
我先来 ,java 是世界上最优秀的语言,杠我的去和楼主对线 /🐶
|
5
imzcg2 2022-08-31 18:39:33 +08:00
不能自动写代码完成任务的都不是最优秀的图灵完备语言
|
6
justanetizen 2022-08-31 19:13:42 +08:00
呃,java 8 连 UTF8 处理起来都麻烦,不知道你们为毛还要抱残守缺。
|
7
WispZhan 2022-08-31 19:13:46 +08:00 via Android
为什么不看看其他 JVM 语言呢?
|
8
dqzcwxb 2022-08-31 19:21:40 +08:00
@justanetizen #6 细说
|
9
zed1018 2022-08-31 19:28:23 +08:00
如果一定要 everything 我选择 kotlin ,java 有的我都有,我有的 java 真不一定现在就有,而且 non-nullable type 这个对我来讲太刚需
|
10
SuperMild OP @qW7bo2FbzbC0 一直听说 C# 的优秀,以后找个机会研究研究学习学习。
@lisongeee kotlin 用了更多函数式编程方法,我脑子不太够用,总觉得 kotlin 用起来反而比 java 更累,java 还是比较直白的。 |
11
fzdwx 2022-08-31 19:37:41 +08:00 1
然后这个写 Java for everything 的人的 github 的置顶项目没有一个 Java 写的。太搞了哈哈。
|
12
wuxqing 2022-08-31 19:55:32 +08:00
如果不搞 spring 那个体系,https://solon.noear.org/ 这个看着也很简洁。
|
14
cyningxu 2022-08-31 20:10:10 +08:00
kotlin ,你是我的神!
|
15
Veneris 2022-08-31 20:16:11 +08:00 via iPhone
go 打成二进制包就可以了,java 需要 jre ,不过反过来说 java 因此也是跨平台的了,这一点是优点还是缺点见仁见智
但是 java 打出来的包体积,启动后的内存占,普遍要大一些,有时候我只是想写个玩具项目而已,总给我一种很笨重的感觉 另外,kotlin 可以 native 了,不过还没有具体尝试过 |
16
Leviathann 2022-08-31 20:20:57 +08:00
@Veneris kotlin 的 native ,目前还不如借助 graalvm 的 jvm native
|
17
proxychains 2022-08-31 20:21:53 +08:00
我先来
感觉不如 php...java |
19
TWorldIsNButThis 2022-08-31 20:30:25 +08:00
@SuperMild 恩 习惯 kotlin 的 lambda 算是一个坎,lambda 也是 kotlin 语法魔术的核心
另外 kotlin 也比较推崇灵活变换隐含的 receiver 来实现更接近自然语言的表达 |
20
Huelse 2022-08-31 20:41:40 +08:00
来体验下 scala fp 吧
|
21
makelove 2022-08-31 21:03:31 +08:00
java 还是不太行,很多年没写过 java 了,当年觉得 java 实在算不上好用,比如没有关键字参数,不知道现在有没有了
|
22
wdhwg001 2022-09-01 06:34:27 +08:00 via iPhone 1
@qW7bo2FbzbC0 我私底下觉得这纯属微软管太宽了,啥都是第一方的,所以社区没有造轮子的热情。
这个策略本身就不对,正确的是把基础的打好,然后 fund 一些好的第三方框架,出钱出力去帮忙补测试覆盖,提升性能和出钱 audit 代码。 |
23
CodeCodeStudy 2022-09-01 09:10:55 +08:00
java17 支持多行字符串了吗
|
25
qinxi 2022-09-01 09:58:40 +08:00
@CodeCodeStudy #23 该更新了 https://openjdk.org/jeps/378
|
26
fenglangjuxu 2022-09-01 10:36:38 +08:00
看了下 好牛逼 和 spring boot 完全两个样子
和 go 挺像的 |
27
fgwmlhdkkkw 2022-09-01 10:39:03 +08:00
那你有什么理由拒绝 kotlin 呢?还有 async 用。
|
28
CodeCodeStudy 2022-09-01 10:41:17 +08:00
@qinxi #25 感谢! 20 年才搞这个,晚了点吧,早就该推出来了
|
29
promisenev 2022-09-01 14:32:35 +08:00
scala YYDS
|
30
wetalk 2022-09-01 15:17:12 +08:00
Kotlin ,Scala ,Groovy 任君挑选
|
31
SuperMild OP @fenglangjuxu 是呀,我从 Go 转过来感觉很舒服。但如果正经项目还是用 spring boot 比较好,业余小项目用 Javalin 很方便。
|