Final局部变量如何“避免重复调用”?方法?
使用 JFC/Swing 创建 GUI >执行自定义绘画:完善设计
我正在阅读上面链接的教程,部分示例代码让我感到困惑。根据moveSquare
方法中的代码注释,将位置信息存储为最终局部变量将
'避免重复调用相同的内容 方法'
来说完全没有意义,我希望有人能够解释该评论的含义。 (请参阅上面的链接以获取完整的源代码和教程评论)
class MyPanel extends JPanel {
RedSquare redSquare = new RedSquare();
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
moveSquare(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent e){
moveSquare(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y){
// Current square state, stored as final variables
// to avoid repeat invocations of the same methods.
final int CURR_X = redSquare.getX();
final int CURR_Y = redSquare.getY();
final int CURR_W = redSquare.getWidth();
final int CURR_H = redSquare.getHeight();
final int OFFSET = 1;
if ((CURR_X!=x) || (CURR_Y!=y)) {
// The square is moving, repaint background
// over the old square location.
repaint(CURR_X,CURR_Y,CURR_W+OFFSET,CURR_H+OFFSET);
// Update coordinates.
redSquare.setX(x);
redSquare.setY(y);
// Repaint the square at the new location.
repaint(redSquare.getX(), redSquare.getY(),
redSquare.getWidth()+OFFSET,
redSquare.getHeight()+OFFSET);
}
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("This is my custom Panel!",10,20);
redSquare.paintSquare(g);
}
}
Creating a GUI with JFC/Swing > Perform Custom Painting : Refining the Design
I was reading through the tutorial linked above and a portion of the example code has me perplexed. According to the code comment in the moveSquare
method, storing location information as final local variables will
'avoid repeat invocations of the same
methods'
This makes absolutely no sense to me and I was hoping that someone could expound on the meaning of the comment. (see link above for full source and tutorial commentary)
class MyPanel extends JPanel {
RedSquare redSquare = new RedSquare();
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
moveSquare(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent e){
moveSquare(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y){
// Current square state, stored as final variables
// to avoid repeat invocations of the same methods.
final int CURR_X = redSquare.getX();
final int CURR_Y = redSquare.getY();
final int CURR_W = redSquare.getWidth();
final int CURR_H = redSquare.getHeight();
final int OFFSET = 1;
if ((CURR_X!=x) || (CURR_Y!=y)) {
// The square is moving, repaint background
// over the old square location.
repaint(CURR_X,CURR_Y,CURR_W+OFFSET,CURR_H+OFFSET);
// Update coordinates.
redSquare.setX(x);
redSquare.setY(y);
// Repaint the square at the new location.
repaint(redSquare.getX(), redSquare.getY(),
redSquare.getWidth()+OFFSET,
redSquare.getHeight()+OFFSET);
}
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("This is my custom Panel!",10,20);
redSquare.paintSquare(g);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这意味着调用 getX() 或其他方法的结果将保存在变量中并重用,这样您就不必在每次需要 X 或 Y 时继续调用这些方法。
具有三个优点:
This means that the result from calling getX() or the other methods is saved in a variable and reused so that you don't have to keep calling those methods every time you need the X or Y.
This has three advantages:
正如您所怀疑的那样,使局部变量final没有真正的区别。在某些情况下它可以帮助 JVM 优化代码,但是现在 JVM 已经相当智能了,它并没有多大帮助。
真正的区别在于结果完全存储为局部变量,以避免方法调用。
然而,由于方法调用可能是简单的 getter,JVM 可以内联这些方法,因此性能差异可能不会很大。
如果变量未被访问或仅访问一次(如其中一些变量),则可能会损害性能。
重新绘制的成本可能比此方法高 1000 倍,因此此处的更改并不那么重要。
总的来说,我建议让代码简单明了是编写代码时最重要的因素,而且通常 JVM 会非常有效地优化简单明了的代码。
Making the local variable final makes no real difference as you suspect. It can help the JVM optimise the code in some cases, however the JVM is fairly smart these days and it doesn't help much.
The real difference is the fact the results are stored as local variables at all, to avoid method calls.
However, since the method calls are likely to be trivial getters, the JVM can inline those methods, so the performance difference, may not be great.
If the variable is not accessed or only accessed once as some of these are, they might hurt performance.
The repaint is likely to be 1000x times more expensive than this method, making the changes here not so important.
In general, I recommend making code simple and clear the most important factor in writing code, and often the JVM will optimise simple and clear code very efficiently.
最终变量只能设置一次值。
如果您尝试多次设置最终变量的值,或者编写一个函数来设置最终变量的值,那么它实际上会生成编译器错误成员变量。这可确保您不能多次设置该值,从而可以避免重复调用同一方法。例如,如果您尝试再次编写:
您将收到错误,因为您已经设置了该最终变量。因此,您可以避免重复调用
redSquare.getX()
。在这种情况下,它实际上并没有做太多事情,但在其他对象的其他实现中,该方法可能会产生巨大的计算。Final variables can only have their value set once.
It literally will generate a compiler error if you try to set the value of a final variable more than once, or write a function to set the value of a final member variable. This makes sure that you cannot set the value more than once, which can avoid repeat invocations of the same method. For example, if you tried to write again:
You would get an error because you already set that final variable. So you're avoiding the repeat invocation of
redSquare.getX()
. In this case, it doesn't really do much, but in other implementations with other objects, that method could spawn a huge calculation.这都是关于 moveSquare 函数 - 与此相同:
如您所见,如果不使用这些常量(仅初始化一次),您最终会调用 getX() 和 getY()例如 2 次以上(尽管我认为 JIT 编译器会优化它!)——但是,您通过引入这些常量保存了这 2 次调用。
(只有当使用常量时这些代码行中 X 的值没有改变时,这才有效 - 例如,如果
if ((redSquare.getX()!=x) || (redSquare .getY()!=y))
更改 X 或 Y 的值,您将无法使用常量方法,并且将必须按顺序调用如上所示的函数以获得正确的值。)It's all about the
moveSquare
function -- which is the same to this:as you can see, by not using those constants (which are initialized just once) you end up calling getX() and getY() for instance 2 more times (though I think the JIT compiler will optimize that!) -- however, you saved those 2 calls by introducing these constants.
(This will only work if the value of X is not changed in those lines of code when the constants are used -- if for instance the line after
if ((redSquare.getX()!=x) || (redSquare.getY()!=y))
changes the value of X or Y you won't be able to use the constants approach and will have to call the functions as shown above in order to have the correct values.)