2004年十一月月 发布的文章

Java 5.0新特性研究(一)

DreamHead计划使用"Java 5.0 Tiger"来开发我们的Dominoo,理由是:2-3年后"Tiger" will be mature。

我们对刚刚发布不久的"Tiger"了解的不多,晚上我们几个group member坐了下来,听DreamHead讲解"Tiger"的新特性。回到寝室自己做了些实验,有了些体会。

通过对"Tiger"的讨论和研究,得知Sun推出"Tiger"目的就是为了简化Java程序员的开发工作。在下面的详细解释及代码例子中你会深刻的体会到这一点。

1、Auto-boxing and auto-unboxing conversion

Problem:
─ Conversion between primitive types and wrapper objects (and vice-versa)
─ Needed when adding primitives to a collection

Java 5.0给我们的解决方案就是:Let the compiler(Javac) do it。事实上javac真的是这么做的么,耳听为虚,眼见为实,看代码吧!

我使用IntelliJ-Idea4.5.2写的代码(现在IntelliJ4.5已经可以支持jdk5.0的语法了,今早看了一下Eclipse的网站,Eclipse要到3.1才支持jdk5.0新加入的特性)[注]:在IntelliJ4.5中"File"—〉"Setting"—〉左下角"Classic View"最下面的"Language level for project"选择5.0即可。

/*
 * test auto-boxing and auto-unboxing
 */
//old 1.4 style
Integer intObj1 = new Integer(22);
int i = intObj1.intValue();
System.out.println(i);      //output: 22

//new 1.5 style
Integer intObj2 = 23;  //auto-boxing
int j = intObj2;      //auto-unboxing
System.out.println(j); //output: 23

//old 1.4 style
ArrayList al1 = new ArrayList();
al1.add(new Integer(24)); //or al1.add(Integer.valueOf(24))

//new 1.5 style
ArrayList al2 = new ArrayList();
al2.add(24);   // auto-boxing conversion   

编译为.class模块后,我们使用DJ Java Decompiler重新反编译得到以下代码(只写出对应上面代码的):
Integer intObj1 = new Integer(22);
int i = intObj1.intValue();
System.out.println(i);

Integer intObj2 = Integer.valueOf(23);
int j = intObj2.intValue();
System.out.println(j);

ArrayList al1 = new ArrayList();
al1.add(new Integer(24));

ArrayList al2 = new ArrayList();
al2.add(Integer.valueOf(24));

从上面代码中我们也可以看出,javac的确帮了我们的忙,它把繁重的活都揽去了,给我们留下了清闲,哦,忘说了,俺也是懒人^_^。

2、Generics in java
Problem: Collection element types
– Can not be checked at compile time
– Assignment must use cast
– Can cause runtime exception or errors(ClassCastException)

解决方案:
–Tell the compiler what type your collection is
– Compiler can fill in casts for you
还是那个原则,告诉编译器你的collection中需要什么类型,编译器为你完成一切(类型检查,转型等)。看代码:

ArrayList strArrayList = new ArrayList();
strArrayList.add("Hello");
System.out.println(strArrayList.iterator().next());  //output:Hello
System.out.println(strArrayList.getClass());        //output:class java.util.ArrayList

反编译后代码:
ArrayList strArrayList = new ArrayList();
strArrayList.add("Hello");
System.out.println((String)strArrayList.iterator().next());
System.out.println(strArrayList.getClass());

实际上包括转型等都是javac帮我们做了。 从上面的代码中我们还能看出问题:看紫色标记的代码,我们打印strArrayList的类型,该变量在声明的时候是ArrayList类型的,我们的头脑里会认为打印出的应该是"class java.util.ArrayList",可实际打印出的信息告诉我们collection中的元素的类型信息被丢弃了。也就是说ArrayList和ArrayList本不该是同一类型,不过我们看到的实际情况却是他们是同一类型。由于java中的generic只是在compiler一级得到支持,在jvm一级是不知道有generic这回事的,也许sun可能在不久的将来修正这一缺陷,别忘了java的强大的竞争对手C# 在2.0中已经在vm中加入对generic的支持。

这里要提一下DreamHead对java模板的理解,挺逗的,蛮有启发性。DreamHead用 "剧本  电影版本"来理解java generic:

射雕剧本  83版射雕 = new  射雕剧本();
射雕剧本  03版射雕 = new  射雕剧本();

