AJPFX谈Java 性能优化之基本类型 vs 引用类型
★名词定义
先明确一下什么是“基本类型”,什么是“引用类型”。
简单地说,所谓基本类型就是 Java 语言中如下的8种内置类型:
boolean
char
byte
short
int
long
float
double
而引用类型就是那些可以通过 new 来创建对象的类型(基本上都是派生自 Object)。
★两种类型的存储方式
这两种类型的差异,首先体现在存储方式上。
◇引用类型的创建
当你在函数中创建一个引用类型的对象时,比如下面这句:
StringBuffer str = new StringBuffer();
该 StringBuffer 【对象】的内容是存储在堆(Heap)上的,需要申请堆内存。而变量 str 只不过是针对该 StringBuffer 对象的一个引用(或者叫地址)。变量 str 的【值】(也就是 StringBuffer 对象的地址)是存储在【栈】上的。
◇基本类型的创建
当你在【函数中}创建一个基本类型的变量时,比如下面这句:
int n = 123;
这个变量 n 的【值】也是存储在栈(Stack)上的,但是这个语句不需要再从堆中申请内存了。
为了更加形象,便于大伙儿理解,简单画了一个示意图如下:
★堆和栈的性能差异
可能有同学会小声问:堆和栈有啥区别捏?
要说堆和栈的差别,那可就大了去了。如果你对这两个概念还是不太明白或者经常混淆,建议先找本操作系统的书拜读一下。
由于是介绍性能,所以来讨论一下堆和栈在性能方面的差别(这个差异是很大滴)。堆相对进程来说是全局的,能够被所有线程访问;而栈是线程局部的,只能本线程访问。打个比方,栈就好比个人小金库,堆就好比国库。你从个人小金库拿钱去花,不需要办什么手续,拿了就花,但是钱数有限;而国库里面的钱虽然很多,但是每次申请花钱要打报告、盖图章、办 N 多手续,耗时又费力。
同样道理,由于堆是所有线程共有的,从堆里面申请内存要进行相关的加锁操作,因此申请堆内存的复杂度和时间开销比栈要大很多;从栈里面申请内存,虽然又简单又快,但是栈的大小有限,分配不了太多内存。
★当初为啥这样设计?
可能有同学又问了,干嘛把两种类型分开存储,干嘛不放到一起捏?这个问题问得好!下面我们就来揣测一下,当初 Java 为啥设计成这样。
当年 Java 它爹(James Gosling)设计语言的时候,对于这个问题有点进退两难。如果把各种东东都放置到栈中,显然不现实,一来栈是线程私有的(不便于共享),二来栈的大小是有限的,三来栈的结构也间接限制了它的用途。那为啥不把各种东东都放置到堆里面捏?都放堆里面,倒是能绕过上述问题,但是刚才也提到了,申请堆内存要办很多手续,太繁琐。如果仅仅在函数中写一个简单的“int n = 0;”,也要到堆里面去分配内存,那性能就大大滴差了(要知道 Java 是1995年生出来的,那年头俺买了台 PC 配【4兆内存】就属豪华配置了)。
左思右想之后,Java 它爹只好做了一个折中:把类型分为“基本类型”和“引用类型”,两者使用不同的创建方式。这种差异从 Java 语法上也可以看出来:引用类型总是用 new 创建对象(提醒一下:某些单键对象/单例对象,表面上没用 new,但是在 getInstance() 内部也还是用 new 创建的);而基本类型则【不需要】用 new 来创建。
★这样设计的弊端
顺便跑题一下,斗胆评价 Java 它爹这种设计的弊端(希望 Java Fans 不要跟我急)。我个人认为:这个折中的决策,带来了许多深远的影响,随手举出几个例子:
1、由于基本类型不是派生自 Object,因此不能算是纯种的对象。这导致了 Java 的“【纯】面向对象”招牌打了折扣(当年 Sun 老是吹嘘 Java 是“纯”OO 的语言,其实 Java 的 OO 是不够纯粹滴)。
2、由于基本类型不是派生自 Object,出于某些场合(比如容器类)的考虑,不得不为每个基本类型加上对应的包装类(比如 Integer、Byte 等),使得语言变得有点冗余。
★结论
从上述的介绍,我们应该明白,使用 new 创建对象的开销是【不小】的。在程序中能避免就应该尽量避免。另外,使用 new 创建对象,不光是创建时开销大,将来垃圾回收时,销毁对象也是有开销的
AJPFX谈Java 性能优化之基本类型 vs 引用类型的更多相关文章
- AJPFX浅谈Java性能优化之finalize 函数
★finalize 函数的调用机制 俺经常啰嗦:“了解本质机制的重要性”.所以今天也得先谈谈 finalize 函数的调用机制.在聊之前,先声明一下:Java虚拟机规范,并没有硬性规定垃圾回收该不该搞 ...
- AJPFX浅谈Java 性能优化之垃圾回收(GC)
★JVM 的内存空间 在 Java 虚拟机规范中,提及了如下几种类型的内存空间: ◇栈内存(Stack):每个线程私有的.◇堆内存(Heap):所有线程公用的.◇方法区(Method Area):有点 ...
- AJPFX浅谈Java 性能优化之字符串过滤实战
★一个简单的需求 首先描述一下需求:给定一个 String 对象,过滤掉除了数字(字符'0'到'9')以外的其它字符.要求时间开销尽可能小.过滤函数的原型如下: String filter(Strin ...
- 【转】10种简单的Java性能优化
10种简单的Java性能优化 2015/06/23 | 分类: 基础技术 | 14 条评论 | 标签: 性能优化 分享到: 本文由 ImportNew - 一直在路上 翻译自 jaxenter.欢迎加 ...
- Java 性能优化之 String 篇
原文:http://www.ibm.com/developerworks/cn/java/j-lo-optmizestring/ Java 性能优化之 String 篇 String 方法用于文本分析 ...
- 《Java性能优化权威指南》
<Java性能优化权威指南> 基本信息 原书名:Java performance 原出版社: Addison-Wesley Professional 作者: (美)Charlie Hunt ...
- 推荐:Java性能优化系列集锦
Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...
- JVM——九大工具助你玩转Java性能优化
本文转载自 http://www.importnew.com/12324.html 本文由 ImportNew - 陈 晓舜 翻译自 idrsolutions.欢迎加入翻译小组.转载请参见文章末尾的要 ...
- 44个Java性能优化
44个Java性能优化 首先,代码优化的目标是: 减小代码的体积 提高代码运行效率 代码优化细节 1 .尽量指定类.方法的final修饰符 带有final修饰符的类是不可派生的.在Java核心AP ...
随机推荐
- 初探linux子系统集之led子系统(一)【转】
本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37569789 就像学编程第一个范例helloworld一样,学嵌入式,单片机.f ...
- hihocoder #1068 : RMQ-ST算法 ( RMQ算法 O(nlogn)处理 O(1)查询 *【模板】 1)初始化d数组直接读入+计算k值用数学函数log2()==*节约时间 )
#1068 : RMQ-ST算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在美国旅行了相当长的一段时间之后,终于准备要回国啦!而在回国之前,他们准备 ...
- poj 1789 Truck History 解题报告
题目链接:http://poj.org/problem?id=1789 题目意思:给出 N 行,每行7个字符你,统计所有的 行 与 行 之间的差值(就是相同位置下字母不相同),一个位置不相同就为1,依 ...
- SPOJ:Dandiya Night and Violence(Bitset优化)
It is Dandiya Night! A certain way how dandiya is played is described: There are N pairs of people p ...
- kali-linux简单学习
一. curl --head 返回操作系统的版本 同样的Xprobe2可以和nmap一起返回操作系统的版本 nmap 直接加域名或者ip地址,比较权威判断操作系统版本,或者服务版本,以及开的端口 nm ...
- 深入理解dispatch_sync
关于GCD的基础知识,之前写过一篇博客,详见GCD基础知识.虽然之前已经梳理过了,但对很多知识点的理解仍然不够透彻…写这篇博客的原因是在阅读AFNetworking代码时遇到一些奇怪的代码. 如下: ...
- DP专辑之最长公共子序列及其变形
vijos1111(裸的最长公共子序列) 链接:www.vijos.org/p/1111 题解:好久没有写最长公共子序列了,这题就当是复习了.求出最长公共子序列,然后用两个单词的总长度减去最长公共子序 ...
- AJAX如何传递json对象给后端
如果页面上一直报错,根本没有触发异步请求的话,首先就要检查接口或者路径是否写对或者写全,在去考虑是否跨境的问题. 如果想要给后端传递一个json对象,需要在路径上一句添加content:applica ...
- nodejs开发游戏服务器遇到的性能问题
问题描述: 使用nodejs开发了一个游戏服务器,为了尽可能提高服务器的性能,服务器采用多进程的架构,前面处理玩家socket连接的是多个nodejs进程,使用 child_process 模块,服务 ...
- YARN(MapReduce 2)运行MapReduce的过程-源码分析
这是我的分析,当然查阅书籍和网络.如有什么不对的,请各位批评指正.以下的类有的并不完全,只列出重要的方法. 如要转载,请注上作者以及出处. 一.源码阅读环境 需要安装jdk1.7.0版本及其以上版本, ...