初学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出来的是对象。

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

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

Java中对象与引用的更多相关文章

  1. Java中对象和引用的理解

    偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两方面去更形象的认识理解,再去记忆. 一.对象和引用的概念: 在Java中万 ...

  2. 详解Java中对象的软、弱和虚引用的区别

    对于大部分的对象而言,程序里会有一个引用变量来引用该对象,这是最常见的引用方法.除此之外,java.lang.ref包下还提供了3个类:SoftReference.WeakReference和Phan ...

  3. Java中对象、对象引用、堆、栈、值传递以及引用传递的详解

    Java中对象.对象引用.堆.栈.值传递以及引用传递的详解 1.对象和对象引用的差别: (1).对象: 万物皆对象.对象是类的实例. 在Java中new是用来在堆上创建对象用的. 一个对象能够被多个引 ...

  4. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

  5. 理解Java中的弱引用(Weak Reference)

    本篇文章尝试从What.Why.How这三个角度来探索Java中的弱引用,理解Java中弱引用的定义.基本使用场景和使用方法.由于个人水平有限,叙述中难免存在不准确或是不清晰的地方,希望大家可以指出, ...

  6. Java中对象的深复制和浅复制详解

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...

  7. Java中对象的生与灭- 核心篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中对象的生与灭- 核心篇>,希望对大家有帮助,谢谢 文章纯属原创,个人总结难免有差错,如果有,麻烦在评论区回复或后台私信,谢啦 简介 ...

  8. 你真的了解JAVA中对象和类、this、super和static关键字吗

    作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 目录 Java对象究竟是什么? 创建对象的过程 ...

  9. java 中对象比较大小

    java 中对象比较大小 java 中对象比较大小有两种方法 1:实现Comparable 接口 的 public int compareTo(T o) 方法: 2:实现Comparator 接口 的 ...

随机推荐

  1. 如何在linux下搭建svn服务

    • 安装svn 使用命令 yum install subversion 如果提示上述错误,请以管理员身份运行 使用命令su root 再执行 yum install subversion 2,查看sv ...

  2. Java中数组要点总结

    1.数组是基本数据类型和字符串类型的容器(引用数据类型),而集合是类数据类型的容器: 2.数组定义的格式: (1)一般格式: 元素类型[] 数组名 = new 元素类型[元素个数或者数组长度]: 其中 ...

  3. Asp.net MVC4 Step By Step(4)-使用Ajax

    Ajax技术就是利用Javascript和XML技术实现这样的效果, 可以向Web服务器发送异步请求, 返回更新部分页面的数据, 而不需要全部更新整个页面. Ajax请求两种类型的内容, 一种是服务端 ...

  4. Asp.net MVC4 Step by Step (2)-参数数据的传递

    首先创建一个表单,不同于WebForm,框架提供了一系列HMTL帮助方法来生成HTML标签. 下面创建一个Create.cshtml为文件名的视图. <h2> Create Auction ...

  5. Android RecyclerView初体验

    很早之前就听说过RecyclerView这个组件了,但一直很忙没时间学习.趁着周末,就花了一天时间来学习RecyclerView. 准备工作 在Android Studio里新建一个Android项目 ...

  6. jenkins如何实现重新发布历史构建记录里的版本

    Jenkins以前打包都会将打出的拷贝放到历史版本里放到Daily_Result里,昨天不只是误操作还是系统问题,误将一个历史版本的包删掉了,而且这个包是之前比较稳定的一个版本,需要重新给客户发,所以 ...

  7. OpenCV实现灰度直方图和直方图拉伸

    原文链接:http://blog.csdn.net/xiaowei_cqu/article/details/7600666 如有疑问或者版权问题,请移步原作者或者告知本人. 灰度直方图是数字图像中最简 ...

  8. swift 类型系统 Self self Type

    namedClass:静态类型:与类型实现直接关联:可以用于初始化.类型检查等. namedClass.self:@thick,脱敏(脱关)类型:动态类型:可以作为元类型的实例:可以作为类型参量进行传 ...

  9. 06.系统编程-4.多线程和GIL

    为什么有人会说 Python? 多线程是鸡肋?知乎上有人提出这样一个问题,在我们常识中,多进程.多线程都是通过并发的方式充分利用硬件资源提高程序的运行效率,怎么在 Python 中反而成了鸡肋? 有同 ...

  10. matplotlib的annotate用法小结

    这个是matplotlib自定义的annotate方法的文本: 一. def annotate(self, s, xy, *args, **kwargs): a = mtext.Annotation( ...