Java中对象与引用

 Java中对象与引用

   初学Java 时,在很长一段时间里,总觉得基本概念很模糊。后来才知道,在许多Java 书中,把对象和对象的引用混为一谈。 

    如果分不清对象与对象引用,那实在没法很好地理解下面的面向对象技术,把自己的一点认识写下来,或许能让初学Java 的朋友们少走一点弯路。         

    为便于说明,我们先定义一个简单的类:       

 class student{   

  int name;   

  int age;   

  int sex;   

}    

    有了这个类模板,就可以用它来创建对象:student stu1 = new student(); 

    通常把这条语句的动作称之为创建一个对象,其实,它包含了四个动作。 

    1) 右边的"new student" ,是以student 类为模板,在堆空间里创建一个student 类的对象也简称为student 对象。 

    2) 末尾的() 意味着,在对象创建后,立即调用student 类的构造函数,对刚生成的对象进行初始化。 

构造函数是肯定有的。如果你没写,Java 会给你补上一个默认的构造函数。 

    3) 左边的"student stu1" 创建了一个student 类引用变量。所谓student 类引用,就是以后可以用来指向某个 

student 对象的对象引用,它指向的是某个student 对象的内存地址有点语言中指针的味道。 

    4)"=" 操作符使对象引用指向刚创建的那个student 对象。 

    我们可以把这条语句拆成两部分:student stu1; stu1 = new student(); 效果是一样的。 

    这样写,就比较清楚了,有两个实体:一是对象引用变量(stu1) ,在Sun 公司的实现中对象的引用是一个句柄其中包含一对指针一个指针指向该对象的方法表,一个指向该对象的数据;另一个是对象本身就是new 出来的那个对象。 

    在堆空间里创建的实体,与在数据段以及栈空间里创建的实体不同。尽管它们也是确确实实存在的实体, 但是,我们看不见,也摸不着。不仅如此,我们仔细研究一下第二句,想想刚刚创建的student 对象叫什么名字? 

    有人说,它叫"student" 。不对,"student" 是类对象的创建模板的名字。一个student 类可以据此创建 出无数个对象,这些对象不可能全叫"student" 。对象连名都没有,没法直接访问它。我们只能通过 对象引用来间接访问对象。

    为了形象地说明对象、对象引用及它们之间的关系,可以做一个或许不很妥当的比喻: 

    对象好比是一只没有线的风筝,引用变量是一根线,可以用来系风筝。如果只执行了第一条语句, 还没执行第二条,此时创建的引用变量stu1 还没指向任何一个对象,它的值是null ,引用变量可以 指向某个对象,或者为null 。这时stu1 是一根线,一根还没有系上任何一个风筝的线。 

    执行了第二句后,一只新风筝做出来了,并被系在stu1 这根线上。我们抓住这根线,就等于抓住了那只风筝。 

    再来一句:student stu2; 就又做了一根线,还没系上风筝。如果再加一句:stu2=stu1; 系上风筝了。 

    这里,发生了复制行为。但是,要说明的是,对象本身并没有被复制,被复制的只是对象引用。 

    结果是,stu2 也指向了stu1 所指向的对象,也就是两根线系的是同一只风筝。 

    如果用下句再创建一个对象:stu2=new student(); 则引用变量stu2 改指向第二个对象。 

    从以上叙述再推演下去,我们可以获得以下结论: 

    (1) 一个对象引用可以指向个或个对象一根线可以不系风筝,也可以系一个风筝,而且可以改指; 

    (2) 一个对象可以有个引用指向它可以有条线系同一个风筝。 

如果有下面语句:stu1=stu2; 

    按上面的推断,stu1 也指向了第二个对象。这个没问题。问题是第一个对象呢?没有一条线系住它,它飞了。 

    很多书里说,它被Java 的垃圾回收机制回收了,这不确切,准确地说,它已成为Java 垃圾回收机制的处理对象。 

    至于什么时候真正被回收,那要看垃圾回收机制的心情了。由此看来,new student(); 该语句应该不合法吧, 

    至少是没用的吧?不对,它是合法的,而且可用的。譬如,如果我们仅仅为了打印而生成一个对象, 就不需要用引用变量来系住它。最常见的就是打印字符System.out.println("I am Java!"); 字符串对象"I am Java!" 在打印后即被丢弃,有人把这种对象称之为临时对象。

