- 浏览: 367320 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (225)
- java (76)
- English (2)
- office (2)
- 架构设计 (1)
- 人在职场 (3)
- database (21)
- C# (18)
- 向往的院校 (0)
- C++ (1)
- AJAX (1)
- 操作系统 (8)
- eclipse (1)
- Spring (0)
- Linux (1)
- Javascript (6)
- 离散 (0)
- 协议 (1)
- sql server (5)
- sql server (0)
- fdf (0)
- xml (1)
- sql语句里top和distinct一起用 (1)
- 正则表达式 (7)
- 表达 (1)
- ms server (1)
- SWFObject (0)
- 线程 (2)
- Java线程 (0)
- Android & SQLite (0)
- Android (0)
- window.XMLHttpRequest (0)
- DB pool (0)
- tomcat内存溢出设置JAVA_OPTS (1)
- java bcp (1)
- 文件系统转换 (1)
- Microsoft XMLDom (1)
- tree (0)
- C# installer (0)
- 对付http cc攻击 (0)
- Ckeditor (0)
- MyEclipse (0)
- PDM (0)
- PDM OOM (0)
- asp.net (0)
- tomcat (1)
- Tomcat session (1)
- jdk (0)
- Bootstrap (0)
最新评论
-
kenail:
格式太乱了。
转 使用WebService压缩传输的心得 -
存在即为合理:
写得好乱,但是还是谢谢你的驱动
JDBC连接SQL server 2005 驱动 -
guji528:
长见识了,谢谢分享!
TL1协议(正文信息收集整理来源Internet) -
王大人:
Js window confirm()方法及其使用 -
Eastman:
SqlServer附加数据库出错,错误代码5123
今天看《Thinking in java》4th发现
//: initialization/InitialValues.java
// Shows default initial values.
import static net.mindview.util.Print.*;
public class InitialValues {
boolean t;
char c;
byte b;
short s;
int i;
long l;
float f;
double d;
InitialValues reference;
void printInitialValues() {
print("Data type Initial value");
print("boolean " + t);
print("char [" + c + "]");
print("byte " + b);
print("short " + s);
print("int " + i);
print("long " + l);
print("float " + f);
print("double " + d);
print("reference " + reference);
}
public static void main(String[] args) {
InitialValues iv = new InitialValues();
iv.printInitialValues();
/* You could also say:
new InitialValues().printInitialValues();
*/
}
} /* Output:
Data type Initial value
boolean false
char [ ]
byte 0
short 0
int 0
long 0
float 0.0
double 0.0
reference null
*///:~
我不理解不是说,变量都得初始化吗?
就查了reference的资料发现梦想风暴这篇讲得不错
Java基本功——Reference
有这样一种说法,如今争锋于IT战场的两大势力,MS一族偏重于底层实现,Java一族偏重于系统架构。说法根据无从考证,但从两大势力各自的社区力量和图书市场已有佳作不难看出,此说法不虚。于是,事情的另一面让人忽略了。
偏巧,我是一个喜欢探究底层实现的Java程序员,虽然我的喜好并非纯正咖啡,剑走偏锋却别是一番风味。
Reference
Java世界泰山北斗级大作《Thinking In Java》切入Java就提出“Everything is Object”。在Java这个充满Object的世界中,reference是一切谜题的根源,所有的故事都是从这里开始的。
Reference是什么?
如果你和我一样在进入Java世界之前曾经浪迹于C/C++世界,就一定不会对指针陌生。谈到指针,往日种种不堪回首的经历一下子涌上心头,这里不是抱怨的地方,让我们暂时忘记指针的痛苦,回忆一下最初接触指针的甜蜜吧!还记得你看过的教科书中,如何讲解指针吗?留在我印象中的一种说法是,指针就是地址,如同门牌号码一样,有了地址,你可以轻而易举找到一个人家,而不必费尽心力的大海捞针。
C++登上历史舞台,reference也随之而来,容我问个小问题,指针和reference区别何在?我的答案来自于在C++世界享誉盛名的《More Effective C++》。
- 没有null reference。
- reference必须有初值。
- 使用reference要比使用指针效率高。因为reference不需要测试其有效性。
- 指针可以重新赋值,而reference总是指向它最初获得的对象
设计选择:
当你指向你需要指向的某个东西,而且绝不会改指向其它东西,或是当你实作一个运算符而其语法需要无法有指针达成,你就应该选择reference。其它任何时候,请采用指针。
这和Java有什么关系?
初学Java,鉴于reference的名称,我毫不犹豫的将它和C++中的reference等同起来。不过,我错了。在Java中,reference可以随心所欲的赋值置空,对比一下上面列出的差异,就不难发现,Java的reference如果要与C/C++对应,它不过是一个穿着reference外衣的指针而已。
于是,所有关于C中关于指针的理解方式,可以照搬到Java中,简而言之,reference就是一个地址。我们可以把它想象成一个把手,抓住它,就抓住了我们想要操纵的数据。如同掌握C的关键在于掌握指针,探索Java的钥匙就是reference。
一段小程序
我知道,太多的文字总是令人犯困,那就来段代码吧!
public class ReferenceTricks {
public static void main(String[] args) {
ReferenceTricks r = new ReferenceTricks();
// reset integer
r.i = 0;
System.out.println("Before changeInteger:" + r.i);
changeInteger(r);
System.out.println("After changeInteger:" + r.i);
// just for format
System.out.println();
// reset integer
r.i = 0;
System.out.println("Before changeReference:" + r.i);
changeReference(r);
System.out.println("After changeReference:" + r.i);
}
private static void changeReference(ReferenceTricks r) {
r = new ReferenceTricks();
r.i = 5;
System.out.println("In changeReference: " + r.i);
}
private static void changeInteger(ReferenceTricks r) {
r.i = 5;
System.out.println("In changeInteger:" + r.i);
}
public int i;
}
对不起,我知道,把一个字段设成public是一种不好的编码习惯,这里只是为了说明问题。
如果你有兴趣自己运行一下这个程序,我等你!
OK,你已经运行过了吗?结果如何?是否如你预期?下面是我在自己的机器上运行的结果:
Before changeInteger:0
In changeInteger:5
After changeInteger:5
Before changeReference:0
In changeReference: 5
After changeReference:0
这里,我们关注的是两个change——changeReference和changeInteger。从输出的内容中,我们可以看出,两个方法在调用前和调用中完全一样,差异出现在调用后的结果。
糊涂的讲解
先让我们来分析一下changeInteger的行为。
前面说过了,Java中的reference就是一个地址,它指向了一个内存空间,这个空间存放着一个对象的相关信息。这里我们暂时不去关心这个内存具体如何排布,只要知道,通过地址,我们可以找到r这个对象的i字段,然后我们给它赋成5。既然这个字段的内容得到了修改,从函数中返回之后,它自然就是改动后的结果了,所以调用之后,r对象的i字段依然是5。下图展示了changeInteger调用前后内存变化。
Reference +--------+ Reference +--------+
---------->| i = 0 | ---------->| i = 5 |
|--------| |--------|
| Memory | | Memory |
| | | |
| | | |
+--------+ +--------+
调用changeInteger之前 调用changeInteger之后
让我们把目光转向changeReference。
从代码上,我们可以看出,同changeInteger之间的差别仅仅在于多了这么一句。
r = new ReferenceTricks();
这条语句的作用是分配一块新的内存,然后将r指向它。
执行完这条语句,r就不再是原来的r,但它依然是一个ReferenceTricks的对象,所以我们依然可以对这个r的i字段赋值。到此为止,一切都是那么自然。
Reference +--------+ +--------+
---------->| i = 0 | | i = 0 |
|--------| |--------|
| Memory | | Memory |
| | Reference |--------|
| | ---------->| i = 5 |
+--------+ +--------+
调用changeReference之前 调用changeReference之后
顺着这个思路继续下去的话,执行完changeReference,输出的r的i字段,那么应该是应该是新内存中的i,所以应该是5。至于那块被我们抛弃的内存,Java的GC功能自然会替我们善后的。
事与愿违。
实际的结果我们已经看到了,输出的是0。
肯定哪个地方错了,究竟是哪个地方呢?
参数传递的秘密
知道方法参数如何传递吗?
记得刚开始学编程那会儿,老师教导,所谓参数,有形式参数和实际参数之分,参数列表中写的那些东西都叫形式参数,在实际调用的时候,它们会被实际参数所替代。
编译程序不可能知道每次调用的实际参数都是什么,于是写编译器的高手就出个办法,让实际参数按照一定顺序放到一个大家都可以找得到的地方,以此作为方法调用的一种约定。所谓“没有规矩,不成方圆”,有了这个规矩,大家协作起来就容易多了。这个公共数据区,现在编译器的选择通常是“栈”,而所谓的顺序就是形式参数声明的顺序。
显然,程序运行的过程中,作为实际参数的变量可能遍布于内存的各个位置,而并不一定要老老实实的呆在栈里。为了守“规矩”,程序只好将变量复制一份到栈中,也就是通常所说的将参数压入栈中。
打起精神,谜底就要揭晓了。
我刚才说什么来着?将变量复制一份到栈中,没错,“复制”!
这就是所谓的值传递。
C语言的旷世经典《The C Programming Language》开篇的第一章中,谈到实际参数时说,“在C中,所有函数的实际参数都是传‘值’的”。
马上会有人站出来,“错了,还有传地址,比如以指针传递就是传地址”。
不错,传指针就是传地址。在把指针视为地址的时候,是否考虑过这样一个问题,它也是一个变量。前面的讨论中说过了,参数传递必须要把参数压入栈中,作为地址的指针也不例外。所以,必须把这个指针也复制一份。函数中对于指针操作实际上是对于这个指针副本的操作。
Java的reference等于C的指针。所以,在Java的方法调用中,reference也要复制一份压入堆栈。在方法中对reference的操作就是对这个reference副本的操作。
谜底揭晓
好,让我们回到最初的问题上。
在changeReference中对于reference的赋值实际上是对这个reference的副本进行赋值,而对于reference的本尊没有产生丝毫的影响。
回到调用点,本尊醒来,它并不知道自己睡去的这段时间内发生过什么,所以只好当作什么都没发生过一般。就这样,副本消失了,在方法中对它的修改也就烟消云散了。
也许你会问出这样的问题,“听了你的解释,我反而对changeInteger感到迷惑了,既然是对于副本的操作,为什么changeInteger可以运作正常?”
呵呵,很有趣的大脑短路现象。
好,那我就用前面的说法解释一下changeInteger的运作。
所谓复制,其结果必然是副本完全等同于本尊。reference复制的结果必然是两个reference指向同一块内存空间。
虽然在方法中对于副本的操作并不会影响到本尊,但对内存空间的修改确实实实在在的。
回到调用点,虽然本尊依然不知道曾经发生过的一切,但它按照原来的方式访问内存的时候,取到的确是经过方法修改之后的内容。
于是方法可以把自己的影响扩展到方法之外。
多说几句
这个问题起源于我对C/C++中同样问题的思考。同C/C++相比,在changeReference中对reference赋值可能并不会造成什么很严重的后果,而在C/C++中,这么做却会造成臭名昭著的“内存泄漏”,根本的原因在于Java拥有了可爱的GC功能。即便这样,我仍不推荐使用这种的手法,毕竟GC已经很忙了,我们怎么好意思再麻烦人家。
在C/C++中,这个问题还可以继续引申。既然在函数中对于指针直接赋值行不通,那么如何在函数中修改指针呢?答案很简单,指针的指针,也就是把原来的指针看作一个普通的数据,把一个指向它的指针传到函数中就可以了。
同样的问题到了Java中就没有那么美妙的解决方案了,因为Java中可没有reference的reference这样的语法。可能的变通就是将reference进行封装成类。至于值不值,公道自在人心。
参考文献
1 《Thinking in Java》
2 《More Effective C++》
3 《The C Programming Language》
可是我那个疑点还没揭开,请高手帮忙。
哈哈,书里解释:在类里定义一个对象应用时,如果不将其初始化,此应用就会获得一个特殊值NULL
发表评论
-
tomcat安装不成功.提示是:failed to install tomcat6 service ,check your setting and permis
2018-03-08 14:55 409以管理员身份运行 命令提示符,弹出窗口 ,选择“是”,输入 ... -
把系统时间设置成跟数据库的一致
2016-08-22 16:41 0public String time(int x) { ... -
struts标签<logic:iterate>的用法
2016-01-08 16:17 0<logic:iterate>主要用来 ... -
WIN7环境下cmd javac不是内部或外部命令 .
2015-07-21 11:27 1193一般步骤如下: 网上摘抄部分: JAVA_HOME ... -
jdk环境变量配置
2014-08-25 11:01 0进行java开发,首先要安装jdk,安装了jdk后还要进行环境 ... -
[转]JDBC使用TNS连接多节点Oracle
2012-06-29 15:15 1175JDBC使用TNS连接多节点O ... -
一个简单的JDBC通用工具
2012-06-29 15:01 0一个简单的JDBC通用工具 支持多种数据库,统一方式产 ... -
Java调用BCP导入数据到数据库解决标识列ID问题
2012-06-29 14:53 1089面的一篇博文讲解了调用bcp批量导出数据,对于批量导入数据则写 ... -
java 可变参数方法Object... objs
2012-06-29 14:42 4155public abstract List find(Str ... -
java调用存储过程
2012-06-14 12:34 0在java可以使用java.sql.CallableState ... -
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接 错误解决办法
2012-06-13 12:56 3044用java连接sqlserver2005时总是出现下面这个错误 ... -
javac编译外部jar包
2012-06-12 14:23 3560这个有个很简单到解决 ... -
[转]Eclipse中将Java项目(引用了第三方包) 打包为jar
2012-06-12 14:13 990如果自己的java project中需要引用额外的jar包作为 ... -
java 调用BCP导入文本数据到表
2012-06-04 15:53 0在dos下的导入语句bcp SMM_SQL_REPLICA.d ... -
[转]jdk和jre有什么区别?
2012-03-09 14:28 772来源 简单的说JDK是面 ... -
[转]Java线程:线程栈模型与线程的变量
2012-02-16 14:06 744Java线程:线程栈模型与线程的变量 SCJP5学 ... -
[转] Java线程:概念与原理
2012-02-16 13:29 795Java线程:概念与原理 ... -
Java线程:创建与启动
2012-02-16 13:26 505SCJP5学习笔记 一、定义线程 ... -
JSP页面用get传递参数乱码问题
2011-06-24 15:52 1241通过get 方式传递参数时,如果参数是中文 ,则会出现乱码现在 ... -
PO/VO/DAO/BO/POJO是什么(JAVA几种对象的解释)
2011-03-30 16:49 0/*PO:persistant object持久对 ...
相关推荐
直到查阅到类似情况:https://forums.xilinx.com/t5/Embedded-Development-Tools/SDK-undefined-reference/td-p/818300 发现我的工程的问题是gcc 链接时找不到库文件,如下图我在gcc链接命令中添加了 -llwip4 (该...
The CSS Quick Syntax Reference is a 150-page syntax reference to the Cascading Style Sheet specification and style sheet language. It presents the essentials of CSS in a well-organized format that can...
reference中的reference中的reference中的reference中的
Welcome to the Command Reference.This reference contains a complete dictionary of detailed command descriptions, arranged in alphabetical order. It is the definitive resource for correct command ...
ANSYS Mechanical APDL Theory Reference
Spring Framework 4.x Reference Documentation 中文翻译 Chinese translation of the Spring Framework 4.x Reference Documentation ...
OpenGL Reference Manual OpenGL Reference Manual
This is the MySQL™ Reference Manual. It documents MySQL 8.0 through 8.0.14. It may include documentation of features of MySQL versions that have not yet been released. For information about which ...
OpenGL 4.5 Reference Pages API + GLSLangSpec.4.60 + glspec46.coreOpenGL 4.5 Reference Pages API + GLSLangSpec.4.60 + glspec46.coreOpenGL 4.5 Reference Pages API + GLSLangSpec.4.60 + glspec46....
Volume 2, Xlib Reference Manual, is a complete programmer's reference for Xlib . Covers X11 Release 4 and Release 5. Contents Include: Reference pages for Xlib functions Reference pages for event ...
This ARM Architecture Reference Manual is protected by copyright and the practice or implementation of the information herein may be protected by one or more patents or pending applications. No part ...
The C Quick Syntax Reference is a condensed code and syntax reference to the popular C programming language, which has enjoyed some resurgence of late. C's efficiency makes it a popular choice in a ...
abaqus scripting reference manual用于ABAQUS的二次开发
S32K Reference Manual ,很值得下載,很多細節可以參考與確認。
This updated handy quick C++ 14 guide is a condensed code and syntax reference based on the newly updated C++ 14 release of the popular programming language. It presents the essential C++ syntax in a ...
The Python Quick Syntax Reference is the “go to” book that contains an easy to read and use guide to Python programming and development. This condensed code and syntax reference presents the Python ...
Volume 2, Xlib Reference Manual, is a complete programmer's reference for Xlib . Covers X11 Release 4 and Release 5. Contents Include: Reference pages for Xlib functions Reference pages for event ...
Volume 2, Xlib Reference Manual, is a complete programmer's reference for Xlib. Covers X11 Release 4 and Release 5. Contents Include: Reference pages for Xlib functions Reference pages for event ...
Zynq-7000 All Programmable SoC Technical Reference Manual
AutoCAD二次开发官方帮助文档(acad_aag.chm和acadauto.chm),acadauto.chm文件为ActiveX Reference Guide,可查询各种属性、方法和事件,并含有VBA及Visual LISP例子,acad_aag.chm文件为ActiveX Develop's Guide,...