Showing posts with label java_tech. Show all posts
Showing posts with label java_tech. Show all posts

Thursday, June 14, 2007

Netbeans的UML工具

今天差点被Netbeans的UML工具感动得哭了出来。从Netbeans4.0开始知道除了Eclipse还有一个这么好的IDE。虽然当时Netbeans离JBuilder和Eclipse还有很大的距离,但我一直十分坚持使用Netbeans,因为我从Netbeans身上学到的不光是使用一个IDE,更多的是做程序开发的思想。

记得那次我是写一个八数码的搜索算法分析的程序,用到了GUI,那时我发现在Label修改文本的时候可以有一个叫Resource Bundle的东西,于是我知道了Java的国际化,当时感叹啊。。。 于是呼,以后写程序坚决不在程序内直接放字符串常量,要么在头上声明个final引用,要么就Resource Bundle一下。

Netbeans的GUI编辑器是让我感动最多的地方,它的易用性给我减轻了很多的负担,使编程变得愉快而轻松。除了GUI编辑器以外,当时他的Web开发包也是让我感动死掉~,整合的Tomcat使得调式如此简便,就在当时我一再向周围的人推荐Netbeans,希望大家能把目光从Eclipse身上转移一点给Netbeans,但最后都是以失败告终。

后来Netbeans的合作开发包,虽然当时一直是对Eclipse的ECF感兴趣,但Netbeans的合作开发实在太先进了。还有JavaHelp等等,从Netbeans身上学了好多好多东西。

今天,为了在毕业设计里加几个UML图,尝试性地下载了Netbeans的UML工具包。哇!哭了,一上来就有三个选项:平台无关模型、Java模型、对Java项目做逆向工程。思路非常清晰,Java模型是主打,其他的仍然可以用平台无关模型。而我选择的是Java逆向工程,完美!把我那个项目所有引用到的类都解析出来了。然后使用使用看看,哦~~~太感动了,功能so强大。前一阵子在唠叨Poseidon For UML又慢又龊,于是乎去网上找了N个UML 开发工具,要么是付费的,要么就是太龊,而Eclipse的UML工具,建模没问题,只是图形开发环境得用最新的Eclipse,更新最新的满麻烦的。

以下这张UML,是我通过选中几个模型之后,自动创建的类图,然后稍加修饰的结果:


总之,Netbeans的UML工具智能化程度已经很高了,可能还不如一些收费工具来的厉害。但作为一款免费的IDE,免费的UML工具,已经是相当相当专业的。Sun不愧是开源的老大啊。

Tuesday, May 22, 2007

Portlet with Ajax Tech (Jetspeed)

I was required to upload a large file via portlet with the process message displaying in the client side, and ajax would be the best choice. In order to ease the job, prototype was included first, so that the Ajax instance would do me a great help.

I've referred so many articles about the ajax application in portal, mostly work for WebSphere Portal rather than Jetspeed, tomcat-based portal. At last, I solved this problem, and as a conclude, I found that the problem could be broken down into three problem:

  1. Understanding the principle of the ajax application in portal, JSR-168 would be the most helpful reference. And here is a well-spread diagram to show this principle:

    As JSR168 said, portlet session could share the data with servlet session, so render the page via portlet and request the update from servlet, which makes the ajax realizable. Here is the article where the above diagram from.

  2. Share the data between portlet and servlet. Of cause, there are some applications do not need the servlet and portlet bundled, there would be unnecessary to consider this problem in such cases. But as to my problem, portlet and servlet should bundled together. As the articles I have read, I found it maybe was not a problem for WebSphere, but it's really a problem for tomcat based portal. The solution was so easy, just configure the server.xml like this, I mean to add emptySessionPath="true" attribute:

    <connector port="8080"
    maxthreads="150" minsparethreads="25" maxsparethreads="75"
    enablelookups="false" redirectport="8443" acceptcount="100"
    connectiontimeout="20000" disableuploadtimeout="true"
    emptysessionpath="true" />

    And read this article to know what the session identifier do to make such tricky problem.

  3. Last work is to write the codes and test it. So the last problem is about the coding.
    Most of these coding barriers could be taken easily via careful reading JSR168 Spec. Such as, portlet and servlet share data in APPLICATION_SCOPE, so using APPLICATION_SCOPE to store session. Url and javascript debuging would also cost a lot of time.


A good article about Ajax with WebSphere Portal:
http://www-128.ibm.com/developerworks/websphere/library/techarticles/0606_bishop/0606_bishop.html?ca=dgr-lnxw03AjaxPortals

So, it's really fun to work with portal, especially that using the ajax tech to make the portal more vivid. Hope this article help you solve your problem, thanks.

Tuesday, January 30, 2007

jlGui - Music Player