java中的构造函数

原则:

1.构造方法不能声明返回类型,不能被staticfinalsynchronizedabstractnative修饰。

2.当某个类中没有自定义的构造方法时,编译器会自动为你产生一个缺省的构造方法,这是一个不带参数且没有任何代码的构造方法;但是一旦你为你的类定义了一个构造方法,不管是否带参数,那么编译器将不会再为你产生缺省的构造方法。

3.父类的构造方法不能被子类继承。子类不能直接通过方法名调用父类的一个构造方法,而是要通过super关键字调用父类的一个构造方法,super语句必须位于子类构造方法的第一行。

4.当你试图调用某个类的某一构造方法(暂定名为a方法)来产生该类的一个实例时,将首先需要调用其父类的构造方法,此时有两种情况:(1)a方法中显示地用super关键字调用了父类的某一构造方法(是否带参都行)(注意此时super句必需出现在a方法的第一行);(2a方法中没有显示地用super关键字调用了父类的某一构造方法,此时编译器在编译子类时会a方法中的第一行加上super();语句。

5.当一个类有几个构造方法时如果想在一个构造方法(暂定名为a)中调用另一个构造方法(暂定名为b),需要使用this关键字而不是用方法名直接调用且this句必需放在第一行;在这种情况下,如果通过this关键字调用的构造方法b中显示地调用了父类的某一构造方法时,编译器不会再在a方法中添加super();来调用父类的缺省构造方法。

也谈Java值传递-到底传递了什么?

java里面只有值传递,这是不变的真理,不过由于对象类型的特殊性,有些人还是会疑惑 值传递?还是 引用传递?

可能主要是这句话造成的Java中方法参数的传递,对象是传递引用,基本数据类型是传递值。

如果java里面只有值传递,为何又要说对象是 引用传递?

对于 基本数据类型 是值传递,相信没有人会有疑惑。那对象到底传递了什么?

其实这源于JAVA在解释其变量类型时的一个混淆:JAVA里面只有8种基本数据类型和对象类型

于是便有了 基本数据类型是传递值,对象是传递引用

其实如果把对象类型也解释成一种基本数据类型 ,那就不会出现 对象是传递引用 这句话让人疑惑的话了

下文将 对象类型 看成一种新的基本类型姑且称之为 olong (object long),即 所有对象变量 都是 olong,虽然在java书写时可以写成具体的对象类型,如 Long a; 但其传递实质是  olong a;

让我们来重新认识 olong :

赋值:

long a = 1234;

olong oa = new Long(1234); //Long oa = new Long(1234);

传递:

long b = a;

olong ob =oa;  //Long ob = oa;

 

改变:

b = 4321;

ob = new Long(4321); //ob = new Long(4321);

改变了什么?:

System.out.println(a); //输出 1234

System.out.println(b); //输出 4321

System.out.println(oa.longValue()); //输出 1234

System.out.println(ob.longValue()); //输出 4321

到底传递了什么:

long:

long a = 1234; //a的值1234

long b = a;//值传递 b的值1234;a的值1234

b = 4321;//b的值被改变为4321;a不受影响,依然是1234

olong:

long类型的变量保存和传递的是其指代的基本类型的值,那么olong?

可以认为olong类型的变量保存和传递的是一个指向具体对象的内存地址,

olong oa = new Long(1234);//假设new Long生成的对象的地址为0001,oa的值为0001

olong ob =oa; //值传递,ob的值0001;oa的值0001

ob = new Long(4321);//ob的值被赋予一个新的对象的地址,假设为0002,oa的值不受影响,依然为0001

因此olong类型的赋值结果与long类型的表现一致,也是值传递

为什么对象是传递引用?

其实这句话也不错,因为olong变量本身就是一个引用,引用了一个对象(的内存地址)

但其实质是 值传递!只不过因为 olong 的值 还有一个 别名 叫做 引用,所以就被叫做了一个让人迷惑的新词:引用传递!

总结:

olong的引入只是为了方便解释Java对象的值传递,说明在参数传递过程中,对象变量的传递和基本变量的传递是没有本质区别的,所以,在Java,没有 引用传递,只有值传递!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值