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