Java generic与其他预言generic的简单比较,Java在compiler一级加入generic,导致的后果就是丢掉了类型信息,我们知道C++模板是不会丢掉类型信息的,但是会使可执行文件大小发生膨胀。C#2.0由于有VM的支持,所以既拥有类型信息,又不会使可执行文件的体积膨胀,但是总体来言,C++的generic最强大,也最成熟,当然和它支持的比较早也不无关系。

[注] 在《Adding Generics to the Java Programming Language:Participant Draft Specification》一文中关于上述问题有以下说明:

A parameterized class or interface declaration defines a set of types, one for each possible instantiation of the type parameter section. All parameterized types share the same class or interface at runtime.

For instance, the code:
Vector x = new Vector();
Vector y = new Vector();
return x.getClass() == y.getClass();

will yield true.

3、Enhanced for loop(foreach)
C#早已引入foreach这个关键字,C++也提供foreach算法(如果要弄懂这个需要学习的东西就比较多了^_^),java从jdk5.0开始引入这种高级for-loop机制,不过java的设计者还是很聪明的,java并没有引入新的关键字,因为要是这样做的话,需要进行的改动工作就太多了。Java利用原有的for关键字和一个":"就把这个完成了,不过java引入这一机制也只是方便程序员开发,这一机制也都是由javac来支持的,jvm一级并不知道foreach这一机制的存在。我们看看代码吧!

Vector strVec = new Vector();
strVec.add("Hello");
strVec.add("Tiger");
strVec.add("!");

//old 1.4 style – dynamic container
for (Iterator i = strVec.iterator(); i.hasNext(); ){
    System.out.println(i.next());
}

//new 1.5 style – dynamic container
for ( String str1 : strVec ){
    System.out.println(str1);
}

String [] strArray = {
    "Java 2",
    "Platform",
    "Standard",
    "Edition",
    "1.5"};
//old 1.4 style – static container
for(int i = 0 ; i < strArray.length ; ++i){
    System.out.println(strArray[i]);
}

//new 1.5 style – static container
for(String str2 : strArray){
    System.out.println(str2);
}
我们还是来看看反编译后的代码:
for(Iterator iterator1 = vector.iterator(); iterator1.hasNext(); System.out.println(s))
s = (String)iterator1.next();

String args2[] = args1;
int j = args2.length;
for(int k = 0; k < j; k++)
{
    String s1 = args2[k];
    System.out.println(s1);
}
注:上面对应颜色的代码相对应。

可以看出javac又在帮我们的忙。紫色部分我们看到仅用3行代码就搞定,而编译器得辛苦生成那么多代码。

4、Type safe Enumerations
Java不支持enum是java程序员抱怨较多的,这次sun终于在java5.0中加入了对enum的支持,不过还是如上面几个new features一样,只是在java compiler一级支持。

我们看看enum类型被javac转换成什么了?
//Color.java
public enum Color {
    RED,
    GREEN,
    BLUE
};

上面是一个很简单的enum声明,下面是反编译器输出的代码:
public final class Color extends Enum
{

    public static final Color[] values()
    {
        return (Color[])$VALUES.clone();
    }

    public static Color valueOf(String s)
    {
        Color acolor[] = $VALUES;
        int i = acolor.length;
        for(int j = 0; j < i; j++)
        {
            Color color = acolor[j];
            if(color.name().equals(s))
                return color;
        }

        throw new IllegalArgumentException(s);
    }

    private Color(String s, int i)
    {
        super(s, i);
    }

    public static final Color RED;
    public static final Color GREEN;
    public static final Color BLUE;
    private static final Color $VALUES[];

    static
    {
        RED = new Color("RED", 0);
        GREEN = new Color("GREEN", 1);
        BLUE = new Color("BLUE", 2);
        $VALUES = (new Color[] {
            RED, GREEN, BLUE
        });
    }
}

在sun公司的一份培训材料中写到:
Problem:
—-Variable needs to hold limited set of values e.g. card suit can only be spade, diamond, club, heart
Solution:
—New type of class declaration Enum type has public, self-typed members for each enum constant
—New keyword, enum Works with switch statement

下面我们根据上面的叙述来使用一下enum:
public class TestEnum{
    public enum Color {
            RED,
            GREEN,
            BLUE
        };
    public static void main(String[] args) {
        for (Color clr : Color.values() ){
            System.out.println(clr);
            /*output:
                RED
                GREEN
                BLUE
            */
        }        
    }
}

反编译后我们会看到如下的代码:
public static void main(String args[])
{
        Color acolor[] = Color.values();
        int i = acolor.length;
        for(int j = 0; j < i; j++)
        {
            Color color = acolor[j];
            System.out.println(color);
        }
}

