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出来的是对象。
在后面的左右都是引用的“=”语句时,左右的引用同一时候指向了右边引用所指向的对象。
再所谓实例,事实上就是对象的同义词。
Java中对象与引用的更多相关文章
- Java中对象和引用的理解
偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两方面去更形象的认识理解,再去记忆. 一.对象和引用的概念: 在Java中万 ...
- 详解Java中对象的软、弱和虚引用的区别
对于大部分的对象而言,程序里会有一个引用变量来引用该对象,这是最常见的引用方法.除此之外,java.lang.ref包下还提供了3个类:SoftReference.WeakReference和Phan ...
- Java中对象、对象引用、堆、栈、值传递以及引用传递的详解
Java中对象.对象引用.堆.栈.值传递以及引用传递的详解 1.对象和对象引用的差别: (1).对象: 万物皆对象.对象是类的实例. 在Java中new是用来在堆上创建对象用的. 一个对象能够被多个引 ...
- Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...
- 理解Java中的弱引用(Weak Reference)
本篇文章尝试从What.Why.How这三个角度来探索Java中的弱引用,理解Java中弱引用的定义.基本使用场景和使用方法.由于个人水平有限,叙述中难免存在不准确或是不清晰的地方,希望大家可以指出, ...
- Java中对象的深复制和浅复制详解
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...
- Java中对象的生与灭- 核心篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中对象的生与灭- 核心篇>,希望对大家有帮助,谢谢 文章纯属原创,个人总结难免有差错,如果有,麻烦在评论区回复或后台私信,谢啦 简介 ...
- 你真的了解JAVA中对象和类、this、super和static关键字吗
作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 目录 Java对象究竟是什么? 创建对象的过程 ...
- java 中对象比较大小
java 中对象比较大小 java 中对象比较大小有两种方法 1:实现Comparable 接口 的 public int compareTo(T o) 方法: 2:实现Comparator 接口 的 ...
随机推荐
- JQuery 动态创建表单,并自动提交
前言:写这个是为了实现使用cookie进行自动登录的功能, 下面的代码是一个元素一个元素进行创建和赋值的, (可以尝试下将所有的html代码(form.input)全部拼好以后放到${ } 中,再进行 ...
- (转)vuex2.0 基本使用(2) --- mutation 和 action
我们的项目非常简单,当点击+1按钮的时候,count 加1,点击-1按钮的时候,count 减1. 1, mutation The only way to actually change state ...
- NLP:单词嵌入Word Embeddings
深度学习.自然语言处理和表征方法 原文链接:http://blog.jobbole.com/77709/ 一个感知器网络(perceptron network).感知器 (perceptron)是非常 ...
- VTK:VTK嵌入MFC成功
VTK作为医学显示库,得到较多使用.作为较为上层的设计,对OpenGL进行了封装,并且有Windows.Linux.安卓等开发版本,可移植性较强. 不过VES暂时没有编译成功. 以下是嵌入MFC-ID ...
- 我的web前端自学之路-心得篇:我为什么要学习web前端?
时光如流水,转眼间,自己已经是大三的学长了,看着一个个学弟学妹,心中有种莫名的感觉,很怀念大学的前两年时光,但也很憧憬着自己的未来,自己将要去经历很多从未经历的事.我是我们学校信科院的一名学生,在编程 ...
- 预备篇 I :范畴与函子
拓扑是研究几何图形或空间在连续改变形状后还能保持不变的一些性质的一个学科.它只考虑物体间的位置关系而不考虑它们的形状和大小. 拓扑是集合上的一种结构. 拓扑英文名是Topology,直译是地志学,最早 ...
- php 加密解密函数封装
算法一: //加密函数 function lock_url($txt,$key='yang') { $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi ...
- vue小白学习笔记
<div id="div"> <h2>{{ key }}</h2> </div> new Vue ({ el : "#di ...
- [jzoj 5770]【2018提高组模拟A组8.6】可爱精灵宝贝 (区间dp)
传送门 Description Branimirko是一个对可爱精灵宝贝十分痴迷的玩家.最近,他闲得没事组织了一场捉精灵的游戏.游戏在一条街道上举行,街道上一侧有一排房子,从左到右房子标号由1到n. ...
- 虚拟机pycharm
一.进入虚拟机Ubuntu软件查找pycharm专业版进行安装 二.进入https://www.jetbrains.com/pycharm/download/#section=linux 下载Linu ...