引用类型初认识
引用(reference)和对象(object)
1、Java中没有指针和地址的概念
2、其中一种视角——引用和对象都是内存中数据的一种规定的组织方式。
Java中不允许程序员直接接触对象,只能通过引用间接操作体现了:
安全性:接触到对象,就不会破坏对象。
可控性:只能使用规定范围内的功能。
引用和对象之间的关系
理解引用和对象之间的关系
引用指向对象,对对象进行操作,把这种关系叫做,引用指向对象。
引用指向对象的一些规则
1、只能用引用指向对象,不能对象指向引用,也不能引用指向引用,更不能对象指向对象
2、引用在同一时刻只能指向一个对象,对象在同一时刻可以被多个引用指向。
3、引用不指向任何对象,称为null。
4、引用的赋值运算,是让被赋值的引用指向该引用当前指向的对象。
null的理解
null可以理解为“空”,即引用不指向任何对象,我们称其为null。
例如:
int [] arr = null ;
我们就把这种情况称为:a等于空,或者a等于null,表达的是,a不指向任何对象
引用的赋值操作符理解
引用的赋值运算,是让被赋值的引用指向该引用当前引用的对象
例如:
int [] a = {
1,2,3,4,5};
int [] b = null;
b = a;
是让b,指向当前a指向的对象。如图:
引用的比较操作符理解
对于引用,没有>(大于)和 <(小于)的操作符比较,只有:
== (等于):判断两个对象是否指向同一个对象,是的话返回true,否则false
!=(不等于):判断两个对象是否不指向同一个对象,是的话返回true,否则false
另外:引用也不存在:+ - * / 的操作符。只有:=,= =,!=,. , [ ].(赋值,等于,不等于,解引用的 . 和 [ ])。
例如:
int [] a = {
1,2,3,4,5};
int [] b = {
1,2,3,4,5};
a == b; //a和b指向的不是同一个对象,所以结果为 false
a != b;//a和b指向的不是同一个对象,所以结果为 true
b = a;
a == b; //a和b指向的是同一个对象,所以结果为 true
a != b;//a和b指向的是同一个对象,所以结果为 false
解引用操作符
引用的 . 操作符理解
引用的 . 操作符,可以理解成 “的”,实际上就是通过访问的对象
int [] a = {
1,2,3,4,5};
System.out.println(a.length);//获取a指向的数组对象的长度
数组类型引用的 [ ] 操作符理解
只有数组才支持 [ ] 操作符!
int [] a = {
1,2,3,4,5};
System.out.println(a [0]);//获取a指向的数组对象的第一个元素
引用操作对象表现出的"共享"性
1、通过赋值表现
int [] a = {
1,2,3,4,5};
System.out.println(Arrays.toString(a));//[1,2,3,4,5]
int [] b = a;
System.out.println(Arrays.toString(b));//[1,2,3,4,5]
int [] a = {
1,2,3,4,5};
int [] b = a;
b[0]=100;
System.out.println(Arrays.toString(a));//[100,2,3,4,5]
System.out.println(Arrays.toString(b));//[100,2,3,4,5]
NUllPointerException异常
被翻译成空指针异常,在对一个引用做 . 或者 [] 操作的时候,就是需要通过引用操作引用指向的对象。如果有 一个 引用 == null,则表示该引用没有指向任何对象。则此时在对该引用使用 . 或者 [] 操作符,就会抛出 NullPointerException 了
int[] arr = null;
System.out.println(arr.length);
因为arr没有指向对象,// 运行结果,会出现运行时异常
Exception in thread “main”== java.lang.NullPointerException==
同理:
int[] arr = null;
System.out.println(arr[0]);
因为arr没有指向对象,// 运行结果,会出现运行时异常
Exception in thread “main”== java.lang.NullPointerException==
方法传参
1、通过实参传递给形参,交换:
import java.util.Arrays;
/**
* 方法传参
*/
public class methodDemo {
public static void main(String[] args) {
int[] a = {
1, 2, 3, 4, 5};
int[] b = {
5, 6, 7, 8, 9};
swap(a, b);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
}
private static void swap(int[] a, int[] b) {
int[] tmp = a;
a = b;
a = tmp;
}
}
可以发现,实际上,并没有发生我们想要的交换,结果任然没有发生变换!
如图可见,在函数栈帧中,swap中确实发生了交换,而且在执行完毕,就出栈销毁了,所以并不影响实际的交换,
简单来说:在swap中发生的一切改变,在函数完成后,并不对实参造成影响,一切关系,在完成后都结束。
2、
import java.util.Arrays;
/**
* 操作一个对象
*/
public class methodDemo2 {
public static void main(String[] args) {
int[] a = {
1, 2, 3, 4, 5};
swap(a, 0, 4);
System.out.println(Arrays.toString(a));
}
private static void swap(int[] a, int x, int y) {
int tmp = a[x];
a[x] = a[y];
a[y] = tmp;
}
}
结果显而易见,首尾元素交换成功。
这个和上面最大的区别在于:
这是直接对对象的内容进行修改,在函数结束后,对象中的内容会保存下来,所以结果不同。
所以得出结论:
形参的改变,并不影响实参
总结:
1、引用是一种数据类型,用来指向对象。
2、 对引用进行的大部分操作实际上都是操作的该引用指向的对象。
3、 当多个引用指向同一个对象时,通过哪个引用修改了对象,其他引用都可以看到变化
4、 当一个引用不指向对象时,要求访问其指向的对象,就会遇到 NullPointerException