
多年以前我看到一篇神奇的文章 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 你说的这些优点是确实存在的,你用的这个 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 呃呃,既然追求代码简洁,为什么不试试神奇的 kotlin 呢?  |
3 zbatman 2022-08-31 18:32:00 +08:00 有请双方辩手入场 |
4 hccsoul 2022-08-31 18:38:10 +08:00 我先来 ,java 是世界上最优秀的语言,杠我的去和楼主对线 / |
5 imzcg2 2022-08-31 18:39:33 +08:00 不能自动写代码完成任务的都不是最优秀的图灵完备语言/div> |
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 lllllliiii 2022-08-31 19:37:41 +08:00 然后这个写 Java for everything 的人的 github 的置顶项目没有一个 Java 写的。太搞了哈哈。 |
12 wuxqing 2022-08-31 19:55:32 +08:00 如果不搞 spring 那个体系,https://solon.noear.org/ 这个看着也很简洁。 |
13 lllllliiii 2022-08-31 20:02:41 +08:00 @wuxqing #12 solon 就代码组织形式跟 spring 就什么区别吗? |
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 @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 keepfun 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 EthanZC 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 很方便。 |