Mission Completed!

十分让人振奋,Inside Java 2 Virtual Machine看完了

几个月走之前还在想,这本书买了最后会不会读,能否读完,在今天下午的时候终于读完了!

后续工作包括:在本月底结束前把Linking Model等几个重要章节再复习1-2遍;抓紧时间结合本书和Dalvik已泄漏的资料和视频,研究Dalvik与JVM的差异之处。

最重要的是,下个月内一定要看完Dalvik的源代码。

Banzai!

奥巴马就职仪式观后小感

总体来说,比较让人失望。


1. 宣誓的时候没听到法官的话就开始说,结果大法官又重复了一遍,瓜到了。而且,据我仔细听,他重复的那句话并不完全按照大法官的话说的..... 难道说他其实法律上并没有完成宣誓仪式..... 开玩笑哈

2. 就职演说中完全没有以前他演讲的冲进,没有带给人的全新的感觉。而是重复一个概念,我们现在遇到问题,我们有能力解决。然后就是反复说这个。

3. 居然还在说战胜共产主义,法西斯主义,老火。

4. 最让人失望的是,冗长不带劲。

我估计很多美国人或者世界各地的人都希望能听到一次鼓舞人心的演说,可惜让他们失望了。

本人听到听到就开始开其他网页了,唯一一次转回切看NBC直播就是听到他说“那些嘲笑美国没有准备大干一场的勇气(吗还是实力,记不到了)的人,他们低估了我们的意志。”其他的真是太平庸了,还不得他当时当选后的那篇“是的,我能!”演说好。

我甚至感觉没有马英九的就职演说说得好。



还有点儿小花絮

奥巴马和他家庭后面坐的居然是个华人模样的人,不晓得和他们是啥子关系。反正只要一拍到奥巴马和他的女儿就可看到那个华人。这次就职仪式看过切,满眼都是华人哦,马友友也在副总统和总统宣誓中间被请上切演奏,看起来激情得很哦。希望美国有一年也能选出华人总统出来!

切尼,美国上届副总统才瓜,昨天搬家的时候绊了一跤,结果今天坐起轮椅来。

刚开始奥巴马要演说的时候,镜头切到了纽约一个广场看到很多人在看,演说完了开始美国一个诗人的朗诵后(很搞笑哈,美国也搞这些东西),镜头再切换到纽约,人都走得稀稀落落了.......

本人还是深深的为美国人民能够选出一位黑人总统的胆识和境界所折服。如果他真如罗斯福那样神勇,救美国经济于大难中,估计以后还会出现更多的黑人,华人,甚至西班牙裔的总统。但是如果他搞杂了,估计以后美国人还是相信白人吧..

本文已由本人发于“最成都”和“成都向上”论坛了。


....后记:“奥巴马重新宣誓弥补典礼缺憾

解析Java中神秘的String

很多Java的初学者对于String的使用细节不是太关心,但是我在这里想通过对Inside Java 2 Virtual Machine的学习和部分手动试验向大家展示String在所有Java Object中最特别的地方。

关键词: ==, equals, hashCode, intern, interned string reference list

首先最重要的是区分String中“==”, “equals()”以及“hashCode()”。

在Java中,很多时候两个相同Class的实例对象就算内容一样,通过equals对比后还是不一样,比如,

Car car1 = new Car();
Car car2 = new Car();
car1.equals(car2); // false

其根本原因还是两个对象在内存中是不同的对象,放在Java虚拟机的堆中不同的位置上。这样,你在对比两个对象的时候,当然就是不同的东西了。而equals有个必要条件,就是只要两个对象equals不一样的话,hashCode就必须不一样;反之,hashCode必须是一样的。因此我们可以知道当两个内容相同的实例对象equals不同的时候,他们的hashCode也必然是不同的。

String很特别,他的equals以及hashCode实现的方法是充分的利用了已有的对象,能够非常有效的节约空间。其实现方法就是两个不同的String对象,假如内容一样,那么equals是一样的,即他们的hashCode也是相同的。从已有的代码来看,其hashCode计算方法即是对每一个放在String内部数据结构所带的char数组中的字符进行计算和相加。比如,

String s1 = "hello";
其可能的hashCode计算方法是将h, e, l, l, o的每个ASCII码取出来然后乘以一个数字,最后相加。这样做的结果就是,只要你两个String字符串是一样的,最后hashCode就是一样的。而String的equals实现方法还是比较两个String对象中的字符串是否一样,一样的则返回为真。这也同样说明了两个String对象的字符串相同则就是同一个对象。

而“==”比较的是调用它的String引用所指向的String对象是否相同,这是什么意思呢?就是说,我用了==符号就是去比较位于==两边String引用所指向的,放在Java虚拟机的堆中的String对象是否是一样的。比如,

String s1 = new String("123");
String s2 = new String("234");

大家一看,必然知道这两者不仅equals下来是不一样的,==后肯定也是不一样的,毕竟这两个字符串内容都不一样,所以对应的String对象也肯定是不一样的。那么我们看这样呢?

String s1 = new String("123");
String s2 = new String("123");

首先可以确定的是s1.equals(s2);结果肯定是true,两者分别查看hashCode()后结果也是一样的,都是48690。但是如果你用s1 == s2进行比较的话,结果肯定是false!

为什么呢?

原因很简单,因为你使用了动态分配对象new,所以Java虚拟机在自己的堆上分别为两个String对象都分配了空间,因此你用==进行比较的时候,它比较的是两个String对象堆中实际的位置,结果当然就是不一样的了。而你用equals因为比较的是String实际的字符串是否相等,所以结果是相同的。

同样的,我们有,

String s1 = "123";
String s2 = new String("123");

这个==下来结果也是不同的,equals和hashCode是相同的。

神秘的“=”符号和new的区别。

可能大部分同学在使用String生成一个新的String对象的时候,都没有去想过使用动态分配对象new和直接在“=”符号后赋上一个字符串生成String对象的区别。实际上两者区别非常大。

使用=号后直接赋上字符串是告诉Java虚拟机,你在Java编译器将Java源代码编译成为bytecode的时候就让bytecode所在的class file知道String内容是什么,并且“潜规则”预订好了将String生成为一个对象的时间后续动作

上面两个黑体字符串表示什么特别的意思呢?
就是说,在这个String s1 = "123";所在的方法被调用的时候,Java虚拟机会对编译时候已经知道的“123”进行一些动作以便生成String对象。第一个动作就是resolution,第二个动作是检查interned string reference list中是否有改对象的引用了(即reference),第三个可能的动作是在interned string reference list中没有该String对象的引用的时候对该对象intern()一下,将其加入到list中。

问题是上面几句话是什么意思?

因为我们知道在编译完的时候Java虚拟机就已经知道了我们以后会用到123这个String对象,所以将其暂时放到class file中的constant pool表中。其实说白了,就是说因为我知道以后要用你,现在就暂时以文字的方式将你存储起来,以后以便将你实例化。这就像XML一样,你先可以将一些对象的内容存储在XML文件中,到时候遇到它要用它的时候再将其deserialize读出来,并放到构造器中实例化。Java虚拟机也是这样做的。好这样我们知道通过第一步resolution后,我们会将其实例化。

但实际上,Java虚拟机中为了节省空间,暂时并没有将其实例化,而是检查放在其method area中所维护的一个叫做interned string reference list中是否有该对象存在了。该list中保持的是指向Java虚拟机堆中的String对象的引用。所以你在进行检查的时候,实际上是调用了这个即将创建的String对象的equals和该list中所有引用比较。这样做的好处就是,因为equals会在发现两者字符串相同的时候返回true,所以你能保持同样的String在Java虚拟机堆中永远只有这一个对象存在

继续刚才的1,2,3。假如Java虚拟机发现了相同的String内容已经存在了,就返回该对象的引用给s1。所以这样s1指向了这个已存在的对象。而假如Java虚拟机发现没有同样的内容存在,那么就调用new String();创建该对象,并放在堆中。

第三步是在list中没有该对象的时候,将刚创建的String对象intern(),即将其加入到这个维护的list中。

new会做什么呢?new使得Java虚拟机在调用一个class file的时候无从得知该对象的存在,即在method具体走到该步的时候,才会在堆中分配该对象。仅此而已。这样做的一个缺点是,假如该堆中已经有了同样内容的String对象,即“123”已经存在,虚拟机还是会为你再次分配个一样的对象。这叫做浪费革命粮食。因此我们可以比较一下,

String s1 = "123";
String s2 = new String("123");
String s3 = new String("123");

s1在method调用到这句话的时候在堆中创建了一个String对象,内容是123,并将这个对象的引用添加到了interned string reference list中。
s2在堆中创建了一个同样为123的对象。s3也是在堆中创建了一个s3的对象。

s1 == s2; // false
s2 == s3; // false
s1.equals(s2); //true
s2.equals(s3); //true

intern()以及优化String。

我们在有了下面的语句后,

String s1 = "123";
String s2 = new String("123");
String s3 = new String("123");

分别用,

s2 = s2.intern();
s3 = s3.intern();

这样就会让Java虚拟机去寻interned string reference list中寻找是否有相同内容的String对象存在。结果是它会发现s1所指向的对象的内容和s2以及s3所指向的对象的内容是一样的。于是乎,s2以及s3会被赋予s1。这样s2和s3原来所指向的堆中的对象就是没有reference的对象了。迟早,他们会被垃圾回收器所回收掉空间。

上面两步完成后你再测试,

s1 == s2; // true
s2 == s3; // true

希望以上的文字对于大家进行Java或者Java虚拟机的学习有帮助。