关于 Java 很啰嗦的问题

2022-05-12 12:19:17 +08:00
 Joker123456789

我先声明啊,我不是来吹捧 java 的,我只是想说一个事实,编程语言 没有谁绝对的碾压谁,真遇到了实际业务需求,写出来的代码量绝对是半斤八两。

我希望大家 在 吐槽一门语言的时候,可以理性一点,不要瞎喷。这篇文章的用意就在于此。

还有一点,我用 go 来比较,是因为 go 擅长的场景,跟 java 有一定的重叠,有很多公司都用 go 开发 web 。绝对没有对 go 不敬的意思。

首先目录问题

总结下来,从工作量的角度来看,就是多了一个倒置的域名而已,而且只需要花建一层目录的时间,并且这个倒置的域名 是有他的意义在里面的,你们可以把他看做是这个

// go 语言里的 import ,前面也有一个域名+项目名 来确定唯一性,包名里的倒置域名就是起这个作用的
import "github.com/scan-util/xxx/xxx"

还有很重要的一点,你们喷来喷去的那些多余的目录结构,在我们的观念里 根本就不存在,因为从来没有手工去创建过,要不是你们来吐槽,我们还真想不到这一点。

不是因为 习惯了,而是真的从来没有为他们花过 5 秒钟以上的时间。有的连一毫秒都没花过。

方法语法

go

func BytesToString(val []byte) string

java

public String BytesToString(byte[] val)

我真没看出来多了什么东西

定义变量

go

name := "张三";

var map = make(map[string]interface{})
var array = make(string[], 10);

java

String name = "张三";

Map<String, Object> map = new HashMap<>();
String[] array = new String[10];

好像多了点东西,又好像没多什么。

循环

go

for(i:=0;i<100;i++){

}

for(i<100){

}

java

for(int i=0;i<100;i++){

}

while(i<100){

}

确实多了几个字母。

创建类

go

我知道这叫结构体,跟类是两码事,但是 go 就是用它来兼容 oop 的,所以我只能用它来举例子,因为没有其他语法可以实现 oop 了

type DemoParam struct {
    name string
}

func (demoParam *DemoParam) FormValues(key string) []string {
}

java

class DemoParam {
    public String name;
    
    public String[] FormValues(String key){
        
    }
}

字数上相差多少,我是懒得数了,但是你们真的不觉得 java 的结构更清晰吗? 其他的继承,多态 我就不拿出来说了,go 基本上是 用的 c 的编程思想,oop 只是个兼容, 所以用 java 来跟他比 oop 没什么可比性。因为是两个方向。

异常处理

go


func testFunction(paramStr string) (string, error) {
    if xxx {
        return Errors.New("xxxx");
    }
}

paramStr, err := testFunction("ok")                              
if err != nil {                           
    log.Println(err.Error())                           
}

java

public String testFunction(String paramStr){
    if (xxx) {
        throw new Execption("xxx");
    }
}

try {
    String paramStr = testFunction("ok");
} catch(Execption e){
    log.Println(e.getMessage); 
}

这个看起来 go 好像 舒服一点,但是,实际场景下 go 经常是这种姿势

paramStr, err := testFunction("ok")                              
if err != nil {                           
    log.Println(err.Error())                           
}

paramStr, err := testFunction2("ok")                              
if err != nil {                           
    log.Println(err.Error())                           
}

paramStr, err := testFunction3("ok")                              
if err != nil {                           
    log.Println(err.Error())                           
}

而 java 还是只需要这样

try {
    String paramStr = testFunction("ok");
    String paramStr = testFunction2("ok");
    String paramStr = testFunction3("ok");
} catch(Execption e){
    log.Println(e.getMessage); 
}

并且这是 经过人为判断后,返回的错误提示,如果是意外的异常呢? go 里面叫 panic ,java 只要用 try catch 包住了 就可以捕获,但是 go 需要用 defer ,而且一旦抛出异常就意味着这个函数结束了,你如果想在出异常后,处理一下 然后继续往下走,go 会非常的麻烦。

拆箱

go

// 如果有一个 interface{} 类型的变量 a ,想转成 int
// 你必须明确的知道,他装箱前就是 int ,不然根本没法拆,必须做一下类型判断。
// 我之前在写框架的时候 就被折磨的够呛,一大堆不必要的 if

java

// 不管装箱前是什么,只要他的值是一个整数
// 无论是 1 , 还是 "1", 都可以这么转
Integer aInt = Integer.parseInteger(a.toString());

// 也可以直接拆成 String
a.toString();

如果你们还不服,那很好办,

你们出一个需求给我,我用 java ,你们用 go ,nodejs ,python ,php 随便什么语言,最后来比比 谁的代码少一些。 我敢说,绝对半斤八两,不可能有谁碾压谁的。

而且还有一定的概率,java 在 丰富的生态+强大官方库的 加持下,可以更快完成。

