Java方法调用与使用变量

时间:2022-04-28 20:48:46

Recently I got into a discussion with my Team lead about using temp variables vs calling getter methods. I was of the opinion for a long time that, if I know that I was going to have to call a simple getter method quite a number of times, I would put it into a temp variable and then use that variable instead. I thought that this would be a better both in terms of style and performance. However, my lead pointed out that in Java 4 and newer editions, this was not true somewhat. He is a believer of using a smaller variable space, so he told me that calling getter methods had a very negligible performance hit as opposed to using a temp variable, and hence using getters was better. However, I am not totally convinced by his argument. What do you guys think?

最近我和我的团队负责人讨论了使用临时变量与调用getter方法的问题。很长一段时间我认为,如果我知道我将不得不多次调用一个简单的getter方法,我会将它放入一个临时变量然后使用该变量。我认为这在风格和性能方面都会更好。但是,我的主管指出,在Java 4和更新版本中,这有点不正确。他相信使用一个较小的变量空间,所以他告诉我,调用getter方法的性能影响非常小,而不是使用temp变量,因此使用getter更好。但是,我并不完全相信他的论点。你们有什么感想?

13 个解决方案

#1


64  

Never code for performance, always code for readability. Let the compiler do the work.

从不编写性能代码,始终编写可读性代码。让编译器完成工作。

They can improve the compiler to run good code faster and suddenly your "Fast" code is actually slowing the system down.

他们可以改进编译器以更快地运行良好的代码,突然你的“快速”代码实际上减慢了系统的速度。

#2


23  

Your lead is correct. In modern versions of the VM, simple getters that return a private field are inlined, meaning the performance overhead of a method call doesn't exist.

你的领导是正确的。在VM的现代版本中,返回私有字段的简单getter被内联,这意味着方法调用的性能开销不存在。

#3


12  

Don't forget that by assigning the value of getSomething() to a variable rather than calling it twice, you are assuming that getSomething() would have returned the same thing the second time you called it. Perhaps that's a valid assumption in the scenario you are talking about, but there are times when it isn't.

不要忘记通过将getSomething()的值赋给变量而不是将其调用两次,您假设getSomething()在第二次调用它时会返回相同的内容。也许这是你所谈论的场景中的一个有效假设,但有时却不是。

#4


10  

It depends. If you would like to make it clear that you use the same value again and again, I'd assign it to a temp variable. I'd do so if the call of the getter is somewhat lengthy, like myCustomObject.getASpecificValue().

这取决于。如果您想明确表示一次又一次使用相同的值,我会将其分配给临时变量。如果getter的调用有点冗长,我会这样做,比如myCustomObject.getASpecificValue()。

You will get much fewer errors in your code if it is readable. So this is the main point.

如果代码可读,您将获得更少的错误。所以这是重点。

The performance differences are very small or not existent.

性能差异很小或不存在。

#5


8  

If you keep the code evolution in mind, simple getters in v1.0 tend to become not-so-simple getters in v2.0.

如果你记住代码进化,v1.0中的简单getter往往在v2.0中成为不那么简单的getter。

The coder who changes a simple getter to not-so-simple getter usually has no clue that there is a function that calls this getter 10 times instead of 1 and never corrects it there, etc.

将简单的getter改为不那么简单的getter的编码器通常不知道有一个函数可以调用这个getter 10次而不是1次,并且从不在那里修改它等等。

That's why from the point of view of the DRY principal it makes sense to cache value for repeated use.

这就是为什么从DRY原理的角度来看,缓存重复使用的价值是有意义的。

#6


6  

I will not sacrifice "Code readability" to some microseconds.
Perhaps it is true that getter performs better and can save you several microseconds in runtime. But i believe, variables can save you several hours or perhaps days when bug fixing time comes.

我不会牺牲“代码可读性”到几微秒。也许确实,getter表现更好,可以在运行时节省几微秒。但是我相信,变量可以为你节省几个小时或者几天的时间来修复错误。

Sorry for the non-technical answer.

很抱歉非技术性的答案。

#7


2  

I think that recent versions of the JVM are often sufficiently clever to cache the result of a function call automatically, if some conditions are met. I think the function must have no side effects and reliably return the same result every time it is called. Note that this may or may not be the case for simple getters, depending on what other code in your class is doing to the field values.

我认为,如果满足某些条件,最近版本的JVM通常足够聪明地自动缓存函数调用的结果。我认为该函数必须没有副作用,并且每次调用时都可靠地返回相同的结果。请注意,对于简单的getter,这可能是也可能不是这种情况,具体取决于类中其他代码对字段值执行的操作。