通过这两个例子也可以看出enum不过是从Enum继承下来的类罢了,只是javac将相关的变换细节隐藏了。不过却给我们带来了极大的便利。

5、Varargs
Problem:
— To have a method that takes a variable number of parameters
— Can be done with an array, but not nice
— Look at java.text.MessageFormat

Solution: Let the compiler do it for you
— New syntax:
— public static String format (String fmt , Object… args);
— Java. gets printf !

例子:
public static void myPrintf(Object… args){
        for(Object obj : args){
            System.out.println(obj);
        }
}

public static void main(String[] args) {
    int i = 6;
    myPrintf("Hello" , "Tiger" , "Java 5.0");
    myPrintf("Harbin" ,"Beijing","Shenyang" ,"Changchun");
    myPrintf("The number is :" , i);
}

我们看一下反编译器输出的代码:

public static transient void myPrintf(Object aobj[])
{
    Object aobj1[] = aobj;
    int i = aobj1.length;
    for(int j = 0; j < i; j++)
    {
        Object obj = aobj1[j];
        System.out.println(obj);
    }
}

byte byte0 = 6;
myPrintf(new Object[] {
    "Hello", "Tiger", "Java 5.0"
});
myPrintf(new Object[] {
    "Harbin", "Beijing", "Shenyang", "Changchun"
});
myPrintf(new Object[] {
    "The number is :", Integer.valueOf(byte0)
});

从反编译的代码可以看出javac内部使用了数组来完成对变参数的支持。

6、Static imports
Problem:
—Having to fully qualify every static referenced from external classes

Solution: New import syntax
—import static TypeName.Identifier;
—import static Typename.*;
—Also works for static methods and enums e.g Math.sin(x) becomes sin(x)

上面是引用sun那个ppt中的一些东东,这个我就不想详细写了,今天较累,看看电影轻松一下吧!

Java5.0第一部分就写到这。

CVS Primer

CVS Repository?
 –> checkout(co)
 –> commit(ci)
 –> update(up)

Repository vs Modules?
   –Repository is the modules’s container
   –Module is often a project

Repository has four main parts :
   –main trunk(called "head" in Eclipse)
   –versions
   –branchs
   –date

CVS Version?
a) Version vs Revision?
The internal revision number(修订号) that CVS keeps for each file is unrelated to the version number of the software product of which the files are part.

The CVS revision numbers are invisible to your customers (unless you give them repository access); the only publicly visible number is the "3" in Version 3.

b) Where do versions come in?
Behind the scenes, a version control system's repository is a fairly clever beast. It doesn't just store the current copy of  each of the file in its care. Instead it stores every version that has ever been checked in. If you check out a file, edit it, version then check it back in, the repository will hold both the original version and the version that contains your changes.this system of storing revisions is remarkably powerful. Using it, the version control system can do things such as:

– retrieve a special revision of a file.
– check out all of the source code of a system as it appeared two months ago.
– tell you what changed in a particular file between versions 1.3 and 1.5.
– you can't use the individual file version numbers to keep track of things such as project releases

repeat: The individual revision numbers that CVS assigns to files should not be used as external version numbers. Instead, version control systems provide you with tags (or their equivalent).

CVS tag?
Tags to the rescue. Version control systems let you assign names to a group of files (or modules, or an entire project) at a particular point in time. If you assigned the tag .Pre-Release2. to this group of three files, you could subsequently check them out using that same tag. You'd get revision 1.11 of File1.java, 1.7 of File2.java, and 1.10 of File3.java.

usage:
    cvs tag release_1_0
    cvs update –r release_1_0  //get the project which version is release_1_0

注意:Tag 的使用并不局限于产品版本号,也不局限于整个模块,你可以随意的给任何一个文件加Tag,不过滥用Tag 就会使Tag 失去它应有的作用。

CVS Branch?

– Main trunk(主线,Eclipse称为Head)
– Branch(分支)

                        main trunk
                         tagged                          tagged                   tagged
————-〉release_1_0 ———–>release_2_0———–>release_3_0
                                      |
                                      |
                                      |  branch(使用分支)
                                    ln_release_1_0
                                    (tag和branch有相似性)

主线与分支相对应,在一个模块的初始是没有分支的,而在以后的开发过程中可以从主线上引出分支,上面图中分支ln_release_1_0就是基于主线的tag release_1_0的。在主线上引出一个分支来专门对付变更后的需求,而主线则保持原来的开发进程。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats