对象创建、发布

对象的创建,许多新手也都耳熟能详了,例如

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对象被提前发布了。

对象的创建、发布、逸出相关推荐

  1. Java并发学习笔记(8)发布逸出

    发布逸出 (1)发布:发布是指将一个对象,使其引用储存到一个其他代码可以访问到的地方,在一个非私有方法返回这个引用,也可以把它传递到其他对象中. a)  发布最简单的就是将对象设置到公共静态域中 b) ...

  2. java this 逸出_发布逸出 java this 逸出【转】

    转自:http://blog.csdn.net/joker_zhou/article/details/7322801 (1)发布:发布是指将一个对象,使其引用储存到一个其他代码可以访问到的地方,在一个 ...

  3. Java 并发编程(二)对象的发布逸出和线程封闭

    对象的发布与逸出 "发布(Publish)"一个对象是指使对象能够在当前作用域之外的代码中使用.可以通过 公有静态变量,非私有方法,构造方法内隐含引用 三种方式. 如果对象构造完成 ...

  4. Java多线程 发布private对象逸出的演示

    文章目录 发布逸出 发布逸出 什么是发布: 把这个对象, 给别的类去使用. (作为参数传递, return对象等情况. ) 对象逸出: 对象发布到了不该发布的地方. 如下的情况都是逸出 如下的代码演示 ...

  5. 《java并发编程实战》读书笔记二 对象的发布与逸出

    概念 发布(publishing): 发布一个对象的意思是使它能够被当前范围之外的代码所使用.比如将一个引用存储到其他代码可以访问的地方,在一个非私有的方法中返回这个引用,也可以把它传递到其他类的方法 ...

  6. Java多线程 解决private对象逸出--返回副本

    文章目录 解决private对象逸出--返回副本 解决private对象逸出–返回副本 如下的代码, 使用的是返回对象的副本的方式, 来解决private对象逸出 package com.thread ...

  7. 逸出 java_【java】知识系谱-基础篇-线程-发布、逸出

    java并发编程实战的解释,不够详细,尤其this引用逸出让人理解有些费解,java并发编程实战里面的内容就直接拷贝过来 发布:使对象能够在当前作用域之外的代码中使用 逸出:当某个不该被发布的对象被发 ...

  8. java this 逸出_this引用逸出

    1.定义 public class UnsafeClass { public UnsafeClass(Button button) { button.addActionListener(new Act ...

  9. 并发编程之对象的发布和逸出

    一.对象的发布和逸出 发布(publish)对象意味着其作用域之外的代码可以访问操作此对象.例如将对象的引用保存到其他代码可以访问的地方,或者在非私有的方法中返回对象的引用,或者将对象的引用传递给其他 ...

最新文章

  1. CUDA是Nvidia开发的一种并行计算平台和编程模型,用于在其自己的GPU(图形处理单元)上进行常规计算
  2. uniapp /deep/设置uni-app组件样式时 h5生效 小程序失效问题解决
  3. 【转】excel表格导出集锦repeater实用,和普通用法
  4. java 字符串原样输出_Java 中如何原样输出转义符号
  5. JNDI学习总结(3)——Tomcat下使用C3P0配置JNDI数据源
  6. Java Web基础回顾 —JQuery DOM
  7. REACT打印页面组件
  8. gurobi和java,在Java中使用Gurobi与在Ampl中使用Gurobi
  9. html快闪软件制作,抖音如何制作快闪视频?怎样快速制作炫酷视频?
  10. 【第十届“泰迪杯”数据挖掘挑战赛】C题:疫情背景下的周边游需求图谱分析 问题三方案及Python实现
  11. FreeWheel是一家怎样的公司?
  12. 著名英文谚语(珍藏版)
  13. 在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。
  14. 使用Juju将OpenStack部署在单机的LXD容器上(by quqi99)
  15. FPGA的六大应用领域,你了解吗?
  16. oracle dg备库恢复
  17. 适合计算机社团活动的游戏,活跃气氛的70个小游戏 适合集体活动的趣味游戏
  18. sitemap.xml格式实例说明
  19. 如何写出一篇优秀的博客文章
  20. 常见大数据面试话术(建议收藏)

热门文章

  1. 现代计算机技术是什么,现代教育中计算机技术的应用分析
  2. 纵横交错的学问——Power Plan
  3. android上传图片到PHP后台全过程
  4. 有没有什么惊艳的微信头像?Python一键下载1000张!
  5. 联发科linux开发板,MT7688
  6. LLDB(四):Chisel 的安装与使用
  7. ArcGIS:从dem提取水系(以雅江为例)
  8. 离散数学实验一 真值计算
  9. 内存烤机是什么 aida64内存测试爆红是什么原因
  10. fctix 中文输入法如何翻页