每个学 Java 的人都应该搞懂
http://www.cnblogs.com/benshing/archive/2006/12/17/595097.html 分享
问题一: 我声明了什么!
String s = "Hello world!";
许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个 String ,内容是 “Hello world!” 。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。
这个语句声明的是一个指向对象的引用,名为 “s” ,可以指向类型为 String 的任何对象,目前指向 "Hello world!" 这个 String 类型的对象。这就是真正发生的事情。我们并没有声明一个 String 对象,我们只是声明了一个只能指向 String 对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句:
String string = s;
我们是声明了另外一个只能指向 String 对象的引用,名为 string ,并没有第二个对象产生, string 还是指向原来那个对象,也就是,和 s 指向同一个对象。
问题二: "==" 和 equals 方法究竟有什么区别?
问题三: String 到底变了没有?
没有。因为 String 被设计成不可变 (immutable) 类,所以它的所有对象都是不可变对象。请看下列代码:
String s = "Hello";
s = s + " world!";
s 所指向的对象是否改变了呢?从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中, s 原先指向一个 String 对象,内容是 "Hello" ,然后我们对 s 进行了 + 操作,那么 s 所指向的那个对象是否发生了改变呢?答案是没有。这时, s 不指向原来那个对象了,而指向了另一个 String 对象,内容为 "Hello world!" ,原来那个对象还存在于内存之中,只是 s 这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用 String 来代表字符串的话会引起很大的内存开销。因为 String 对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个 String 对象来表示。这时,应该考虑使用 StringBuffer 类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都 new 一个 String 。例如我们要在构造器中对一个名叫 s 的 String 引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非 s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为 String 对象不可改变,所以对于内容相同的字符串,只要一个 String 对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的 String 类型属性 s 都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同, Java 认为它们代表同一个 String 对象。而用关键字 new 调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把 String 类设计成不可变类,是它的用途决定的。其实不只 String ,很多 Java 标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以 Java 标准类库还提供了一个可变版本,即 StringBuffer 。
问题四: final 关键字到底修饰了什么?
final 使得被修饰的变量 " 不变 " ,但是由于对象型变量的本质是 “ 引用 ” ,使得 “ 不变 ” 也有了两种含义:引用本身的不变,和引用指向的对象不变。
引用本身的不变:
final StringBuffer a=new StringBuffer("immutable");
final StringBuffer b=new StringBuffer("not immutable");
a=b;// 编译期错误
引用指向的对象不变:
final StringBuffer a=new StringBuffer("immutable");
a.append(" broken!"); // 编译通过
可见, final 只对引用的 “ 值 ”( 也即它所指向的那个对象的内存地址 ) 有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象的变化, final 是不负责的。这很类似 == 操作符: == 操作符只负责引用的 “ 值 ” 相等,至于这个地址所指向的对象内容是否相等, == 操作符是不管的。
理解 final 问题有很重要的含义。许多程序漏洞都基于此 ----final 只能保证引用永远指向固定对象,不能保证那个对象的状态不变。在多线程的操作中 , 一个对象会被多个线程共享或修改,一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为 final ,意图使得它 “ 永远不变 ” 。其实那是徒劳的
分享到:
相关推荐
### 每个学Java的人都应该搞懂的关键概念 在Java编程的学习旅程中,有若干核心概念是每位学习者必须掌握的。本文将基于提供的部分信息深入解析这些关键知识点,帮助初学者更好地理解并运用Java。 #### Java中的...
### 每个学Java的人都应该搞懂的问题 在学习Java的过程中,会遇到许多经典问题,这些问题不仅是初学者常犯的错误来源,也是深入理解Java语言特性的重要途径。本文将针对给定文件中的几个核心问题进行详细解析,帮助...
每个学Java的人都应该搞懂。当然,如果只是学Java玩玩就无所谓了。如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列。
这个名为“每个JAVA初学者都应该搞懂的问题”的压缩包文件,显然是为那些刚开始学习Java的人准备的一份详细教程。让我们来探讨一下其中可能包含的知识点。 首先,我们看到一个名为“每个JAVA初学者都应该搞懂的问题...
对于一个以前从来没有接触过java的人,java无疑是庞大的,似乎每个领域都可以拓展开来都是一片开阔地,每一个领域要想深入接触到每一个细节所耗费的精力都是巨大的。这个时候大家都胸怀壮志,两眼发光的盯着每一个...
这本书适合具备一定编程基础,工作1-3年的研发人员,想阅读Java核心源码但总感觉看不懂的人,看了太多理论但没有实践验证的人,以及求职面试时总被面试题搞的死去活来的人。通过阅读这本书,你可以学到怎么写简历、...
JAVA工程有很多配置文件,单纯看配置文件有时难以掌握一个交易的流程,甚至花很长时间也难以搞懂交易的流程。SOPA将交易流程生成到文件,类似于一个建筑的图纸一样,使开发人员通过看流程分析图可以在短时间内就可以...
2. **每个初学者都应该搞懂的问题.doc**: 这份文档可能会列出Java初学者常常遇到的困惑点和关键知识点,比如JVM的工作原理、垃圾回收机制、内存模型、异常处理的最佳实践、以及如何调试代码等。理解和掌握这些内容...
- 然后,对每个模块进行深入分析。 - 在此过程中,注意区分系统函数和自定义函数,前者通常不需详细阅读,只需了解其功能即可。 5. **逐步细化**:从高层次到细节逐步深入阅读,这样可以避免一开始就陷入细节问题...
作者从切身体会出发,深知配套教程的重要性,因此精心编写了一组使用文档,亲测每一个步骤,力求为用户的使用提供最大程度的方便。 tjpcms收费吗? 开源(采用最宽松的MIT 协议)、免费(个人参考学习、商用均免费...
程序员的发展过程可以分为十个层次,每个层次都有其特点和要求。以下是对每个层次的详细解释: 第 1 层:菜鸟 程序员的发展过程从菜鸟开始。菜鸟层的门槛很低,只需要懂计算机的基本操作,了解计算机专业的一些...
1. 找到一本浅显易懂的教程,从头到尾学习,实践例程,并搞懂每个例程的原理。 2. 找一个实际项目练手,例如创建一个网站,解决实际问题。 3. 找到一个已经会 Python 的人,向其请教学习规划和卡壳时的建议。 在...
javaEE 并进行小组实验确实挺难受的,在实验验收方面,老催会让小组中的每个人依次讲解自己负责的内容,检查挺细的,所以最好不要上网 Download,我们这届就有两个小组被发现了。老催人虽然挺严格,但是也挺有趣的,...
这句话强调了每个人的特长,每个⼈需要寻找适合自己的工作和兴趣爱好。 知识点32: 代码的衡量 靠代码⾏数来衡量开发进程就好⽐⽤重量来衡量飞机制造的进度。这句话强调了代码的衡量,代码的质量和数量可以衡量开发...
书中的算法以英语加伪代码的形式给出,只要有一点程序设计经验的人都能读懂,并可以用任何计算机语言(如C/C++和Java等)方便地实现。在书中,作者将算法的讨论集中在一些比较现代的例子上,它们来自分子生物学(如...
书中的算法以英语加伪代码的形式给出,只要有一点程序设计经验的人都能读懂,并可以用任何计算机语言(如C/C++和Java等)方便地实现。在书中,作者将算法的讨论集中在一些比较现代的例子上,它们来自分子生物学(如...
<<page 1>> page begin==================== 目 目目 目 录 录录 ... 2000 年 6 月 22 日 不论对 Microsoft 还是对整个 IT 业界都将成为值得纪念的一天 这一天 微软公司正式推出了其下一代...