We have been using the concept of "object" before, but we have not discussed the specific way in which objects are stored in memory. This discussion will lead to the important concept of "object reference".
object reference
We continue to use the Human class defined previously and have a Test class:
Copy the code code as follows:
public class Test
{
public static void main(String[] args)
{
Human aPerson = new Human(160);
}
}
classHuman
{
/**
* constructor
*/
public Human(int h)
{
this.height = h;
}
/**
*accessor
*/
public int getHeight()
{
return this.height;
}
/**
* mutator
*/
public void growHeight(int h)
{
this.height = this.height + h;
}
private int height;
}
Classes can be called externally to create objects, such as the above in the Test class:
Copy the code code as follows:
Human aPerson = new Human(160);
An object aPerson of Human class is created.
The above is a very simple statement, but we have a lot of details to go into:
1. First look at the right side of the equal sign. new opens up space for objects in memory. Specifically, new opens up space for objects on the heap of memory. In this space, the data and methods of the object are stored.
2. Look at the left side of the equal sign. aPerson refers to a Human object, which is called an object reference. In fact, aPerson is not the object itself, but is similar to a pointer to the object. aPerson exists in the stack in memory.
3. When we use the equal sign to assign a value, the address of the object created in the heap by new on the right is assigned to the object reference.
The memory here refers to the Java process memory space virtualized by the JVM (Java Virtual Machine). For the concepts of heap and stack in memory, please refer to Linux From Program to Process.
The stack can be read faster than the heap, but the data stored on the stack is limited by the valid range. In C language, when a function call ends, the corresponding stack frame is deleted, and the parameters and automatic variables stored on the stack frame disappear. Java's stack is also subject to the same restriction. When a method call ends, the data stored on the stack by the method will be cleared. In Java, all (ordinary) objects are stored on the heap. Therefore, the full meaning of the new keyword is to create an object on the heap.
Objects of primitive types, such as int and double, are stored on the stack. When we declare a basic type, there is no need for new. Once declared, Java stores primitive types of data directly on the stack. Therefore, the variable name of a basic type represents the data itself, not a reference.
The relationship between references and objects is like a kite and a person. When we look at the sky (written in the program), what we see is a kite (reference), but what corresponds to the kite is a person (object):
Separation of references and objects; references point to objects
Although references and objects are separated, all our access to objects must go through the "door" of references, such as accessing object methods through reference.method(). In Java, we cannot skip references and touch objects directly. For another example, if the data member of object a is an ordinary object b, the data member of a saves a reference to object b (if it is a basic type variable, then the data member of a saves the basic type variable itself).
In Java, references play the role of pointers, but we cannot directly modify the value of the pointer, such as adding 1 to the pointer value like in C language. We can only perform operations on objects through references. This design avoids many errors that pointers can cause.
reference assignment
When we assign a reference to another reference, we are actually copying the address of the object. Both references will point to the same object. For example, dummyPerson=aPerson; will result in:
An object can have multiple references (one person can fly multiple kites). When a program modifies an object through one reference, the modification is visible through other references. We can use the following Test class to test the actual effect:
Copy the code code as follows:
public class Test
{
public static void main(String[] args)
{
Human aPerson = new Human(160);
Human dummyPerson = aPerson;
System.out.println(dummyPerson.getHeight());
aPerson.growHeight(20);
System.out.println(dummyPerson.getHeight());
}
}
Our modifications to aPerson will affect dummyPerson. These two references actually point to the same object.
Therefore, assigning a reference to another reference does not copy the object itself. We must find other mechanisms to copy objects.
Garbage collection
As the method call ends, reference and primitive type variables are cleared. Since the object lives on the heap, the memory occupied by the object will not be cleared when the method call ends. The process space may quickly become filled with objects being created. Java has a built-in garbage collection mechanism for clearing out objects that are no longer used to reclaim memory space.
The basic principle of garbage collection is that when there is a reference pointing to an object, the object will not be recycled; when there is no reference pointing to an object, the object is cleared. The space it occupies is reclaimed.
The above figure assumes the memory status in the JVM at a certain moment. The Human Object has three references: aPerson and dummyPerson from the stack, and the president, a data member of another object. The Club Object has no reference. If garbage collection is started at this time, the Club Object will be emptied, and the Human Object's reference (president) from the Club Object will also be deleted.
Garbage collection is an important mechanism in Java, which directly affects the operating efficiency of Java. I'll get into the details of that later.
Parameter passing
When we separate the concepts of references and objects, the parameter passing mechanism of Java methods is actually very clear: Java parameter passing is by value. That is, when we pass a parameter, the method will get a copy of the parameter.
In fact, one of the parameters we pass is a variable of basic type and the other is a reference to the object.
Pass-by-value for primitive type variables means that the variable itself is copied and passed to the Java method. Modifications of variables by Java methods will not affect the original variables.
Passing by value means that the address of the object is copied and passed to the Java method. Java method access based on this reference will affect the object.
There is another situation worth mentioning here: we use new inside the method to create an object and return a reference to the object. If the return is received by a reference, since the object's reference is not 0, the object still exists and will not be garbage collected.
Summarize
new
reference, object
Conditions for being garbage collected
Parameters: passed by value