在java的学习当中,很多时候并没有能很好分清把对象和对象的引用。如果没能很好认识分清这两者的关系,就可能会很难理解一些指针的移动的代码。
JAVA基本类型的变量的时其变量名及值(变量名及值是两个概念)是放在方法栈中,引用类型所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆类存中的。
我们先定义一个简单的类:
public class DemoClass {
private String name;
}
有了这个模板,就可以用它来创建对象:
DemoClass demo= new DemoClass ();
通常把这条语句的动作称之为创建一个对象,其实,它包含了四个动作。
1)右边的“ new DemoClass”,是以DemoClass类为模板,在堆空间里创建一个DemoClass类对象(也简称为DemoClass对象)。
2)末尾的()意味着,在对象创建后,立即调用DemoClass类的构造函数,对刚生成的对象进行初始化。
3)左边的“DemoClass”创建了一个DemoClass类引用变量。所谓DemoClass类引用,就是以后可以用来指向DemoClass对象的对象引用。
4)“=”操作符使对象引用指向刚创建的那个DemoClass对象。
我们可以把这条语句拆成两部分:
DemoClass demo; --对象引用变量
demo= new DemoClass (); --对象本身
效果是一样的。这样写,就比较清楚了,有两个实体:一是对象引用变量,一是对象本身。
通过上面知识我们来看两个相对复杂一点demo,这个例子中通过tempHead 改变对实体对象指向的改变,使其tempHead 一直指向链表的末尾。head 指向链表头部
public class TempClass {
@Test
public void replaceSingleNode(){
//定义一个请求头对象
SingleLinkedNode head = new SingleLinkedNode(0);
//定义tempHead的引用名 将指向 new SingleLinkedNode(0) 这个对象本身
SingleLinkedNode tempHead=head;
for (int i = 1; i <=5 ; i++) {
//tempHead.next 引用名 将指向 new SingleLinkedNode(i)本身
tempHead.next = new SingleLinkedNode(i);
//tempHead引用名 指向 tempHead 的下个对象本身
tempHead = tempHead.next;
}
//这个时候head 这个引用名 实际指向 new SingleLinkedNode(0);
System.out.println("请求头:"+head);
//这个时候 tempHead 这个应用名实际指向 new SingleLinkedNode(i); 当i=5的时候
System.out.println("运输对象:"+tempHead);
}
@Data
class SingleLinkedNode{
private int value;
private SingleLinkedNode next;
public SingleLinkedNode(int value) {
this.value = value;
}
}
}
打印内容
请求头:TempClass.SingleLinkedNode(value=0, next=TempClass.SingleLinkedNode(value=1, next=TempClass.SingleLinkedNode(value=2, next=TempClass.SingleLinkedNode(value=3, next=TempClass.SingleLinkedNode(value=4, next=TempClass.SingleLinkedNode(value=5, next=null))))))
运输对象:TempClass.SingleLinkedNode(value=5, next=null)
我们的出 tempHead = tempHead.next; 只是改变tempHead 这个引用对象,而不是直接对对象进行替换,我这里再用一个双链表来作证这一结论。在双链表中如果是不是覆盖,那最后tempHead就应该保留整条链表数据,只是tempHead指向链表末尾的字段。
public class TempClass {
@Test
public void replaceDoubleNode(){
//定义一个请求头对象
DoubleLinkedNode head = new DoubleLinkedNode(0);
//定义tempHead的引用名 将指向 new SingleLinkedNode(0) 这个对象本身
DoubleLinkedNode tempHead=head;
for (int i = 1; i <=5 ; i++) {
//newNode 引用名 将指向 new SingleLinkedNode(i)实体本身
DoubleLinkedNode newNode = new DoubleLinkedNode(i);
//tempHead.tail 这个引用 指向new DoubleLinkedNode(i);实体
tempHead.tail =newNode;
//newNode 这个引用 指向tempHead 的实体
newNode.front = tempHead;
//将tempHead 指向 tempHead.tail 实体 ,也就是 new DoubleLinkedNode(i) 实体本身
tempHead = tempHead.tail;
}
System.out.println("请求头:"+head);
System.out.println("运输对象:"+tempHead);
}
class DoubleLinkedNode{
private int value;
private DoubleLinkedNode front;
private DoubleLinkedNode tail;
public DoubleLinkedNode(int value) {
this.value = value;
}
}
}
希望通过这里讲解说明,能够很好的认识引用和对象本身的区别