前言
关于指针的概念,还是在C和C++中有了解,但没想到,在java中也遇到,一时半会拐不过弯来。先看题目:删除链表中重复的节点,看示例的要求是重复的节点一个都不保留,(要是可以保留一个的话,那太简单了,单指针就能做)。
再看一下解题源码:
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
//当传入链表为空或者链表长度为1
if (pHead==null || pHead.next==null){return pHead;}
ListNode Head = new ListNode(0);//创建一个无关节点
Head.next = pHead;//这个节点指向输入的链表,表头
ListNode pre = Head;//创建一个指向表头的引用指针
ListNode last = Head.next;//创建一个当前节点的引用指针
while (last!=null){
if(last.next!=null && last.val == last.next.val){
// 找到最后的一个相同节点
while (last.next!=null && last.val == last.next.val){
last = last.next;
}
pre.next = last.next;//我很纳闷,改变指针的所指内容的属性就可以改变原来的Head
last = last.next;
}else{
pre = pre.next;//而改变指针自己,却没有改变Head为Head的下一个节点,这它丫的就是C++里的指针。。。。
last = last.next;
}
}
return Head.next;
}
}
所以: 弄清楚引用的作用之后,就不会混淆了。因为在声明的时候ListNode pre = Head;没有使用new关键字创建对象,所以只是创建了一个ListNode类型的指针指向了Head,这个指针也可以指向其他的ListNode,在这个改变指向的过程中,不会引起原来指向的内容的变化,只是单方面的挪开了指针,比如pre = pre.next;就是指针往下挪了一位。而pre.next = last.nex; 这就像C++中,对指针指向的地址的内容的属性进行赋值的操作,这种操作是会引起指针所指内容变化的。
通过链表的这个指针引用,我发现java中还是有C++的影子,这样也容易理解了为什么String有常量池,Integer有-128~127的常量池;为什么其他的类需要用关键字new才能创建(这里不包括反射的创建实例),而String s = “Hello World” 却可以直接等于一个字符串呢?没有new就没有开辟内存是吗?那Integer a = 128;这已经超出了常量池的缓存范围了,是不是后台又进行了new操作。
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
return i >= -128 && i <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[i + 128] : new Integer(i);
}
Integer的内部类
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
private IntegerCache() {
}
static {
int h = 127;
String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
int i;
if (integerCacheHighPropValue != null) {
try {
i = Integer.parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
h = Math.min(i, 2147483518);
} catch (NumberFormatException var4) {
}
}
high = h;
cache = new Integer[high - -128 + 1];
i = -128;
for(int k = 0; k < cache.length; ++k) {
cache[k] = new Integer(i++);
}
assert high >= 127;
}
}
看到Integer的源码,果然,HotSpot的JVM里面,就是在-128~127就在缓存中取,否则的话就是直接new了,所以没有new就不开辟内存(这里先不提反射的newInstance)。
原来,之前说java没有指针是我自己骗自己,只不过是没有了C和C++中那样的*作指针而已,java中的引用,其实就是一个指针的作用呀。