1
bololobo 2021-10-25 21:50:50 +08:00
能显得比较厉害。别人问我为什么要这样写,我就会说 你看源码也这样写
|
2
monster1priest OP @bololobo hashmap 就是这么写的。人家应该不是为了炫耀吧
|
3
BBCCBB 2021-10-25 21:53:41 +08:00
一般是
int a; if (xxx && (a=getNumber() > 0)) 这样吧, 不能只有一个条件也 f((a=getNumber()) >0)/ |
4
cmdOptionKana 2021-10-25 22:31:04 +08:00 6
有 C 语言背景可能会习惯这样写
|
5
rannnn 2021-10-25 22:36:23 +08:00
这么写一般是在 while 里吧
|
6
zardmyLove 2021-10-25 22:51:57 +08:00
我的想法是显得紧凑
|
7
zjsxwc 2021-10-25 22:52:32 +08:00 via Android 3
因为这个变量 a 只是单纯想在 if 条件中使用?
而 if 的 condition 里不能 declare 变量 a 类型,不得不挪到外面。 https://stackoverflow.com/questions/16148580/assign-variable-value-inside-if-statement |
8
zjsxwc 2021-10-25 22:53:51 +08:00 via Android
感觉,莫名好笑😄
|
9
546L5LiK6ZOt 2021-10-25 23:56:42 +08:00 4
我记得很多类库还有一个常见的写法,就是在一个方法里,把类的成员变量赋值给局部变量,方法里都使用这个局部变量,而不直接用成员变量。例如:
class A { int a; void func() { int a = this.a; // …… } } 后来看到一种解释,说访问方法里成员变量不利于运行时优化(至少局部变量肯定是线程安全的)。 我记得 jdk 的类库里还经常看到这么种情况,明明这两个循环可以写在一起,合并成一个循环,但是却特地分开写。一种解释说,小的循环容易让 cpu 命中 cache ,执行更快。。。 总之,类库总有些特殊的写法,跟写业务代码不一样 |
10
mritd 2021-10-26 01:28:45 +08:00 via iPhone
@546L5LiK6ZOt #9 这种好像是为了满足那些 get set 规范
|
11
Jooooooooo 2021-10-26 01:39:44 +08:00
这是习惯问题
两种写法还能用性能差异那是 jvm 有毛病 |
12
chendy 2021-10-26 08:25:08 +08:00
没啥好处,甚至不太好读
是源码还是反编译?反编译的话经常看到一些奇怪的写法,但是都是编译器优化导致的 |
13
rpish 2021-10-26 08:27:36 +08:00
|
14
yidinghe 2021-10-26 08:37:10 +08:00 via Android
不看上下文的话,每次都这么写是脱裤子放屁,但确实有合理使用的场景,一般都是在 IO 流读取时出现。
|
15
Cbdy 2021-10-26 08:40:33 +08:00
IO 时会这样写,C 语言延续下来的传统,我记得 Unix 高程称赞过这种写法
|
16
Leviathann 2021-10-26 09:16:41 +08:00 via iPhone
这就是 c 味
反正我挺不喜欢的 |
18
aguesuka 2021-10-26 09:24:28 +08:00
就是 4 楼的说法, 请相信这种简单的优化, 编译器比人更聪明.
|
19
bk201 2021-10-26 09:37:59 +08:00
语意应该浅显易懂,我觉得源码这处不行
|
20
cubecube 2021-10-26 09:38:23 +08:00
@aguesuka 然而有时候编译器并不会更聪明。
javac 近些年几乎保持不变。很多 jdk 的代码的确有部分优化,至于这种方式是否有神秘性能加成,回头可以分析下。 |
21
wolfie 2021-10-26 09:43:11 +08:00
简洁啊。
举例不对,这个例子没有任何必要。 |
22
cpstar 2021-10-26 09:50:33 +08:00
从编译出的 bytecode 上,这两个没差别,也无所谓性能调优。
都是先 invoke 再 ifgt 。 如果说性能调优,那就是 9#说的问题,局部变量,不需要每次都 invoke——当然编译器也可能自动识别并且加上一个局部变量压栈 |
23
yinzhili 2021-10-26 09:56:19 +08:00
一些人原先习惯了其它的编程语言,写 Java 代码的时候就会带上之前的习惯,比如:喜欢用下划线开头的变量名
|
24
ipwx 2021-10-26 09:59:37 +08:00
if 这么写就是魔怔了。。。
但是如果换成 while ,这么写就爽了。比如: int bytesRead; while ((bytesRead = read(fd)) > 0) { ... } 对比如果不这么写: while (true) { int bytesRead = read(fd); if (bytesRead <= 0) { break; } ... } 显然前者更简洁。 |
25
skinny 2021-10-26 10:02:40 +08:00
可能没什么特殊用意,可能就是写这部分代码的人有一些在 C/C++的不良习惯而已,这写法不是特殊需要在 C/C++也不是推荐写法啊。后面更新维护的人也不会在没有明显问题时去动它,于是就保留了下来。JVM 优化不会这么挫的。说起库源代码违反最佳写法官方推荐写法的多了去了,比如 Python ,就很多问题,但是没人愿意去更新源代码。
|
26
clf 2021-10-26 10:08:02 +08:00
有没有可能第二种的 a 作用域只在 if 的括号里,所以这样写。
|
27
b0644170fc 2021-10-26 10:13:25 +08:00
我觉得 4 楼说的有理.
|
28
cubecube 2021-10-26 10:17:57 +08:00 1
@aguesuka 的确没有神秘加成, 可能就是程序员的个人习惯了
JMHPerfCondition.conditionInvokeFirst avgt 3 13.930 ± 3.733 ns/op JMHPerfCondition.conditionInvokeLater avgt 3 13.742 ± 1.632 ns/op ```java @Benchmark public int conditionInvokeFirst() { int a = SpecialCaseTest.getNumber(); if (a > 0) { return 1; } else { return 0; } } @Benchmark public int conditionInvokeLater() { int a; if ((a = SpecialCaseTest.getNumber()) > 0) { return 1; } else { return 0; } } ``` |
29
MineDog 2021-10-26 10:19:39 +08:00
@546L5LiK6ZOt #9 还有是访问成员变量需要的指令比局部变量多,在保证语义一致的情况下,指令更少,性能更好一点
|
30
tobepro 2021-10-26 11:03:42 +08:00
记得以前学嵌入式的时候,听韦东山老师说过,有部分大型开源项目的看着感觉很高大上的代码,其实没什么卵用,单纯就是写代码的人想炫技
|
31
streamrx 2021-10-26 11:11:03 +08:00 via iPhone
1
|
32
yuchting 2021-10-26 11:44:04 +08:00
其实更吊的写法应该是 if((var a = getNumber()) > 0) ...
可惜没语言支持。 |
33
oldshensheep 2021-10-26 11:53:56 +08:00
@yuchting
python 可以 |
34
xiang0818 2021-10-26 13:44:11 +08:00
因为是上了年代的程序员写的~
|
35
ColinZeb 2021-10-26 15:43:23 +08:00
@yuchting c# 可以 ,还可以顺便判断类型或者是否为空。
if( obj is int a )//判断是否 int 类型 如果是 int 赋值给 int a if(obj is {})//判断是否非空 |
37
newmlp 2021-10-26 15:56:10 +08:00 1
代码行数少,有限的空间内可以看到更多的逻辑,没其他原因
|
38
zhgg0 2021-10-26 16:48:11 +08:00
@newmlp 就是 37 楼说的原因,纯粹就是因为代码行数少。仔细翻下 HashMap 的源码就能验证,我刚验证过。
在 HashMap 源码里面,就拿楼主写的代码来作比方 int a = getNumber(); if(a >0); 1 、如果 a 变量在别的地方早就定义过,那就会被写成 if((a=getNumber()) >0); 2 、如果 a 变量在别的地方没定义过,需要定义,那就会被写成 int a = getNumber(); if(a >0); 1 的情况放 if 里能节省一行,所以放 if 里了; 2 的情况不管是否放 if 里都不能节省一行,所以没放 if 里;仔细翻下源码就发现了。 |
39
penguinWWY 2021-10-26 16:50:37 +08:00
@cubecube 优化是后面 Hotspot 干的事情,javac 几乎不做优化
|
40
geligaoli 2021-10-26 16:53:19 +08:00
@546L5LiK6ZOt 多线程中,有时这么写是为了避免锁,局部变量之后的操作,不用担心其他线程的影响。
|
41
littlewing 2021-10-26 19:44:56 +08:00
羡慕 Java ,能看懂 标准库的代码,最新学 C++,STL 不是人看的
|
43
iceheart 2021-10-26 20:21:55 +08:00 via Android
C 代码转过来的吧,直接用了,省事
|
44
eason1874 2021-10-26 20:39:45 +08:00
@yuchting #32 PHP 很多就这么写的,不用提前声明变量 $a ,直接在条件判断里赋值运算,某些场景能省不少 if 嵌套
if (isOk() && ($a = getNumber()) > 0 && $a < 10) echo $a; |
45
someonedeng 2021-10-27 00:45:55 +08:00
c 语言留下的习惯,个人感觉不好看
|
46
fuchaofather 2021-10-27 10:07:18 +08:00
c 味儿
|
47
GiftedJarvis 2021-10-27 14:25:16 +08:00
我也有这疑问, 不光 HashMap, 还有一堆 BlockQueue, AQS 里都这么写
|
48
yolee599 2021-10-27 17:49:00 +08:00
@skinny #25 对于 C 语言,这样写不是不良习惯,反而是好习惯,因为有的编译器不支持以下语法:
for (int i = 0; i < 10; i++) { ... } 要改成下面的写法才能编译通过: int i; for (i = 0; i < 10; i++) { ... } 为了兼容所有的编译器所以使用第二种写法,还有的编译器定义变量的时候不能在函数中间定义,必须在函数最前面定义。 |