关于指针的概念,还是在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中的引用,其实就是一个指针的作用呀。