java中基本概念引用及和C语言中指针比较
第一点:什么是引用类型
引用类型(reference type)指向一个对象,不是原始值,指向对象的变量是引用变量。
在java里面除去基本数据类型的其它类型都是引用数据类型,自己定义的class类都是引用类型,可以像基本类型一样使用。
示例如下:
public class MyDate {
private int day = 8;
private int month = 8;
private int year = 2008;
private MyDate(int day, intmonth, int year){...}
public void print(){...}
}
public class TestMyDate {
public static void main(Stringargs[]) {
//这个today变量就是一个引用类型的变量
MyDatetoday = new MyDate(23, 7, 2008);
}
}
总结1:基本数据类类型存的是数值本身,而引用类型变量在内存放的是数据的引用,并不是数据的本身,引用类型变量是以间接方式去获取数据。引用类型变量都属于对象类型,如:数组、类、字符串等都属于引用类型变量。所以,引用类型变量里面存放的是数据的地址。形象的比如基本数据类型变量就像是直接放在柜子里的东西,而引用数据类型变量就是这个柜子对应编码的钥匙。钥匙号和柜子对应。
第二点:引用类型的赋值
在java编程语言中,用类的一个类型声明的变量被指定为引用类型,这是因为它正在引用一个非原始类型,这对赋值具有重要的意义。如下代码:
int x = 7;
int y = x;
String s = "Hello";
String t = s;
四个变量被创建:两个原始类型 int 和两个引用类型String。x的值是7,而这个值被复制到y;x和y是两个独立的变量且其中任何一个的进一步的变化都不对另外一个构成影响。至于变量s和t,只有一个String对象存在,它包含了文本"Hello",s和t均引用这个单一个对象。
文章图片
如果将变量t重新定义为t="World";则新的对象World被创建,而t引用这个对象。
文章图片
就上面的比喻来说,指向同一个柜子的编号肯定是相同的 t is s =true;
如果 String s = "hello";
String t ="hello";
则 s is t= false,两个“hello”申请两个不同的地址,他们的应用也不同!
第三点、按值传递和按引用传递的区别
1)按值传递
指的是在方法调用时,传递的参数是按值的拷贝传递。示例如下:
1.public class TempTest {
2.private void test1(int a) {
3.// 做点事情
4.a++;
5.}
6.
7.public static void main(Stringargs[]) {
8.TempTest t= new TempTest();
9.int a = 3;
10.t.test1(a);
//这里传递的参数a就是按值传递。
11.System.out.printIn("main方法中的a===" + a);
12.}
13.}
按值传递的重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。第9行的a和第2行的a是两个变量,当改变第2行的a的值,第9行a的值是不变的,所以打印结果是3。
main方法中的a 为 3
test1 方法中的a 为 4
我们把第9行的a称之为实参,第2行的a称之为形参;对于基本数据类型,形参数据的改变,不影响实参的数据。
2)按引用传递
指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。
示例如下:
1.public class TempTest {
2.private void test1(A a) {
3.a.age =20;
4.System.out.printIn("test1方法中的age="+a.age);
5.}
6.public static void main(Stringargs[]) {
7.TempTest t= new TempTest();
8.A a = newA();
9.a.age =10;
10.t.test1(a);
// 这里传递的参数a就是按引用传递
11.System.out.printIn("main方法中的age="+a.age);
12.}
13.}
14.classA {
15.public int age = 0;
16.}
运行结果如下:test1方法中的age = 20main方法中的age = 20
按引用传递的重要特点:
传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
要想正确理解按引用传递的过程,就必须学会理解内存分配的过程,内存分配示意图可以辅助我们去理解这个过程。
用上面的例子来进行分析:
(1)、运行开始,运行第8行,创建了一个A的实例,内存分配示意图如下:
main方法中的a
文章图片
(2)、运行第9行,修改了A实例里面的age的值,内存分配示意图如下:
main方法中的a
文章图片
(3)、运行第10行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽,但它们指向了同一个A实例。内存分配示意图如下:
文章图片
(4)、运行第3行,为test1方法中的变量a指向A实例的age进行赋值,完成后形成新的内存示意图如下:
文章图片
此时A实例的age值的变化是由test1方法引起的。
(5)、运行第4行,根据此时的内存示意图,输出test1方法中的age=20
(6)、运行第11行,根据此时的内存示意图,输出main方法中的age=20
总结二:如果是基本输入类型被传递则是按值传递 否则就是按引用传递的区别
(1)“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。
(2)在Java里面只有基本类型和按照下面这种定义方式的String是按值传递,其它的都是按引用传递。就是直接使用双引号定义的字符串方式:String str = "Java快车";
指针指向的是地址,地址指向的是内容:
【java中基本概念引用及和C语言中指针比较】int a =10;
int *p ;
p =&a;
*p =11;
这里我们看到,p 是一个变量,我们使用p来存储变量a的地址,这是,我们使用*p对于这个变量进行赋值,那么a的值最后,是多少呢,结果是11,因为我们使用*p赋值,就相当于a=11,赋值效果一样的。
从实现上来讲,引用可以理解为一种受限的指针,引用底层可以采用指针来实现,也可以采用句柄的方式实现。早期jvm一般采用句柄的方式,现在的jvm,比如sun的,IBM的,一般就是用指针来实现。另外指针是可以进行与整数做加减运算的,两个指针之间也可以进行大小比较运算和相减运算。引用不行,只能进行赋值运算。
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募