对象的创建、发布、逸出
对象创建、发布
对象的创建,许多新手也都耳熟能详了,例如
public class School {private static Person person = new Person();
}
但是因为private关键字的作用,其他类无法直接访问person对象,所以产生了“发布”对象概念。对象的“发布”指的是“使对象能够在当前作用域之外的代码使用”。改变private关键字就可以达到目的:
public class School {public static Person person = new Person();
}
也有延迟创建方法,这样只有在调用init()函数时才实例化Person对象,相对来说更为优质:
public class School {private static Person person;public Person init() {person = new Person();return person;}
}
类比面向对象的封装特性,可以说“封装”是一种更加严格规范的“发布”。
对象逸出
对象发布、创建最容易犯的错误就是对象逸出,“对象逸出”指的是某不应该发布的对象被发布的情况。
例如School类引用了Person类,但是假若要求不该让外界知道Person对象的具体内容,那么之前的操作都不应该进行。但是时常发生的是:你认为已经封装好了对象,但是不经意的操作仍然造成了“对象逸出”。根据形式不同可以分为“显式逸出”和“隐式逸出”。
显式逸出
显示逸出主要问题在于向外界暴露了对象的引用。比如向外发布一个数组,很多人会选择这么做:
public class School {private Person[] personArray = new Person[] {new Person("Marco", 28), new Person("tremedous", 25)};public Person[] getPersonArray() {return personArray;}
}
这么发布Person数组并不安全,因为调用getPersonArray()函数的地方会持有personArray在堆内存中的引用,可以间接暴露、改变原personArray中的元素。
所以假若你只是想定义一个数组,只想让外界读取数组元素,不能改写数组,getPersonArray()向外界返回的应该只是personArray数组的一个副本。
public class School {private Person[] personArray = new Person[] {new Person("Marco", 28), new Person("tremedous", 25)};public Person[] getPersonArray() {//Person[] personArrayError = personArray; 错误,personArrayError仍然指向personArray数组引用地址Person[] personArrayCopy = Arrays.copyOf(personArray, personArray.length);return personArrayCopy;}
}
要格外注意新手最容易犯的错,Person[] personArrayError = personArray并不是得到了复制数组,而是在栈中产生了一个新的personArrayError变量保存Person数组在堆中地址的引用。这是personArrayError语句执行的示意图:
显式逸出还有一种情况:一个私有的对象添加到一个集合中去,其他类仍可以通过遍历集合(visitList)获得该对象:
public class School {private static Person person = new Person();public List<Person> visitList = new ArrayList();public List initList() {visitList.add(person);return visitList;}
}
隐式逸出
隐式逸出主要问题在于新建其他对象时候暴露了this引用,例如:
public class School {public static Person person;public static Room room;public School() {this.person = new Person();this.room = new Room();}
}
这里造成了this引用在构造函数逸出。因为在person对象发布(实例化)的同时,也间接发布了this应用。这样School类的构造函数还未结束,就发布了一个尚未构造完成的School对象。单线程执行问题不大, 多线程要考虑竞态条件(线程执行时序),因而这是一种不安全的对象构造过程。
该如何规避呢?多看看一些别人的工程代码后,你就容易得到你的答案:
public class School {public static Person person;public static Room room;public School() {initParam();}private synchronized void initParam() {this.person = new Person();this.room = new Room();}
}
首先,initParam()函数用了synchronized互斥锁,意味着同一时刻只能有一个线程来实例化person和room对象。
再者,调用initParam(),未到达方法出口,不会提前暴露this引用,也就不会造成未构造完成的School对象被提前发布了。
对象的创建、发布、逸出相关推荐
- Java并发学习笔记(8)发布逸出
发布逸出 (1)发布:发布是指将一个对象,使其引用储存到一个其他代码可以访问到的地方,在一个非私有方法返回这个引用,也可以把它传递到其他对象中. a) 发布最简单的就是将对象设置到公共静态域中 b) ...
- java this 逸出_发布逸出 java this 逸出【转】
转自:http://blog.csdn.net/joker_zhou/article/details/7322801 (1)发布:发布是指将一个对象,使其引用储存到一个其他代码可以访问到的地方,在一个 ...
- Java 并发编程(二)对象的发布逸出和线程封闭
对象的发布与逸出 "发布(Publish)"一个对象是指使对象能够在当前作用域之外的代码中使用.可以通过 公有静态变量,非私有方法,构造方法内隐含引用 三种方式. 如果对象构造完成 ...
- Java多线程 发布private对象逸出的演示
文章目录 发布逸出 发布逸出 什么是发布: 把这个对象, 给别的类去使用. (作为参数传递, return对象等情况. ) 对象逸出: 对象发布到了不该发布的地方. 如下的情况都是逸出 如下的代码演示 ...
- 《java并发编程实战》读书笔记二 对象的发布与逸出
概念 发布(publishing): 发布一个对象的意思是使它能够被当前范围之外的代码所使用.比如将一个引用存储到其他代码可以访问的地方,在一个非私有的方法中返回这个引用,也可以把它传递到其他类的方法 ...
- Java多线程 解决private对象逸出--返回副本
文章目录 解决private对象逸出--返回副本 解决private对象逸出–返回副本 如下的代码, 使用的是返回对象的副本的方式, 来解决private对象逸出 package com.thread ...
- 逸出 java_【java】知识系谱-基础篇-线程-发布、逸出
java并发编程实战的解释,不够详细,尤其this引用逸出让人理解有些费解,java并发编程实战里面的内容就直接拷贝过来 发布:使对象能够在当前作用域之外的代码中使用 逸出:当某个不该被发布的对象被发 ...
- java this 逸出_this引用逸出
1.定义 public class UnsafeClass { public UnsafeClass(Button button) { button.addActionListener(new Act ...
- 并发编程之对象的发布和逸出
一.对象的发布和逸出 发布(publish)对象意味着其作用域之外的代码可以访问操作此对象.例如将对象的引用保存到其他代码可以访问的地方,或者在非私有的方法中返回对象的引用,或者将对象的引用传递给其他 ...
最新文章
- CUDA是Nvidia开发的一种并行计算平台和编程模型,用于在其自己的GPU(图形处理单元)上进行常规计算
- uniapp /deep/设置uni-app组件样式时 h5生效 小程序失效问题解决
- 【转】excel表格导出集锦repeater实用,和普通用法
- java 字符串原样输出_Java 中如何原样输出转义符号
- JNDI学习总结(3)——Tomcat下使用C3P0配置JNDI数据源
- Java Web基础回顾 —JQuery DOM
- REACT打印页面组件
- gurobi和java,在Java中使用Gurobi与在Ampl中使用Gurobi
- html快闪软件制作,抖音如何制作快闪视频?怎样快速制作炫酷视频?
- 【第十届“泰迪杯”数据挖掘挑战赛】C题:疫情背景下的周边游需求图谱分析 问题三方案及Python实现
- FreeWheel是一家怎样的公司?
- 著名英文谚语(珍藏版)
- 在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。
- 使用Juju将OpenStack部署在单机的LXD容器上(by quqi99)
- FPGA的六大应用领域,你了解吗?
- oracle dg备库恢复
- 适合计算机社团活动的游戏,活跃气氛的70个小游戏 适合集体活动的趣味游戏
- sitemap.xml格式实例说明
- 如何写出一篇优秀的博客文章
- 常见大数据面试话术(建议收藏)