Локальные глобальные переменные VS в Java

Я думал, что понимаю разницу между локальными и глобальными переменными в Java, пока не увидел пример сегодня. В этом коде каждый пытается добавить элементы в список ссылок в методе:

public void addDataPacket(DataPacket data){
    PacketQueueElement newElement = new PacketQueueElement(data);
    if(firstElement != null){
        lastElement.setNextElement(newElement);
        lastElement = newElement;
    }
    else{
        firstElement = newElement;
        lastElement = newElement;
    }
}

Что я не понимаю, так это то, почему newElement не исчезает после закрытия метода? Потому что это локальная переменная и нигде не определена в классе. Вот полный код этого класса:

public class PacketQueue {

/** Das erste Element in der Warteschlange */
private PacketQueueElement firstElement;

/** Das letzte Element in der Warteschlange. */
private PacketQueueElement lastElement;

/**
 * Instanziert eine neue Warteschlange.
 */
public PacketQueue(){
    this.firstElement = null;
    this.lastElement = null;
}

/**
 * Fuegt ein neues Paket ans Ende der Warteschlange an.
 *
 * @param data Das neue Paket
 */
public void addDataPacket(DataPacket data){
    PacketQueueElement newElement = new PacketQueueElement(data);
    if(firstElement != null){
        lastElement.setNextElement(newElement);
        lastElement = newElement;
    }
    else{
        firstElement = newElement;
        lastElement = newElement;
    }
}

/**
 * Entfernt das erste Element der Warteschlange und gibt es zurueck.
 *
 * @return Das erste Element in der Warteschlange
 */
public PacketQueueElement getAndRemoveFirstElement(){
    PacketQueueElement element = this.firstElement;
    this.firstElement = element.getNextElement();
    return element;
}

/**
 * Gibt das erste Paket aus dem ersten Element zurueck.
 *
 * @return Das erste Paket
 */
public DataPacket getFirstDataPacket(){
    return this.firstElement.getData();
}

/**
 * Entfernt das erste Paket der Warteschlange und gibt es zurueck.
 *
 * @return Das erste Paket in der Warteschlange
 */
public DataPacket getAndRemoveFirstDataPacket(){
    return this.getAndRemoveFirstElement().getData();
}

/**
 * Gibt das erste Element der Warteschlange zurueck
 *
 * @return Das erste Element
 */
public PacketQueueElement getFirstElement(){
    return this.firstElement;
}



/**
 * Ueberprueft, ob die Wartschlange leer ist.
 *
 * @return true, wenn sie leer ist
 */
public boolean isEmpty(){
    if(firstElement == null){
        return true;
    }
    else{
        return false;
    }
}

/* (non-Javadoc)
 * @see java.lang.Object#toString()
 */
public String toString(){
    PacketQueueElement element = this.firstElement;
    String s = "";
    while(element != null){
        s += element + "\n";
        element = element.getNextElement();
    }
    return s;
}

}

заранее спасибо

2 ответа

Решение

Это смешивание переменных и объектов, newElement действительно локальная переменная, и она теряется после завершения метода, но ссылка указывает на объект. Объект пригоден для сборки мусора, если на него нет ссылок (переменных). В этом случае временно newElement а также firstElement оба указали на это. Потерял newElement когда метод вышел, но firstElement по-прежнему указывает на это, как и lastElement так что он не подходит для сбора мусора.

Или другими словами: переменная относится к объекту, это не сам объект.

Аналогия:

  • переменная: лист бумаги, на котором вы можете написать адрес
  • объект: дом
  • сборщик мусора: снос экипажа

Я строю дом и пишу его адрес на клочке бумаги, чтобы вы могли туда добраться, я передаю вам этот клочок бумаги, вы записываете адрес с клочка бумаги в адресную книгу, вы выбрасываете клочок бумаги.

Команда по сносу проверяет, пользуется ли кто-нибудь еще домом, проверяя, сохранил ли кто-нибудь его адрес. Даже если вы выбросили клочок бумаги, у вас все еще есть адрес в адресной книге, поэтому дом все еще используется и не разрушен.

newElement это просто ссылка на объект, созданный в памяти.

firstElement затем содержит ссылку на тот же объект.

Ссылка newElement действительно является локальной переменной, но объект, на который ссылается ссылка, затем также упоминается с помощью другой ссылки, т.е. firstElement, Так что после addDataPacket() метод завершается, newElement ссылка больше не существует, но объект, на который она ссылается, все еще существует в памяти, и на этот объект ссылается firstElement,

Другие вопросы по тегам