If this is not the case and the called function does significant processing then you would indeed be better of caching its result in a temporary variable. While the overhead of a call may be insignificant, a busy method will eat your lunch if you call it more often than necessary.

如果不是这种情况并且被调用的函数进行了大量处理,那么您确实可以将其结果缓存在临时变量中。虽然呼叫的开销可能微不足道,但如果您经常拨打电话,繁忙的方法会吃掉您的午餐。

I also practice your style; even if not for performance reasons, I find my code more legible when it isn't full of cascades of function calls.

我也练习你的风格;即使不是出于性能原因,我发现我的代码在没有充满级联函数调用时更加清晰。

#8


1  

It is not worth if it is just getFoo(). By caching it into a temp variable you are not making it much faster and maybe asking for trouble because getFoo() may return different value later. But if it is something like getFoo().getBar().getBaz().getSomething() and you know the value will not be changed within the block of code, then there may be a reason to use temp variable for better readability.

如果只是getFoo()则不值得。通过将其缓存到临时变量中,您可能不会更快,也可能会遇到麻烦,因为getFoo()可能会在以后返回不同的值。但是如果它类似于getFoo()。getBar()。getBaz()。getSomething()并且你知道在代码块中不会改变值,那么可能有理由使用temp变量来提高可读性。

#9


0  

A general comment: In any modern system, except for I/O, do not worry about performance issues. Blazing fast CPUs and heaps of memory mean, all other issues are most of the time completely immaterial to actual performance of your system. [Of course, there are exceptions like caching solutions but they are far and rare.]

一般性评论:在任何现代系统中,除I / O外,不要担心性能问题。超快的CPU和大量的内存意味着,所有其他问题在大多数情况下对系统的实际性能完全无关紧要。 [当然,有一些例外,如缓存解决方案,但它们非常罕见。]

Now coming to this specific problem, yes, compiler will inline all the gets. Yet, even that is not the actual consideration, what should really matter is over all readability and flow of your code. Replacing indirections by a local variable is better, if the call used multiple times, like customer.gerOrder().getAddress() is better captured in local variable.

现在谈到这个具体问题,是的,编译器将内联所有获取。然而,即使这不是实际的考虑,真正重要的是所有可读性和代码流。如果调用多次使用,则更换局部变量的间接更好,例如customer.gerOrder()。getAddress()在局部变量中被更好地捕获。

#10


0  

The virtual machine can handle the first four local variables more efficiently than any local variable declared after that (see lload and lload_<n> instructions). So caching the result of the (inlined) getter may actually hurt your performance.

虚拟机可以比之后声明的任何局部变量更有效地处理前四个局部变量(请参阅lload和lload_ 指令)。因此缓存(内联)getter的结果实际上可能会损害您的性能。

Of course on their own either performance influence is almost negligible so if you want to optimize your code make sure that you are really tackling an actual bottleneck!

当然,对他们自己要么性能影响几乎可以忽略不计,所以如果你想优化你的代码,请确保你真正解决了实际的瓶颈!

#11


0  

Another reason to not use a temporary variable to contain the result of a method call is that using the method you get the most updated value. This could not be a problem with the actual code, but it could become a problem when the code is changed.

不使用临时变量来包含方法调用结果的另一个原因是使用该方法可以获得最新的值。这可能不是实际代码的问题,但是当代码更改时它可能会成为一个问题。

#12


0  

I am in favour of using temp variable if you are sure about getter will return same value throughout the scope. Because if you have a variable having name of length 10 or more getter looks bad in readability aspect.

如果您确定getter将在整个范围内返回相同的值,我赞成使用temp变量。因为如果你有一个长度为10或更长的变量,那么可读性方面看起来很糟糕。

#13


0  

I've tested it in a very simple code :

我用一个非常简单的代码测试了它:

  • created a class with a simple getter of an int (I tried both with final and non-final value for Num, didn't see any difference, mind that it's in the case num never change also...!):

    用一个简单的int getter创建了一个类(我尝试了Num的final和non-final值,没有看到任何区别,请注意,在这种情况下,num也永远不会改变...!):

    Num num = new Num(100_000_000);
    
  • compared 2 differents for loops:

    比较了2个不同的循环:

    1: for(int i = 0; i < num.getNumber(); ++i){(...)}
    
    2: number = num.getNumber();
    for(int i = 0; i < number; ++i){(...)}
    

