zoukankan      html  css  js  c++  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 对象的内存地址( 有点C 语言中指针的味道) 。

        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) 一个对象引用能够指向0 个或1 个对象( 一根线能够不系风筝,也能够系一个风筝) ,并且能够改指。

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

    假设有以下语句:stu1=stu2;

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

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

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

        至少是无用的吧?不正确。它是合法的。并且可用的。譬如。假设我们只为了打印而生成一个对象, 就不须要用引用变量来系住它。

    最常见的就是打印字符System.out.println("I am Java!"); 字符串对象"I am Java!" 在打印后即被丢弃,有人把这样的对象称之为暂时对象。

     

     

    java中的构造函数

    原则:

    1.构造方法不能声明返回类型,不能被static、final、synchronized、abstract、native修饰。

    2.当某个类中没有自己定义的构造方法时。编译器会自己主动为你产生一个缺省的构造方法。这是一个不带參数且没有不论什么代码的构造方法。可是一旦你为你的类定义了一个构造方法。无论是否带參数,那么编译器将不会再为你产生缺省的构造方法。

    3.父类的构造方法不能被子类继承。

    子类不能直接通过方法名调用父类的一个构造方法。而是要通过superkeyword调用父类的一个构造方法,super语句必须位于子类构造方法的第一行。

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

    5.当一个类有几个构造方法时假设想在一个构造方法(暂定名为a)中调用还有一个构造方法(暂定名为b),须要使用thiskeyword而不是用方法名直接调用且this句必需放在第一行;在这样的情况下。假设通过thiskeyword调用的构造方法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中,没有 引用传递,仅仅有值传递!




    再啰嗦下    

    例如以下表达式:
      A a1 = new A();
    它代表A是类,a1是引用,a1不是对象,new A()才是对象,a1引用指向new A()这个对象。


    在JAVA里。“=”不能被看成是一个赋值语句,它不是在把一个对象赋给另外一个对象,它的运行过程实质上是将右边对象的地址传给了左边的引用,使得左边的引用指向了右边的对象。

    JAVA表面上看起来没有指针。但它的引用事实上质就是一个指针,引用里面存放的并非对象。而是该对象的地址,使得该引用指向了对象。在JAVA里,“=”语句不应该被翻译成赋值语句,由于它所运行的确实不是一个赋值的过程,而是一个传地址的过程。被译成赋值语句会造成非常多误解,译得不准确。


    再如:
    A a2;
    它代表A是类,a2是引用。a2不是对象,a2所指向的对象为空null;


    再如:
    a2 = a1;
    它代表,a2是引用,a1也是引用,a1所指向的对象的地址传给了a2(传址),使得a2和a1指向了同一对象。


    综上所述,能够简单的记为。在初始化时,“=”语句左边的是引用。右边new出来的是对象。


    在后面的左右都是引用的“=”语句时,左右的引用同一时候指向了右边引用所指向的对象。




    再所谓实例,事实上就是对象的同义词。


  • 相关阅读:
    PHP中的PEAR是什么?
    Cookie禁用了,Session还能用吗?原因详解
    php中echo、print、print_r、var_dump、var_export区别
    超强汇总!110 道 Python 面试笔试题
    九种跨域方式实现原理
    在MySQL中如何使用覆盖索引优化limit分页查询
    Laravel大型项目系列教程(五)之文章和标签管理
    Bootstrap-tagsinput标系统使用心得
    bootstrap-datepicker使用
    谭安林:大数据在教育行业的研究与应用
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7140594.html
Copyright © 2011-2022 走看看