Java筆記丨23 引用與相等
引用與指標
引用的實質就是指標,但它是受控的、安全的
比如:
會檢查空指標
沒有指標運算*(p+5)
不能訪問沒有引用到的記憶體
自動回收垃圾
C語言指標在Java中的體現
(1)傳地址->物件
引用型別,引用本身就相當於指標。可以修改物件的屬性、呼叫物件的方法
基本型別:沒有對應的
如交換兩個整數
void swap(int x,int y){int t=x;x=y;y=t;}
int a=8,b=9;swap(a.b);
一種變通的辦法,傳出一個有兩個分量x,y的物件
(2)指標運算->陣列
*(p+5)可以用args[5]
(3)函式指標->介面、Lambda表示式
例:求積分,執行緒,回撥函式,事件處理
(4)指向結點的指標->物件的引用
class Node{
Object data;
Node next;
}
示例:List.java
import java.io.IOException; public class List { private Node Head = null; private Node Tail = null; private Node Pointer = null; private int Length = 0; public void deleteAll() { Head = null; Tail = null; Pointer = null; Length = 0; } public void reset() { Pointer = null; } public boolean isEmpty() { return (Length == 0); } public boolean isEnd() { if (Length == 0) throw new java.lang.NullPointerException(); else if (Length == 1) return true; else return (cursor() == Tail); } public Object nextNode() { if (Length == 1) throw new java.util.NoSuchElementException(); else if (Length == 0) throw new java.lang.NullPointerException(); else { Node temp = cursor(); Pointer = temp; if (temp != Tail) return (temp.next.data); else throw new java.util.NoSuchElementException(); } } public Object currentNode() { Node temp = cursor(); return temp.data; } public void insert(Object d) { Node e = new Node(d); if (Length == 0) { Tail = e; Head = e; } else { Node temp = cursor(); e.next = temp; if (Pointer == null) Head = e; else Pointer.next = e; } Length++; } public int size() { return (Length); } public Object remove() { Object temp; if (Length == 0) throw new java.util.NoSuchElementException(); else if (Length == 1) { temp = Head.data; deleteAll(); } else { Node cur = cursor(); temp = cur.data; if (cur == Head) Head = cur.next; else if (cur == Tail) { Pointer.next = null; Tail = Pointer; reset(); } else Pointer.next = cur.next; Length--; } return temp; } private Node cursor() { if (Head == null) throw new java.lang.NullPointerException(); else if (Pointer == null) return Head; else return Pointer.next; } public static void main(String[] args) throws IOException{ List a = new List(); for (int i = 1; i <= 10; i++) a.insert(new Integer(i)); System.out.println(a.currentNode()); while (!a.isEnd()) System.out.println(a.nextNode()); a.reset(); while (!a.isEnd()) { a.remove(); } a.remove(); a.reset(); if (a.isEmpty()) System.out.println("There is no Node in List n"); System.out.println("You can press return to quitn"); try { System. in .read(); } catch(IOException e) {} } } class Node { Object data; Node next; Node(Object d) { data = d; next = null; } }
(5)使用JNI
Java Native Interface(JNI)
它允許Java程式碼和其他語言寫的程式碼進行互動
相等==
簡單地說,基本型別是值相等,引用型別是引用相等
但有不少的具體情況需要具體分析:
基本型別
數值型別:轉換後比較。浮點數最好不要直接用==,因為有誤差。
Double.NAN==Double.NAN結果為false(參見JDK的API文件)
boolean型無法與int比較
Integer i=new Integer(10);
Integer j=new Integer(10);
System.out.println(i==j);//false
Integer m=10;
Integer n=10;
System.out.println(m==n);//true,因為物件有快取
Integer p=200;
Integer q=200;
System.out.println(p==q);//false,因為物件是兩個
這是為什麼呢?
裝箱物件是否相等
int或者short在-128~127時是有快取的,超過則沒有。
列舉、引用物件是否相等
列舉型別:內部進行了唯一例項化,所有可以直接判斷
引用型別:
直接看兩個引用是否一樣
如果要判斷內容是否一樣,則要重寫equals方法
如果要重寫equals方法,則最好重寫hashCode()方法
String物件的特殊性
String物件
判斷相等,一定不要用==,要用equals
但是字串常量(String literal)及字串常量會進行內部化,相同的字串常量是==的
示例:TestStringEquals.java
class TestStringEquals{
public static void main(String[] args) {
String hello = "Hello", lo = "lo"; // " = "左邊為引用,右邊為常量
System.out.println( hello == "Hello"); //true,
System.out.println( Other.hello == hello ); //true(另外一個類中有hello也是相等的。凡是相同的字串常量它都合併指向同一地方)
System.out.println( hello == ("Hel"+"lo") ); //true
System.out.println( hello == ("Hel"+lo) ); //false(這兩個不能合併成一個常量)
System.out.println( hello == new String("Hello")); //false(new重新建立的一個物件,它和原先的那個常量沒有關係)
System.out.println( hello == ("Hel"+lo).intern()); //true(求得它內部的字串)
}
}
class Other { static String hello = "Hello"; }