The result were around 3 millis int the first one and around 2 millis in the second one. So there's a tiny difference, nothing to worry about for small loops, may be more problematic on big iterations or if you always call getter and need them a lot. For instance, in image processing if you want to be quick, don't use repetively getters I would advise...

结果在第一个中约为3毫米,在第二个中约为2毫米。因此,对于小循环而言,没有什么可担心的,在大型迭代中可能会出现更多问题,或者如果您总是调用getter并且需要它们很多。例如,在图像处理中,如果你想要快速,不要使用重复吸气剂,我会建议...

#1


64  

Never code for performance, always code for readability. Let the compiler do the work.

从不编写性能代码,始终编写可读性代码。让编译器完成工作。

They can improve the compiler to run good code faster and suddenly your "Fast" code is actually slowing the system down.

他们可以改进编译器以更快地运行良好的代码,突然你的“快速”代码实际上减慢了系统的速度。

#2


23  

Your lead is correct. In modern versions of the VM, simple getters that return a private field are inlined, meaning the performance overhead of a method call doesn't exist.

你的领导是正确的。在VM的现代版本中,返回私有字段的简单getter被内联,这意味着方法调用的性能开销不存在。

#3


12  

Don't forget that by assigning the value of getSomething() to a variable rather than calling it twice, you are assuming that getSomething() would have returned the same thing the second time you called it. Perhaps that's a valid assumption in the scenario you are talking about, but there are times when it isn't.

不要忘记通过将getSomething()的值赋给变量而不是将其调用两次,您假设getSomething()在第二次调用它时会返回相同的内容。也许这是你所谈论的场景中的一个有效假设,但有时却不是。

#4


10  

It depends. If you would like to make it clear that you use the same value again and again, I'd assign it to a temp variable. I'd do so if the call of the getter is somewhat lengthy, like myCustomObject.getASpecificValue().

这取决于。如果您想明确表示一次又一次使用相同的值,我会将其分配给临时变量。如果getter的调用有点冗长,我会这样做,比如myCustomObject.getASpecificValue()。

You will get much fewer errors in your code if it is readable. So this is the main point.

如果代码可读,您将获得更少的错误。所以这是重点。

The performance differences are very small or not existent.

性能差异很小或不存在。

#5


8  

If you keep the code evolution in mind, simple getters in v1.0 tend to become not-so-simple getters in v2.0.

如果你记住代码进化,v1.0中的简单getter往往在v2.0中成为不那么简单的getter。

The coder who changes a simple getter to not-so-simple getter usually has no clue that there is a function that calls this getter 10 times instead of 1 and never corrects it there, etc.

将简单的getter改为不那么简单的getter的编码器通常不知道有一个函数可以调用这个getter 10次而不是1次,并且从不在那里修改它等等。

That's why from the point of view of the DRY principal it makes sense to cache value for repeated use.

这就是为什么从DRY原理的角度来看,缓存重复使用的价值是有意义的。

#6


6  

I will not sacrifice "Code readability" to some microseconds.
Perhaps it is true that getter performs better and can save you several microseconds in runtime. But i believe, variables can save you several hours or perhaps days when bug fixing time comes.

我不会牺牲“代码可读性”到几微秒。也许确实,getter表现更好,可以在运行时节省几微秒。但是我相信,变量可以为你节省几个小时或者几天的时间来修复错误。

Sorry for the non-technical answer.

很抱歉非技术性的答案。

#7


2  

I think that recent versions of the JVM are often sufficiently clever to cache the result of a function call automatically, if some conditions are met. I think the function must have no side effects and reliably return the same result every time it is called. Note that this may or may not be the case for simple getters, depending on what other code in your class is doing to the field values.

我认为,如果满足某些条件,最近版本的JVM通常足够聪明地自动缓存函数调用的结果。我认为该函数必须没有副作用,并且每次调用时都可靠地返回相同的结果。请注意,对于简单的getter,这可能是也可能不是这种情况,具体取决于类中其他代码对字段值执行的操作。

If this is not the case and the called function does significant processing then you would indeed be better of caching its result in a temporary variable. While the overhead of a call may be insignificant, a busy method will eat your lunch if you call it more often than necessary.

如果不是这种情况并且被调用的函数进行了大量处理,那么您确实可以将其结果缓存在临时变量中。虽然呼叫的开销可能微不足道,但如果您经常拨打电话,繁忙的方法会吃掉您的午餐。

I also practice your style; even if not for performance reasons, I find my code more legible when it isn't full of cascades of function calls.

我也练习你的风格;即使不是出于性能原因,我发现我的代码在没有充满级联函数调用时更加清晰。

#8


1  

It is not worth if it is just getFoo(). By caching it into a temp variable you are not making it much faster and maybe asking for trouble because getFoo() may return different value later. But if it is something like getFoo().getBar().getBaz().getSomething() and you know the value will not be changed within the block of code, then there may be a reason to use temp variable for better readability.

如果只是getFoo()则不值得。通过将其缓存到临时变量中,您可能不会更快,也可能会遇到麻烦,因为getFoo()可能会在以后返回不同的值。但是如果它类似于getFoo()。getBar()。getBaz()。getSomething()并且你知道在代码块中不会改变值,那么可能有理由使用temp变量来提高可读性。

#9


0  

A general comment: In any modern system, except for I/O, do not worry about performance issues. Blazing fast CPUs and heaps of memory mean, all other issues are most of the time completely immaterial to actual performance of your system. [Of course, there are exceptions like caching solutions but they are far and rare.]

一般性评论:在任何现代系统中,除I / O外,不要担心性能问题。超快的CPU和大量的内存意味着,所有其他问题在大多数情况下对系统的实际性能完全无关紧要。 [当然,有一些例外,如缓存解决方案,但它们非常罕见。]

Now coming to this specific problem, yes, compiler will inline all the gets. Yet, even that is not the actual consideration, what should really matter is over all readability and flow of your code. Replacing indirections by a local variable is better, if the call used multiple times, like customer.gerOrder().getAddress() is better captured in local variable.

现在谈到这个具体问题,是的,编译器将内联所有获取。然而,即使这不是实际的考虑,真正重要的是所有可读性和代码流。如果调用多次使用,则更换局部变量的间接更好,例如customer.gerOrder()。getAddress()在局部变量中被更好地捕获。

#10


0  

The virtual machine can handle the first four local variables more efficiently than any local variable declared after that (see lload and lload_<n> instructions). So caching the result of the (inlined) getter may actually hurt your performance.

虚拟机可以比之后声明的任何局部变量更有效地处理前四个局部变量(请参阅lload和lload_ 指令)。因此缓存(内联)getter的结果实际上可能会损害您的性能。

Of course on their own either performance influence is almost negligible so if you want to optimize your code make sure that you are really tackling an actual bottleneck!

当然,对他们自己要么性能影响几乎可以忽略不计,所以如果你想优化你的代码,请确保你真正解决了实际的瓶颈!

#11


0  

Another reason to not use a temporary variable to contain the result of a method call is that using the method you get the most updated value. This could not be a problem with the actual code, but it could become a problem when the code is changed.

不使用临时变量来包含方法调用结果的另一个原因是使用该方法可以获得最新的值。这可能不是实际代码的问题,但是当代码更改时它可能会成为一个问题。

#12


0  

I am in favour of using temp variable if you are sure about getter will return same value throughout the scope. Because if you have a variable having name of length 10 or more getter looks bad in readability aspect.

如果您确定getter将在整个范围内返回相同的值,我赞成使用temp变量。因为如果你有一个长度为10或更长的变量,那么可读性方面看起来很糟糕。

#13


0  

I've tested it in a very simple code :

我用一个非常简单的代码测试了它:

  • created a class with a simple getter of an int (I tried both with final and non-final value for Num, didn't see any difference, mind that it's in the case num never change also...!):

    用一个简单的int getter创建了一个类(我尝试了Num的final和non-final值,没有看到任何区别,请注意,在这种情况下,num也永远不会改变...!):

    Num num = new Num(100_000_000);
    
  • compared 2 differents for loops:

    比较了2个不同的循环:

    1: for(int i = 0; i < num.getNumber(); ++i){(...)}
    
    2: number = num.getNumber();
    for(int i = 0; i < number; ++i){(...)}
    

The result were around 3 millis int the first one and around 2 millis in the second one. So there's a tiny difference, nothing to worry about for small loops, may be more problematic on big iterations or if you always call getter and need them a lot. For instance, in image processing if you want to be quick, don't use repetively getters I would advise...

结果在第一个中约为3毫米,在第二个中约为2毫米。因此,对于小循环而言,没有什么可担心的,在大型迭代中可能会出现更多问题,或者如果您总是调用getter并且需要它们很多。例如,在图像处理中,如果你想要快速,不要使用重复吸气剂,我会建议...