标签 Java 下的文章

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第一部分就写到这。

Java基础

.jdk的安装
.环境变量的配置
.Eclipse IDE的安装和配置
.Java编码规范

1、jdk的安装

Java号称跨平台,实际上其本身就是个平台,我们要使用Java开发应用程序,我们首先就要安装Java平台,所谓Java平台就是指Java的运行环境(JRE)和相应的SDK。

这里我们选择j2sdk1.4.2来作为我们的Java平台,安装过程只需一路next即可。安装结束后,我们在命令行下输入“java -version”,若显示出:

java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

则说明我们的安装成功了!

2、环境变量的配置

很多初学者接触Java时都在环境变量的配置上花了不少时间和精力,这也是我把它单列出来加以说明的原因。

Java开发环境需要配置3个环境变量,分别是:

JAVA_HOME=your_j2sdk_installation_path
PATH=%JAVA_HOME%\bin;%PATH%
CLASSPATH=.;%JAVA_HOME%\jre\lib\rt.jar;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar

注意:CLASSPATH中包含一个“.”,这个“.”很重要千万不能遗漏,这个“.”的含义是允许在当前路径下搜索。

这些环境变量如何配置呢,在Windows下最简单的配置环境变量的方法是在“我的电脑”上单击右键点击“属性”,打“系统属性”对话框,选择“高级”标签栏,其中有“环境变量”按钮,点击之后打开“环境变量”对话框,在下面的“系统变量”中添加上述3个环境变量即可。

配置成功后,在命令行下输入:javac ,若显示:

Usage: javac
where possible options include:
-g                        Generate all debugging info
-g:none                   Generate no debugging info
-g:{lines,vars,source}    Generate only some debugging info
-nowarn                   Generate no warnings
-verbose                  Output messages about what the compiler is doing
-deprecation              Output source locations where deprecated APIs are used
-classpath          Specify where to find user class files
-sourcepath         Specify where to find input source files
-bootclasspath      Override location of bootstrap class files
-extdirs            Override location of installed extensions
-d             Specify where to place generated class files
-encoding       Specify character encoding used by source files
-source          Provide source compatibility with specified

release

-target          Generate class files for specific VM version
-help                     Print a synopsis of standard options

则说明环境变量配置成功。

3、Eclipse IDE的安装和配置

开发java程序,我们需要一个功能强大而且易用性好的ide,JBuilder太贵我们用不起,我们选择免费的eclipse。eclipse的安装很简单。只需将下载后的压缩包解压到某个目录下即可。相关的eclipse ide的配置我们都可以通过“Window”菜单下的“Open Perspective”和“Preferences”两个菜单项进行设置。

这里我们再来重点说说Java开发中常用的几个工具的配置和使用方法:

Ant — 待定
CVS — 见我的blog文章“CVS Primer
JUnit — 待定

参考资料:OReilly@2004 -  《Eclipse Cookbook》

4、Java编码规范

感觉Java在编码规范方面的分歧较小,比较容易在group中达成共识。
我们准备在Dominoo项目中使用“JBoss Code Style”,这里摘取其中的代码模板的例子:

/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package x;

// EXPLICIT IMPORTS
import a.b.C1; // GOOD
import a.b.C2;
import a.b.C3;

// DO NOT WRITE
import a.b.*;  // BAD

// DO NOT USE "TAB" TO INDENT CODE USE *3* SPACES FOR PORTABILITY AMONG EDITORS

/**
 * A description of this class.
 *
 * @see SomeRelatedClass.
 *
 * @version $Revision: 1.3 $
 * @author  xx
 * @author  yy
 */
public class X
    extends Y
    implements Z
{
    // Constants —————————————————–

    // Attributes —————————————————

    // Static ——————————————————–

    // Constructors ————————————————–

    // Public ——————————————————–

    public void startService() throws Exception
    { // Use the newline for the opening bracket so we can match top and bottom bracket visually

        Class cls = Class.forName(dataSourceClass);
        vendorSource = (XADataSource)cls.newInstance();

        // JUMP A LINE BETWEEN LOGICALLY DISCTINT **STEPS** AND ADD A LINE OF COMMENT TO IT
        cls = vendorSource.getClass();

        if(properties != null && properties.length() > 0)
        {

            try
            {
            }
            catch (IOException ioe)
            {
            }
            for (Iterator i = props.entrySet().iterator(); i.hasNext();)
            {

                // Get the name and value for the attributes
                Map.Entry entry = (Map.Entry) i.next();
                String attributeName = (String) entry.getKey();
                String attributeValue = (String) entry.getValue();

                // Print the debug message
                log.debug("Setting attribute '" + attributeName + "' to '" +
                        attributeValue + "'");

                // get the attribute
                Method setAttribute =
                    cls.getMethod("set" + attributeName,
                            new Class[] { String.class });

                // And set the value
                setAttribute.invoke(vendorSource,
                        new Object[] { attributeValue });
            }
        }

        // Test database
        vendorSource.getXAConnection().close();

        // Bind in JNDI
        bind(new InitialContext(), "java:/"+getPoolName(),
                new Reference(vendorSource.getClass().getName(),
                    getClass().getName(), null));
    }

    // Z implementation ———————————————-

    // Y overrides —————————————————

    // Package protected ———————————————

    // Protected —————————————————–

    // Private ——————————————————-

    // Inner classes ————————————————-
}

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! 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