20891 次点击
所在节点    Java
257 条回复
lisongeee
2022-05-12 13:36:08 +08:00
我就加一个限制,强制明确编译期变量的空状态
java 就得手动加 if(var!=null&&var.k1!=null&&var.k1.k2!=null){var.k1.k2()}
kotlin 只需要 var?.k1?.k2()
Joker123456789
2022-05-12 13:36:21 +08:00
@lisongeee 我不反驳你,不知道你是否可以提供一段代码。
Joker123456789
2022-05-12 13:37:15 +08:00
@lisongeee 你说的 kotlin 的例子,可以看 你的上一层,我刚举了个例子。
Bazingal
2022-05-12 13:38:00 +08:00
“随便什么语言”,话说得太大了,哪位老哥来个 C#的,什么属性、linq 、泛型、模式匹配、switch 表达、可空类型、null 条件运算符、空合并操作符都给他整上
billlee
2022-05-12 13:38:04 +08:00
比代码少那 kotlin 和 scala 就不服了
clownpiece
2022-05-12 13:38:09 +08:00
@Alexliu
new ObjectMapper().readTree(...).path("data").path("person").path("meta").path("address").path("nation").asText("").equals("印度尼西亚")
有什么问题吗
Kinnice
2022-05-12 13:39:38 +08:00
需求:在指定网口上,丢弃 GFW DNS 污染包(即获取到正常干净的 dns 解析结构)

Rust: https://raw.githubusercontent.com/ihciah/clean-dns-bpf/master/src/clean_dns.rs

期待 ing
lisongeee
2022-05-12 13:44:23 +08:00
@Joker123456789 我看了你的例子,你这个例子只有一成属性,实际上我们在使用的过程里会有多层属性,按照你的说法我们岂不是针对每个属性的空都要出逻辑?那岂不是变成了 2^n 个逻辑了?但是实际上我们在写代码的时候往往只是看看这个最终的属性是不是 null 即可,这么说吧, java 和 kotlin 实现你的例子是相同的代码,但是实现我的例子就明显不是一个量级的代码
silentsky
2022-05-12 13:44:32 +08:00
@lisongeee 可以这样 Optional.ofNullable(var).map(o->o.k1()).map(o->o.k2()).orElse(null);
abctt
2022-05-12 13:44:55 +08:00
@lisongeee 写 spring 代码和 Java 没区别,安卓没写过不知道。
zilongzixue
2022-05-12 13:45:17 +08:00
有一说一用 go 做 web 开发和 java 比简直被碾压
number
2022-05-12 13:46:43 +08:00
Y-Combinator 计算斐波那契数列

js 版:

```js
(gen => (g => g(g))(f => n => gen(f(f))(n)))(f => n => n > 1 ? f(n - 1) + f(n - 2) : n)(10)
```

go 版:

```go
package main

import (
"fmt"
)

type (
commFunc func(int) int
genFunc func(commFunc) commFunc
recurseFunc func(recurseFunc) commFunc
)

func Y(gen genFunc) commFunc {
return func(g recurseFunc) commFunc {
return g(g)
}(func(f recurseFunc) commFunc {
return func(n int) int {
return gen(f(f))(n)
}
})
}

func fibGen(f commFunc) commFunc {
return func(n int) int {
if n == 0 {
return 0
} else if n == 1 {
return 1
} else {
return f(n-2) + f(n-1)
}
}
}

func main() {
fmt.Println(Y(fibGen)(10))
}
```
timpaik
2022-05-12 13:47:53 +08:00
golang 每次都要判断有没有错误的原因就是为了尽可能的消除异常,如果真 panic 了那大概率是没法恢复的,go 要求你在实际业务中处理每一个可能出现的错误。
楼主用过 Goland 的话应该会知道,开发体验其实和 Java 差不多的。
很多人觉得 java 啰嗦,不是代码的问题,其实也不是 java 的问题,而是 java 生态里各种写代码前的配置:java 要引入一个包,你得用 gradle ,还没写一行代码就快 7 个文件:

src/main/java/com/example/exampleproj/main.java
gradlew
gradlew.bat
gradle/wapper 文件夹
build.gradle
settings.gradle


golang 这种自带包管理的就一个 main.go 、go.mod 和 lock 文件就行。
如果你说你用 IDE ,这种东西不需要你写,从来没管过,那就是你对,不杠。
pengtdyd
2022-05-12 13:48:16 +08:00
从来没有敢说 C 有问题,因为他们知道那是他们唯一的选择!!!
SeaTac
2022-05-12 13:48:29 +08:00
2022 年了还能在这里看到为了语言吵架的
还是工作不够饱和
DreamSaddle
2022-05-12 13:48:58 +08:00
喷 java 差的有本事自己去实现一门比它牛的再来喷,好吧。
没有像 Linus Torvalds 那样的功底就别学人家那样 fuck you nvida.
zhengsidao
2022-05-12 13:50:23 +08:00
口水战有什么意思...
大数据后端常年用 java 写,文件目录是为了更好的归纳不同类型的内容,没觉得有多麻烦。。
判定语言的好坏如果是用文件目录的话,我建议还是去用 excel 来写文档吧
lisongeee
2022-05-12 13:51:28 +08:00
java 确实生态和历史沉淀很强大,但是要比新语法和代码量少,这点必须是被 kotlin 按在地上摩擦,就拿 kotlin 的 setter 和 getter ,你 java 调用的时候是 obj.setKey(value)/ obj.getKey(),kotlin 是 obj.key = value/ obj.key , 代码量是不是少了一个层级??还有,java 的 settter 并不是完全封装的, class 内部还是可以绕过 setKey 去修改 key, 但是 kotlin 已经从语法层级决定每个 赋值操作必须走 setter ,在这个层级 java 拿什么和 kotlin 比?
Leviathann
2022-05-12 13:52:08 +08:00
终于有 showcase 了,之前一直看空对空的嘴炮早看腻了
passer9527
2022-05-12 13:53:33 +08:00
强烈支持楼主,甚至可以帮楼主提供代码,说这么多有锤子用,有本事说需求,然后你用 xxx 语言,我用 java ,我们来比一下。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/852381

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX