Как конечные локальные переменные «избегают повторных вызовов» методов? - PullRequest
1 голос
/ 10 мая 2011

Создание графического интерфейса пользователя с помощью JFC / Swing> Выполнение пользовательского рисования: уточнение дизайна

Я читал учебник, связанный выше, и часть кода примера озадачила меня.Согласно комментарию к коду в методе 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);
}  
}

Ответы [ 4 ]

2 голосов
/ 10 мая 2011

Это означает, что результат вызова getX () или других методов сохраняется в переменной и используется повторно, так что вам не нужно продолжать вызывать эти методы каждый раз, когда вам нужны X или Y.

Это имеет три преимущества:

  1. Код более читабелен благодаря именам переменных
  2. Производительность улучшена благодаря тому, что нет необходимости вызывать методы снова и снова
  3. Будущие изменения, возможно, проще, потому что вам нужно изменить имена методов только в одном месте, например.
2 голосов
/ 10 мая 2011

Создание локальной переменной final не имеет никакого значения, как вы подозреваете. В некоторых случаях это может помочь JVM оптимизировать код, однако в наши дни JVM достаточно умна и мало помогает.

Реальная разница в том, что результаты вообще сохраняются как локальные переменные, чтобы избежать вызовов методов.

Однако, поскольку вызовы методов, вероятно, являются тривиальными получателями, JVM может встроить эти методы, поэтому разница в производительности может быть невелика.

Если переменная недоступна или доступна только один раз, как некоторые из них, они могут снизить производительность.

Перекраска, вероятно, будет в 1000 раз дороже, чем этот метод, поэтому изменения здесь не так важны.

В общем, я рекомендую сделать код простым и понятным, что является наиболее важным фактором при написании кода, и часто JVM очень эффективно оптимизирует простой и понятный код.

1 голос
/ 10 мая 2011

Для конечных переменных их значение может быть установлено только один раз.

Буквально будет генерироваться ошибка компилятора, если вы попытаетесь установить значение конечной переменной более одного раза или напишите функцию для установки значения конечной переменной-члена. Это гарантирует, что вы не можете установить значение более одного раза, что может избежать повторных вызовов одного и того же метода. Например, если вы попытались написать снова:

CURR_X = redSquare.getX();

Вы получите ошибку, потому что вы уже установили эту последнюю переменную. Таким образом, вы избегаете повторного вызова redSquare.getX(). В этом случае он на самом деле мало что делает, но в других реализациях с другими объектами этот метод может привести к огромным вычислениям.

0 голосов
/ 10 мая 2011

Это все о функции moveSquare - что аналогично этому:

private void moveSquare(int x, int y){

    final int OFFSET = 1;

    if ((redSquare.getX()!=x) || (redSquare.getY()!=y)) {

        // The square is moving, repaint background 
        // over the old square location. 
        repaint(redSquare.getX(),redSquare.getY(),redSquare.getWidth()+OFFSET,redSquare.getHeight()+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);
    }
}

, как вы можете видеть, не используя эти константы (которые инициализируются только один раз), вы в конечном итоге вызываетеНапример, getX () и getY () еще 2 раза (хотя я думаю, что JIT-компилятор оптимизирует это!) - однако вы сохранили эти 2 вызова, введя эти константы.(Это будет работать только в том случае, если значение X не изменяется в этих строках кода при использовании констант - если, например, строка после if ((redSquare.getX()!=x) || (redSquare.getY()!=y)) изменяет значение X или Y, вы не сможете использоватьконстанты приближаются и будет иметь для вызова функций, как показано выше, для получения правильных значений.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...