Thursday, December 28, 2006

台湾一震

这么一震,美国的网站变得好难访问,感觉生活大不方便了。
两个问题:

1 镜像在哪?平时就很少见国外知名站点有中国镜像,侧面反应了国人在这方面素质还有待提高。
2 美国人是不是也在想上中国网会这么慢?希望他们能这么想。

Wednesday, December 27, 2006

GmailFS? So nice!

在学校科技部的QQ群里看到的好东西,Gmail居然还能这么干!

GmailFs 使用Gmail的2G空间作为存储介质(汗呐),在本地的操作系统上虚拟一个硬盘(windows下)或通过FUSE(允许ssh和ftp将远程挂载点挂在本地的工具)提供一个远程的挂载(Linux下)。

Windows下的是安装一个GMail Drive shell extension,然后在我的电脑中即可看见虚拟的硬盘了。记得不用的时候要Logout,不然gmail网站就不能正常登陆了。
上传一个文件其实就是发一个mail(有其具体的格式),相应地删除mail就是删除文件。也因为如此,比较大(>10M)的文件就不能传了。
只是,在文件夹之间的剪切粘贴有点太粗糙了。

Windows下用GmailFS:
http://www.softpedia.com/progDownload/GMail-Drive-shell-extension-Download-15944.html
Linux下用GmailFS:
http://gentoo-wiki.com/HOWTO_GmailFS

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的,这样就能过了。希望他把悲痛都随着那顿麦当劳吃下肚子,再接再历!

Saturday, December 23, 2006

Flash ActionScript?

帮朋友写作业用到了Flash(我这人,哎,好说话呀)。

Flash的确强大,与Yahoo Widget不是一个级别的。
  • 动画制作的强大studio。
  • 提供表单应用程序所需的大部分组件。
  • 已经比较成熟的ActionScript脚本语言。
两天的功夫。。虽然之前从没用过,不过还是赶了出来。头一天跟着样例和感觉做、然后去网上查文档。 http://www.flashplayer.cn 有不少好东东。
制作的过程中,胖昕跑过来要我帮他做一个抽奖程序。。。汗,我又答应了,不过要求很简单,有个开始有个停就行了,也用flash一并做了。

作品还是八数码(因为太熟悉了,所以写得快),在此下载 http://www.tomore.com/dispdocnew.php?id=43057

西安,太多遗憾

西安,可能是Larva以团队的身份最后一次出征。实在有太多的遗憾了。

9点整比赛开始了,在翻阅了近半小时的题目时间里,始终都没能找到适合开始的突破口。

直到娄教主将B题通过的时候,ray也开始写B的代码。leen和leaderz正在讨论E题,从题意上来讲,这是最简单的一道。在不到20分钟的时间 里,ray敲完了代码(当时自我感觉还是可以的),一个简单的搜索架构,能过sample,但对最大的数据却明显TLE了,所以我们没能敢提交。
leen提议要记忆化搜索(这是leen的招牌)。在ray和leen争论了一翻之后,ray的心理开始有些混乱了。leaderz确定E是简单题之后,换leen做,又过了半个多小时,无果。

leaderz发觉了我们两状态的不佳,他提议ray做E,leen做B(从平时练习来讲,也确实应该这样分配,这个时候也许就剩下leaderz的头脑还是清醒的吧)。
接着又犯了个致命错误,ray选择是在leen的代码上改,而leen也选择在ray的代码上修改,由于双方代码风格的截然不同,跌跌撞撞地过了好久,ray勉强把E过了。(而ray已经是满头的汗)

leen和leaderz相互讨论了很长时间,在三个多小时的时候,把B给通过了。我瞄了leen两眼,通红的脸,看来他也承受了不小的压力。

有一段小插曲,leaderz在中间写了F的代码,用的是随机投点的方法。距离sample只有0.001的误差,但考虑到这题过的人实在很少,所以我们没有深入做这题。

环顾了一下四周,ray觉得J是通过的人比较多的,且J的规模可以暴力解,思考了一会后,ray心理默默算好了整段代码的结构,待leen下来的时候, ray立即赶上做J。要是平时的话,在对整段代码有了规划,对算法比较清晰的状况下,ray的代码速度和准确率还是满高的。但毕竟是比赛的时候,和E题一 样,ray犯了一些小错误,终于在距离比赛结束前半小时左右的时间,完成了代码且通过了sample。在测了几组数据后,提交,得到RT?怎么又是RT? 难道ray的人品又出了问题?查了10分钟,才发觉,是提交错题目了(真是有点神志不清了~)。修正后提交,得到了TLE??我的方法是先暴力求出所有解 丢在HashSet(用java)里,然后每个数据到Set里查一下。在本地,初始所有结果的时间1秒不到就OK了,查询都是常数负责度的。当时也顾不着 那么多了,leen和leaderz一起来帮忙把代码再优化,优化了不少东西后,还是不停TLE。最终只能停留在TLE。。。

结束了,就这样结束了,真的有些不甘。但还是结束了,leaderz是整场比赛状态最好的了,他对我们的调整以及他的F题(我们的另一只队在最后5分钟随机投点过了F)都是很准确的。

ray就开头清醒了一会,之后的状态一直比较混乱。leen在过了B题后开始恢复,但最后还是没能挽回J题。

比赛结束后,我们去找裁判组问他们J题是哪个地方导致TLE,见到了刘汝佳,还是很热心的,告诉我们J题时限是10秒(更不可能超了),而且他们的算法也是暴力。不过因为他们拔掉了网络,所以直到现在我还不知道为什么J题会TLE。。。也许只能说我的RP太差了。

Yahoo Widget?

yahoo widget是好东东(其实就是xml加上javascript,流行啊),yahoo widget比赛令我满不爽的 ( cn.widget.yahoo.com )。我的作品在第12-13页的RSS Cabint,成绩满惨的。总结一下教训,避免再做同样的傻事:
  1. 软件不合题意。题目要求创新,RSS管理软件没什么创新的。规则说是投票制,我的软件色彩颇暗,coder的风格,似乎不迎合大众的口味。
  2. 软件的市场定位不对。我不知道国人中有多少是在用RSS的,而我的更是使用了OPML来管理RSS,显然有些天方夜谭的味道。
  3. 宣传没做。关系网里没几个是适合来帮忙宣传这个的。尴尬啊,做人太死板了。要改要改。
虽然不适合比赛,但东西还是好东西。
http://www.tomore.com/dispdocnew.php?id=42885 有下载。

再给胖昕拉拉票,他的作品是八数码,满有希望拿奖的!祝好运!