引用与指针
引用的实质就是指针,但它是受控的、安全的
比如:
会检查空指针
没有指针运算*(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"; }