jlGui ( I guess that jlGui stands for jLayer's Gui ) 是一个java写的音乐播放软件,与当前主流媒体播放器当然还有差距,但其简便和小巧让我印象很深。

  1. 借助Java Web Start部署的应用,虽然很早就知道JWS的思想,也着实为这个idea感到钦佩,但真正的应用并不是很多还。而音乐播放器这一类的应用,用JWS部署是再好不过了!
    比如,我在blog上给个启动jlGui的服务,请确保安装了Java Web Start

    Select Skin (1/6): next
    Custom :
    Select Playlist (1/4): next
    Custom :
    Play Automaticly launch it!


  2. jlGui如其名,只是一个Gui,解码的任务由另一种服务提供(多好的功能分离啊,感动得流泪)。JavaSound集成在JRE中,其采用了SPI( Service Provider Interfaces )允许第三方以插件形式在其基本的JavaSound API下提供新的audio和MIDI资源。而jlGui有MP3SPI作MP3解码和VorbisSPI作OGG解码。

  3. jlGui皮肤采用winamp的皮肤,可以直接使用,但不保证一定好看(呵呵)。

  4. 正因为底层功能被分离了,jlGui本身很小很简单,能够方便地修改与调整。比如既然有JWS的版本,那么Applet自然也是可以的(Applet虽然曾经差点改变世界,但机会给Flash抢走了,所以现在的Applet并不是好选择)。如果开动想象力,应该还有很多种再开发的空间。

更多关于jlGui的信息在 http://www.javazoom.net/
同时,基于jLayer(jlGui的那个开发组的MP3SPI的底层项目)的一个eclipse播放器插件:
http://www.timbaumgartner.de/plugins.html

Tuesday, December 26, 2006

12月25日考SCJP

86%过了SCJP(310-055 English),只看了两天的书,但受益非浅,第一次知道Java还有这么多有趣的行为。

  • Declarations,Initialization and Scoping 83%
  • Flow Control 90%
  • API Contents 90%
  • Concurrency 75%
  • OO Concepts 90%
  • Collections/Generics 70%
  • Fundamentals 100%


1 Override:
一个完整的方法包括 修饰符 + 返回类型 + 方法标识 + 参数 + 异常声明 + 方法体。
构造方法默认返回类型是他自己,所以不用声明。但如下的代码依然是可以通过的:


public class Test{
public Test(){} //构造器
public int Test(){return 1;} //普通的方法
public Test Test(){return this;} //普通的方法
}

对于重写(Override),子类与父类的 方法标识、参数 必须相同。

  • 修饰符:子类无法缩小父类 方法的访问权限。
  • 返回类型:子类无法扩大父类的返回类型。
  • 可以不声明父类已经声明的异常、可以再添加新的异常声明、不能声明父类声明的异常的父类。
  • 方法体内可以随意使用super.method()和this.method()。对于构造器,super()和this()中最多有一个调用一次,且须在方法体第一行。
  • 方法调用类似与C++的virtual(陈胖子的指点),Super b=new Sub(); b.method()调用的是Sub的方法,而 b.var 是父类的字段。
  • 对象的实例化是依次从最顶层的父类开始构造。

关于构造,可以这样理解:

public class A{int a=0;Object a(){}}
public class B extends A{int a=1;String a(){}}

B b=new B();时堆栈情况如下:
A -> int a -> 0
Object a() -> B.a()的地址(因为重写只允许虚方法重写)
B -> int a -> 1
String a() -> B.a()的地址

有一道很狡猾的题目:

class SuperBase{
void p(SuperBase a){
System.out.println("super");
}
}

class Base extends SuperBase{
void p(Base a){
System.out.println("base");
}
}

class Derived extends Base{
static void p(Derived a){
System.out.println("derived");
}
}

public class Test{
public static void main(String[] ag){
SuperBase a1=new SuperBase();
SuperBase b1=new Base();
Base c1=new Derived();
a1.p(new Base());
b1.p(new Derived());
c1.p(new Derived());
}
}

输出结果是supersuperbase,首先要注意都不是重写而是重载。而b1.p结果是super是因为用SuperBase声明的b1只有一个方法 指针p(SuperBase),所以输出super。

2 equals:
5之后有了autoboxing/unboxing,所以要特别注意

Integer a=new Integer(0);
Integer b=new Integer(0);
int c=0;

a==b is false //未拆箱比较
a==c is true //拆箱后比较
c.equals(b) //编译错误
b.equals(c) //true

String的原理与boxing是不同的,理解带引号的字符串会存放在一个优化了的缓冲池里,而用String构造出来的则是实际的对象,其实和其他基 本类型相似,唯一的不同就是不是通过装箱和拆箱来实现两者之间的转换。所以:

String a="a";
String b=new String("a");
Stringc=new String("a");

a==b is false
a=="a" is true
b==c is false

equals是Object的方法,默认实现方法是比较对象地址,为了保持和hashCode()一致,最好重写。

StringBuilder a=new StringBuilder("abc");
StringBuilder b=new StringBuilder("abc");
a.equals(b) is false //StringBuilder没有重写equals,所以用默认的地址比较
如果 a.equals(b)是true,那么a.hashCode()==b.hashCode()一定是true。
如果a.hashCode()==b.hashCode()是true,a.equals(b)不一定是true!

关于boxing,switch语法中的case 是不能自动拆箱的:

switch(0){
case 0: //正确
case new Integer(1): //错误!
case 1+1: //正确
}

还有,System.out.printf("%f",123)是错误的,因为%f对应的是integer 123,不能隐式转型。

3 Generic:
5出来以后Generic一直是比较难搞懂的。

ArrayList<A> list=new ArrayList<B>(); //无论AB什么关系,都是不行的
List<A> list=new ArrayList<A>(); //ok
List<?> list=new ArrayList<A>(); //无论A是什么类型,都可以
List list=new ArrayList<A>(); //ok

List<?> list=new ArrayList<A>();
ArrayList<B> blist=(ArrayList<B>)list; //带warning,编译可以通过

泛型不能作为instanceof的操作值。
ArrayList<Integer> a=new ArrayList<Integer>();
a instanceof ArrayList //true
a instanceof ArrayList<?> //true
a instanceof ArrayList<Integer> //Compile Error
4 Serialize:
  • 继承Serializable的类在Deserialize时不调用构造方法,其父类(没继承Serializable)则一定要调用构造器。
  • 含未Serializable的字段,在串行化时会抛异常,不是Compile Error。


5 罕见的关键字:
保留的:goto,const
transient:串行化时不串行的变量
volatile:易变的变量,多线程时不会有拷贝
strictfp:保持在不同平台上的精度运算结果相同

6 Thread:
用于线程阻塞的方法有sleep()和wait()/notify()两种,其中wait()要放在synchronized段内,以保证监视器正在监控该线程。


synchronized (Thread.currentThread()){ // <-修改为其他实例就不抛异常
obj.wait(); //抛出异常IllegalMonitorStateException
}


7 函数参数:
无法同时声明 void a(String... b) 和 void a(String[] b)
可以同时声明 void a(String b,String... c) 和 void a(String... c),编译通过。但无法调用,因为会有二义性。


8 真题回忆:

感觉自己应该9*%过的(也许考完试的人都有这种心理吧,呵呵),回顾几道题:

-------------------------------------------------------------------------------



public class Main{
public static void main(String[] ars){
// code 1
try{
// code 2
}catch(Exception e){
// code 3
}finally{
System.out.println("a");
}
}
}

问以下五种情况中选三种,使一定会打印出a来:

A 当开始调用垃圾回收时
B 在code 1 抛异常
C 在code 2 抛异常
D 在code 3 抛异常
E code 1 处代码顺利执行

考试时我确定的是 CE,对于B和D我觉着是等价的(因为我一直牢记finally是无论如何都会执行到的)。

回来试了代码才知道,情况B抛出异常后就不会执行finally段!
-------------------------------------------------------------------------------


import java.util.*;
public class Main{
public static void main(String[] ars)throws Exception{
List<String> list=new ArrayList<String>();
list.add("b");
list.add("a");
list.add("c");
System.out.println(Collections.binarySearch(list,"a"));
}
}

问输出: A 0 B 1 C 2 D "a" E "b" F "c"

我选择的是D,因为确实没怎么用过binarySearch,结果是B。

-------------------------------------------------------------------------------
有一道生产者与消费者的问题:


boolean flag=false;
public synchronized void produce(){
flag=true;
___1____
}
public synchronized void comsume(){
while(!flag){
____2____
}
flag=___3___ ;
}

具体选项已经忘记了,因为实在不能确定这题的解,所以凭经验随便填的,我填的是 1 notifyAll() 2 wait() 3 false。
-------------------------------------------------------------------------------
有一道关于Scope的题目,题意不是很懂:



package test;
public class A{
public B instance=new B();
class B{
public int a;
}
}

问以下哪个关于a的access选项是正确的

A any class
B none class
C classes only in package test
D classes only in class A

我当时选择C,考虑到B是包级私有的,所以只能由test包下的类访问。结果~ 答案是A,测试得所有类都可以访问。
-------------------------------------------------------------------------------
还有一道命令行下access的问题,问某人忘记Chess.class放在那里了,运行以下命令后可启动Chess,那么Chess.class可能的位置是哪个?(unix下)

java -classpath test:/home/opt/*.jar game.Chess

n多乱七八糟的选项,我只记得两个,因为我在他们之间徘徊了许久:

A test/game/Chess.class
B /home/opt/chess.jar包内 (保证manifest正确)

我选择的是A,但试了一下都可以,郁闷。
-------------------------------------------------------------------------------

经沈(胖子?呵呵)提醒,又想起一道Thread的题目:



public class T extends Thread{
public void run(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
System.out.println("Interruptted");
}
System.out.println("done");
}
public static void main(String[] args)throws Exception{
System.out.println("start");
T th=new T();
th.start();
th.sleep(2000);
System.out.println("gogo");
th.interrupted();
System.out.println("finished");
}
}

问输出,我给的答案是 start->gogo->Interruptted->done->finished。运行了一下程序得:start->done->gogo->finished。仔细想想,原来th.sleep(2000)是个骗局,sleep的是main线程,上当了。

陈胖子(应胖昕要求这么叫他)很可惜,55% 就差了三题。不过他算是很厉害的了,因为两天之前他还是从没用过Java的人!应该让他考310-035的,这样就能过了。希望他把悲痛都随着那顿麦当劳吃下肚子,再接再历!