跳至主要内容

博文

目前显示的是 八月, 2007的博文

Anti-pattern of Constant Interface in Java

There is a famous book named "Effective Java", whose author is Joshua Bloch. In this book, there is a chapter about the "constant interface" anti-pattern. Besides, a new grammar named "static import" has been added into the language since Java 5.0. As explained in Sun's document , this feature is designed to encourage developers to use utility class rather than constant interface. Quote: In order to get around this, people sometimes put static members into an interface and inherit from that interface. This is a bad idea. In fact, it's such a bad idea that there's a name for it: the Constant Interface Antipattern (see Effective Java Item 17). The problem is that a class's use of the static members of another class is a mere implementation detail. When a class implements an interface, it becomes part of the class's public API. Implementation details should not leak into public APIs.

The Size of a Class/Object

最近在研究C++的object model,刚好看见几道关于sizeof的题目,做下来发现关于virtual关键字的class size并不是那么容易计算。还有编译器为了优化而产生的data padding也很tricky…… class  A { int  a; };             // sizeof(A) = 4 class  B : A { int  b; };         // sizeof(B) = 8 class  C : A { int  c; };         // sizeof(C) = 8 class  D : B, C { };             // sizeof(D) = 16 class  A { int  a; };             // sizeof(A) = 4 class  B : virtual  A { int  b; }; // sizeof(B) = 12 class  C : virtual  A { int  c; }; // sizeof(C) = 12 class  D : B, C { };             // sizeof(D) = 24 class  A { int  a; };       ...

Java & IPC

在Windows/Unix-like平台中,针对 IPC (Inter-process Communication)提供了许多机制,例如 Semaphore, Pipe, Shared memory等。在Java中,这些强大的能力都受到了限制,由于Java本身是提供Thread机制的,所以线程间是不大需要考虑使用IPC的,但是有时候Java应用程序可能需要同其它的native application进行通信,这种情况下就需要考虑IPC方式了。 Socket当然是可选方案之一,不过很多时候由于需要通信的数据并不多,采用socket就有点算weight solution了。RMI和Socket就不放在考察范围之内。 遗憾的是,根据google查到的资料,并没有发现非常简洁优雅的解决方案——最raw的就是用JNI了,遇到这种需要维护C、C++指针的情况,crash掉整个JVM的bug是必然多发的。查了一些资料,愈发无奈…… 难道真的要靠自己搞定JNI,或是购买成熟的commercial product来解决?? I am familiar and had used many times concurrent threads and "synchronized" in Java. The thing is, I want to share memory between 2 threads/processes , one in Java and one in "C". There is of course the JNI solution; I am currently using it; the thing is that when you call a JNI method from Java , and there is some problem in the "C" code (like a pointer which is not handled right and ,for example, is incremented so that it points to a non-valid address) it is sometimes difficult to trace. Of course you c...

Eclipse v3.4M1 Issues

自从将IDE由Eclipse 3.2.1升级到 3.4M1 之后,发现有不少问题: 1) Ctrl-Shift-G 搜索全文引用的时候,经常会出现错误提示——For input string: "filter_imports"。 上网搜索了一下, 解决方案 如下: 进入 $WorkSpace\.metadata\.plugins\org.eclipse.jdt.ui 删除IDE自动保存的一些档案: dialog_settings.xml OpenTypeHistory.xml QualifiedTypeNameHistory.xml 重启Eclipse即可。 2) Console的字符串问题。 我使用Ant脚本来编译项目,ant脚本执行时部分输出信息是中文。不知为何,在3.4M1中只要遇到中文,Console就不再输出任何字符,虽然编译可以继续进行。估计是因为Eclipse的new feature——Default console and file encoding,由于我保存Java source的编码格式都是UTF-8的,它默认也用UTF-8作为console的输出encoding。可能这里有bug,我试着将console encoding改为ISO8859-1,这时候中文都以问号显示,其它的文本都可以输出了。不过这毕竟只能解决一部分问题,目前还没有找到完美的解决方案,搞得我很郁闷……

Migrate Java IDE to Eclipse 3.4M1

周末将我的Java IDE做了一个升级——Eclipse 3.4M1。顺便下载了不少插件,主要都是和JavaEE相关的,包括: emf-sdo-xsd-SDK-2.3.0 GEF-SDK-3.4M1 wtp-S-3.0M1-200708232314 dtp-sdk_1.5_20070704 Subclipse-1.2.3 Subversive_1.1.0.RC6a HibernateTools-3.2.0b10 相较于使用Update-Site做自动下载更新,我更喜欢手动下载好必要的local site,再使用links目录来配置插件。网络上关于Eclipse下如何使用links目录的介绍很多,不过还是要媚俗地记录在blog上,以备将来需要的时候可以查到最顺手的帮助资料: 先将每个插件都解压缩到一个repository中,例如,我的Eclipse安装在D:\eclipse,我将所有的插件都放到D:\eclipse-plugins目录中。每个插件目录都应该以标准的目录树结构出现: eclipse | + [features] | + [plugins] | + <other necessary files> 然后,在eclipse的目录中建立一个links目录,里面新建一个link文件,文件中针对plugin所在的path进行配置,例如我的SVN插件配置为: path=D:/eclipse-plugins/Subversive_1.1.0.RC6a 注意,这里必须用“\\”或是“/”作为路径的分隔符号。 如果你愿意,可以在一个link文件里面使用多行“path=...”来指定所有的插件,或者也可以像我一样,使用多个link文件来指定插件。这属于个人喜好问题,每个人都有不同的偏好(preference)~ 好了,最后执行的时候可以在快捷方式里面加一个参数“-clean”,提醒Eclipse清除之前的缓存配置。如果这次启动成功,并且可以使用所有的新插件,那么就可以去除“-clean”参数了。 Eclipse 3.3之后,就多提供了一个eclipsec.exe文件,这个文件类似于在GUI程序后面挂了一个DOS窗口,显示log用的。Google了一下,貌似是为了解决windows上的一个小bug而提供的这个启动档。 使用Eclipse作合作...

C++编译器对于参数的初始化(Argument Initialization)

C++标准规定,将一个class object作为参数传递给一个function,等效于以下的初始化形式: X xx = arg; 这里,xx表示的是形式参数(formal argument)或是返回值(return value),arg表示的是实际参数(actual argument)。因此,假定有一个函数 void foo(X x0); 并有如下的调用: X xx; // ... foo( xx ); 这时候就需要x0这个局部实例以xx来memberwise initialized。 一种实现的策略就是引入一个临时的对象(temporary object),调用拷贝构造函数(copy constructor)来初始化这个对象,并将它传给function。例如,将以上的代码片段采用这种策略做转换,得到的伪代码如下: // Pseudo C++ code // compiler generated temporary X __temp0; // compiler invocation of copy constructor __temp0.X::X ( xx ); // rewrite function call to take temporary foo( __temp0 ); 但是,这个转换仅仅才完成了一半。为什么呢?因为foo()的声明中,临时对象会先以class X的copy constructor正确地初始化,再被bitwise copy到局部变量x0中!因此,foo()的声明也要做转换,不再使用一个对象实例作为参数,而使用对于class X的一个对象引用作为参数: void foo( X& x0 ); 如果class X声明了一个析构方法,那么在foo方法调用结束之后,临时对象的析构方法会被调用。 另一种实现是将在函数激活的时候,直接以拷贝构造在stack栈上作出实际参数。在函数调用返回之前,局部对象的析构函数会被调用。Borland C++编译器,就采用了这种策略,不过它也提供了一个编译器选项,可以实现第一种策略,这主要是为了兼容早期编译器的实现。

Hibernate Escape SQL Keywords

最近在使用Hibernate的时候遇到了一个诡异的bug,花了将近一个小时的debug时间,终于发现根源是table的column name刚好是SQL keyword (例如id, mode之类的名字)。Hibernate在自动生成的SQL语句中是不会自动加上标准的单引号(`)的,这导致我的数据库MySQL引擎在解释SQL语句的时候抛出了异常…… 经过一番google,最终采用了一个解决方案——在hbm.xml映射文件中为该字段指定使用quote,例如:      <property name="mode" column="`mod`"> 这样就等于强制使用了单引号的语法。 有意思的是,发现NHibernate的bug list中就有 关于是否要自动使用quote的相当激烈的讨论 。个人认为如果在hibernate configuration中可以通过某个property指定所有的SQL语句都要使用quote就很方便了。

关心一下C++0x

午休时间,逛了逛C++的『罗浮宫』,读了 『C++0x漫谈 系列之:Concept, Concept!』 。也看了G9写的一篇精彩的 『随堂笔记』 ,无意中看到Bjarne自称早在20年前就不用VI或是Emacs了…… 好久没用C++了,生疏得发怵…… 最近正在恶补 Inside C++ Object Model.