快乐着飞舞着

---Nothing to do is doing nothing
随笔 - 93, 文章 - 5, 评论 - 56, 引用 - 0
数据加载中……

Hibernate 的 主键生成

Hibernate 的主键生成 中的 uuid.hex本来为什么不输出long 类型的 而要输出一个string 类型的呢? 总觉得一个varchar2 作为主键怪怪的 。。。

posted @ 2006-08-05 21:51 快乐着飞舞着 阅读(269) | 评论 (0)编辑 收藏

Hibernate 的错误

2006-07-23 23:14:53,796 [main] WARN  org.hibernate.impl.SessionFactoryObjectFactory - Could not bind factory to JNDI
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
 at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
 at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:247)
 at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:284)
 at javax.naming.InitialContext.getNameParser(InitialContext.java:439)
 at org.hibernate.util.NamingHelper.bind(NamingHelper.java:52)
 at org.hibernate.impl.SessionFactoryObjectFactory.addInstance(SessionFactoryObjectFactory.java:90)
 at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:291)
 at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1176)
 at reene.study.hibernate.test.TestMain.main(TestMain.java:19)


疑惑中

待解决....
在网上找到如下内容:
(3)报错:Could not bind factory to JNDI
此错误是配置文件的问题,如果hibernate配置文件有session_factory_name这个变量,<session-factory name="foo"> 会试图将一个SessionFactory实例以foo为名bind到jndi上,而有的application container不支持jndi绑定。把这个变量去掉即可。

解决问题

把引用代码也要修改:
大致改成这样:

1 SessionFactory sf = new Configuration().configure()
2                     .buildSessionFactory();
3             Session session = sf.openSession();
4             Transaction tx = session.beginTransaction();



posted @ 2006-07-23 23:21 快乐着飞舞着 阅读(2463) | 评论 (1)编辑 收藏

Failed to setup clustering 错误的解决

使用jboss 开发时碰到

[JBossCacheService][main] jboss.cache:service=TomcatClusteringCache service to Tomcat clustering not   found
[JBossCacheManager][main] JBossCacheService to Tomcat clustering not found
[TomcatDeployer][main] Failed to setup clustering, clustering disabled
错误时 网上有一种解决方法是:
http://wiki.jboss.org/wiki/Wiki.jsp?page=ClusteringFAQ
上的官方解决办法。

但是如果你的应用根本用不到cluster 用不到 distribution 可以用如下方法更改:
检查 你的应用
/WEB-INF/web.xml
中是不是有

1 <web-app>
2 .
3    <distributable/>
4 ..
5 </web-app>
6 


改为

1 < web-app >
2 .
3 <!--
4    <distributable/>
5 -->
6 ..
7 </ web-app >
8


就可以了



posted @ 2006-07-23 16:30 快乐着飞舞着 阅读(1101) | 评论 (0)编辑 收藏

Java 5.0 新特性 [转载]


转载自:http://www.javaresearch.org/article/showarticle.jsp?column=544&thread=25611

J2SE 5.0专题 之 语言特性
yark 转贴  (参与分:29628,专家分:2325)   发表:2005-04-14 17:43   版本:1.0   阅读:2100

J2SE 5.0专题 之 语言特性
                         本文作者: 高宇翔(大胃)

 

1.1.        背景
J2SE(TM) 5.0正式发布至今已超过3个月的时间了,就在前不久,大概是在两周之前,Sun又发布了更新过的JDK 5.0 Update 1,改掉了一些第一个版本中出现的bug。

 

由于Java社群等待这一从1.4向5.0版本升级已经有相当长的一段时间,大家都很关心5.0中有哪些值得关注的变化,于是blog的相关信息满天飞,我也兴冲冲地在自己的blog中添上了一系列的文章。无奈这些blog文章,包括我自己的在内,通常都是泛泛而谈,因此CSDN第二期Java电子杂志的编辑们计划做一个专题对这一话题与相关人士进行一番深入的探讨。

 

作为这期电子刊物的一部分,编辑们也邀请我更系统的探讨一下:J2SE(TM) 5.0中新引入的语言特性究竟在实际中有哪些用途,以及为什么要引入这些新特性。对此我深感荣幸。我本人很乐意将我的一些也许算得上经验的Java经验跟大家分享,希望这一篇小文能对大家了解J2SE(TM) 5.0有一定帮助。

1.2.        准备工作
首先,为了了解J2SE(TM) 5.0的新的语言特性,你需要下载新版的JDK,在这里可以找到下载链接:http://java.sun.com/j2se/1.5.0/download.jsp。当然,如果你已经有过手动配置Java环境的经历,我也建议你使用一个支持J2SE(TM) 5.0的IDE,推荐Eclipse SDK 3.1 M4,或者NetBeans IDE 4.0。两个都是开源免费的,且很容易找到(Eclipse不用说了,NetBeans IDE 4.0有与JDK 5.0 Update 1的捆绑版)。

 

说点题外话,Java的版本号自从1.2开始,似乎就多少显得有点蹩脚。从1.2版本开始,Java (J2SE)被称作Java 2,而不是Java 1.2,现在则显得更加离奇:Java(TM) 2 Platform Standard Edition 5.0或者J2SE(TM) 5.0,而内部的版本号还是1.5.0。那么到底是1、2、还是5呢?来看看Sun官方网站是怎么说的:

 

从Java诞生至今已有9年时间,而从第二代Java平台J2SE算起也有5个年头了。在这样的背景下,将下一个版本的版本号从1.5改为5.0可以更好的反映出新版J2SE的成熟度、稳定性、可伸缩性和安全性。

 

好吧,现在我们将面对如下一些名称,而它们指的基本上是同一个东西:

l         Tiger

l         Java(TM) 2 Platform Standard Edition 5.0

l         J2SE(TM) 5.0

l         Java version 1.5.0

l         …

在本文中,为了方便起见,我将统一使用J2SE(TM) 5.0这个名称。

 

如果你对Java各个版本的代号感兴趣,就像这里的"Tiger",可以参考如下网址:http://java.sun.com/j2se/codenames.html。透露一点:Java下一个版本(6.0)的代号是"Mustang"野马,再下一个版本(7.0)的代号是"Dolphin"海豚。

1.3.        概述
J2SE(TM) 5.0引入了很多激进的语言元素变化,这些变化或多或少减轻了我们开发人员的一些编码负担,其中的大部分也必然会被应用到即将发布的J2EE(TM) 5.0中。主要的新特性包括:

l         泛型

l         增强的for循环

l         自动装箱和自动拆箱

l         类型安全的枚举

l         可变长度参数

l         静态引入

l         元数据(注解)

l         C风格的格式化输出

 

这当中,泛型、枚举和注解可能会占用较大的篇幅,而其余的因为用法直截了当,抑或相对简单,我就稍作介绍,剩下的留给读者去思考、去探索了。

1.4.        泛型
泛型这个题目相当大,大到完全可以就这个话题写一本书。有关Java是否需要泛型和如何实现泛型的讨论也早就在Java社群广为流传。终于,我们在J2SE(TM) 5.0中看到了它。也许目前Java对泛型的支持还算不上足够理想,但这一特性的添加也经足以让我们欣喜一阵了。

 

在接下来的介绍中,我们会了解到:Java的泛型虽然跟C++的泛型看上去十分相似,但其实有着相当大的区别,有些细节的东西也相当复杂(至少很多地方会跟我们的直觉背道而驰)。可以这样说,泛型的引入在很大程度上增加了Java语言的复杂度,对初学者尤其是个挑战。下面我们将一点一点往里挖。

 

首先我们来看一个简单的使用泛型类的例子:

ArrayList<Integer> aList = new ArrayList<Integer>();

    aList.add(new Integer(1));

    // ...

    Integer myInteger = aList.get(0);

我们可以看到,在这个简单的例子中,我们在定义aList的时候指明了它是一个直接受Integer类型的ArrayList,当我们调用aList.get(0)时,我们已经不再需要先显式的将结果转换成Integer,然后再赋值给myInteger了。而这一步在早先的Java版本中是必须的。也许你在想,在使用Collection时节约一些类型转换就是Java泛型的全部吗?远不止。单就这个例子而言,泛型至少还有一个更大的好处,那就是使用了泛型的容器类变得更加健壮:早先,Collection接口的get()和Iterator接口的next()方法都只能返回Object类型的结果,我们可以把这个结果强制转换成任何Object的子类,而不会有任何编译期的错误,但这显然很可能带来严重的运行期错误,因为在代码中确定从某个Collection中取出的是什么类型的对象完全是调用者自己说了算,而调用者也许并不清楚放进Collection的对象具体是什么类的;就算知道放进去的对象“应该”是什么类,也不能保证放到Collection的对象就一定是那个类的实例。现在有了泛型,只要我们定义的时候指明该Collection接受哪种类型的对象,编译器可以帮我们避免类似的问题溜到产品中。我们在实际工作中其实已经看到了太多的ClassCastException,不是吗?

 

泛型的使用从这个例子看也是相当易懂。我们在定义ArrayList时,通过类名后面的<>括号中的值指定这个ArrayList接受的对象类型。在编译的时候,这个ArrayList会被处理成只接受该类或其子类的对象,于是任何试图将其他类型的对象添加进来的语句都会被编译器拒绝。

 

那么泛型是怎样定义的呢?看看下面这一段示例代码:(其中用E代替在实际中将会使用的类名,当然你也可以使用别的名称,习惯上在这里使用大写的E,表示Collection的元素。)

public class TestGenerics<E> {

        Collection<E> col;

        public void doSth(E elem) {

            col.add(elem);

            // ...

        }

}

在泛型的使用中,有一个很容易有的误解,那就是既然Integer是从Object派生出来的,那么ArrayList<Integer>当然就是ArrayList<Object>的子类。真的是这样吗?我们仔细想一想就会发现这样做可能会带来的问题:如果我们可以把ArrayList<Integer>向上转型为ArrayList<Object>,那么在往这个转了型以后的ArrayList中添加对象的时候,我们岂不是可以添加任何类型的对象(因为Object是所有对象的公共父类)?这显然让我们的ArrayList<Integer>失去了原本的目的。于是Java编译器禁止我们这样做。那既然是这样,ArrayList<Integer>以及ArrayList<String>、ArrayList<Double>等等有没有公共的父类呢?有,那就是ArrayList<?>。?在这里叫做通配符。我们为了缩小通配符所指代的范围,通常也需要这样写:ArrayList<? extends SomeClass>,这样写的含义是定义这样一个类ArrayList,比方说SomeClass有SomeExtendedClass1和SomeExtendedClass2这两个子类,那么ArrayList<? extends SomeClass>就是如下几个类的父类:ArrayList<SomeClass>、ArrayList<SomeExtendedClass1>和ArrayList<SomeExtendedClass2>。

 

接下来我们更进一步:既然ArrayList<? extends SomeClass>是一个通配的公用父类,那么我们可不可以往声明为ArrayList<? extends SomeClass>的ArrayList实例中添加一个SomeExtendedClass1的对象呢?答案是不能。甚至你不能添加任何对象。为什么?因为ArrayList<? extends SomeClass>实际上代表了所有ArrayList<SomeClass>、ArrayList<SomeExtendedClass1>和ArrayList<SomeExtendedClass2>三种ArrayList,甚至包括未知的接受SomeClass其他子类对象的ArrayList。我们拿到一个定义为ArrayList<? extends SomeClass>的ArrayList的时候,我们并不能确定这个ArrayList具体是使用哪个类作为参数定义的,因此编译器也无法让这段代码编译通过。举例来讲,如果我们想往这个ArrayList中放一个SomeExtendedClass2的对象,我们如何保证它实际上不是其他的如ArrayList<SomeExtendedClass1>,而就是这个ArrayList<SomeExtendedClass2>呢?(还记得吗?ArrayList<Integer>并非ArrayList<Object>的子类。)怎么办?我们需要使用泛型方法。泛型方法的定义类似下面的例子:

public static <T extends SomeClass> void add (Collection<T> c, T elem) {

        c.add(elem);

}

其中T代表了我们这个方法期待的那个最终的具体的类,相关的声明必须放在方法签名中紧靠返回类型的位置之前。在本例中,它可以是SomeClass或者SomeClass的任何子类,其说明<T entends SomeClass>放在void关键字之前(只能放在这里)。这样我们就可以让编译器确信当我们试图添加一个元素到泛型的ArrayList实例中时,可以保证类型安全。

 

Java泛型的最大特点在于它是在语言级别实现的,区别于C# 2.0中的CLR级别。这样的做法使得JRE可以不必做大的调整,缺点是无法支持一些运行时的类型甄别。一旦编译,它就被写死了,能提供的动态能力相当弱。

 

个人认为泛型是这次J2SE(TM) 5.0中引入的最重要的语言元素,给Java语言带来的影响也是最大。举个例子来讲,我们可以看到,几乎所有的Collections API都被更新成支持泛型的版本。这样做带来的好处是显而易见的,那就是减少代码重复(不需要提供多个版本的某一个类或者接口以支持不同类的对象)以及增强代码的健壮性(编译期的类型安全检查)。不过如何才能真正利用好这个特性,尤其是如何实现自己的泛型接口或类供他人使用,就并非那么显而易见了。让我们一起在使用中慢慢积累。

1.5.        增强的for循环
你是否已经厌倦了每次写for循环时都要写上那些机械的代码,尤其当你需要遍历数组或者Collection,如:(假设在Collection中储存的对象是String类型的)

public void showAll (Collection c) {

    for (Iterator iter = c.iterator(); iter.hasNext(); ) {

        System.out.println((String) iter.next());

    }

}

 

public void showAll (String[] sa) {

    for (int i = 0; i < sa.length; i++) {

        System.out.println(sa[i]);

    }

}

这样的代码不仅显得臃肿,而且容易出错,我想我们大家在刚开始接触编程时,尤其是C/C++和Java,可能多少都犯过以下类似错误的一种或几种:把for语句的三个表达式顺序弄错;第二个表达式逻辑判断不正确(漏掉一些、多出一些、甚至死循环);忘记移动游标;在循环体内不小心改变了游标的位置等等。为什么不能让编译器帮我们处理这些细节呢?在5.0中,我们可以这样写:

public void showAll (Collection c) {

    for (Object obj : c) {

        System.out.println((String) obj);

    }

}

 

public void showAll (String[] sa) {

    for (String str : sa) {

        System.out.println(str);

    }

}

这样的代码显得更加清晰和简洁,不是吗?具体的语法很简单:使用":"分隔开,前面的部分写明从数组或Collection中将要取出的类型,以及使用的临时变量的名字,后面的部分写上数组或者Collection的引用。加上泛型,我们甚至可以把第一个方法变得更加漂亮:

public void showAll (Collection<String> cs) {

    for (String str : cs) {

        System.out.println(str);

    }

}

有没有发现:当你需要将Collection<String>替换成String[],你所需要做的仅仅是简单的把参数类型"Collection<String>"替换成"String[]",反过来也是一样,你不完全需要改其他的东西。这在J2SE(TM) 5.0之前是无法想象的。

 

对于这个看上去相当方便的新语言元素,当你需要在循环体中访问游标的时候,会显得很别扭:比方说,当我们处理一个链表,需要更新其中某一个元素,或者删除某个元素等等。这个时候,你无法在循环体内获得你需要的游标信息,于是需要回退到原先的做法。不过,有了泛型和增强的for循环,我们在大多数情况下已经不用去操心那些烦人的for循环的表达式和嵌套了。毕竟,我们大部分时间都不会需要去了解游标的具体位置,我们只需要遍历数组或Collection,对吧?

1.6.        自动装箱/自动拆箱
所谓装箱,就是把值类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int型包装成Integer类的对象,或者把double包装成Double,等等。所谓拆箱,就是跟装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为值类型的数据。

 

在J2SE(TM) 5.0发布之前,我们只能手工的处理装箱和拆箱。也许你会问,为什么需要装箱和拆箱?比方说当我们试图将一个值类型的数据添加到一个Collection中时,就需要先把它装箱,因为Collection的add()方法只接受对象;而当我们需要在稍后将这条数据取出来,而又希望使用它对应的值类型进行操作时,我们又需要将它拆箱成值类型的版本。现在,编译器可以帮我们自动地完成这些必要的步骤。下面的代码我提供两个版本的装箱和拆箱,一个版本使用手工的方式,另一个版本则把这些显而易见的代码交给编译器去完成:

public static void manualBoxingUnboxing(int i) {

    ArrayList<Integer> aList = new ArrayList<Integer>();

    aList.add(0, new Integer(i));

    int a = aList.get(0).intValue();

    System.out.println("The value of i is " + a);

}

 

public static void autoBoxingUnboxing(int i) {

    ArrayList<Integer> aList = new ArrayList<Integer>();

    aList.add(0, i);

    int a = aList.get(0);

    System.out.println("The value of i is " + a);

}

看到了吧,在J2SE(TM) 5.0中,我们不再需要显式的去将一个值类型的数据转换成相应的对象,从而把它作为对象传给其他方法,也不必手工的将那个代表一个数值的对象拆箱为相应的值类型数据,只要你提供的信息足够让编译器确信这些装箱/拆箱后的类型在使用时是合法的:比方讲,如果在上面的代码中,如果我们使用的不是ArrayList<Integer>而是ArrayList或者其他不兼容的版本如ArrayList<java.util.Date>,会有编译错误。

 

当然,你需要足够重视的是:一方面,对于值类型和引用类型,在资源的占用上有相当大的区别;另一方面,装箱和拆箱会带来额外的开销。在使用这一方便特性的同时,请不要忘记了背后隐藏的这些也许会影响性能的因素。

1.7.        类型安全的枚举
在介绍J2SE(TM) 5.0中引入的类型安全枚举的用法之前,我想先简单介绍一下这一话题的背景。

 

我们知道,在C中,我们可以定义枚举类型来使用别名代替一个集合中的不同元素,通常是用于描述那些可以归为一类,而又具备有限数量的类别或者概念,如月份、颜色、扑克牌、太阳系的行星、五大洲、四大洋、季节、学科、四则运算符,等等。它们通常看上去是这个样子:

typedef enum {SPRING, SUMMER, AUTUMN, WINTER} season;

实质上,这些别名被处理成int常量,比如0代表SPRING,1代表SUMMER,以此类推。因为这些别名最终就是int,于是你可以对它们进行四则运算,这就造成了语意上的不明确。

 

Java一开始并没有考虑引入枚举的概念,也许是出于保持Java语言简洁的考虑,但是使用Java的广大开发者对于枚举的需求并没有因为Java本身没有提供而消失,于是出现了一些常见的适用于Java的枚举设计模式,如int enum和typesafe enum,还有不少开源的枚举API和不开源的内部实现。

 

我大致说一下int enum模式和typesafe enum模式。所谓int enum模式就是模仿C中对enum的实现,如:

public class Season {

    public static final int SPRING = 0;

    public static final int SUMMER = 1;

    public static final int AUTUMN = 2;

    public static final int WINTER = 3;

}

这种模式跟C中的枚举没有太多本质上的区别,C枚举的局限它基本上也有。而typesafe enum模式则要显得健壮得多:

public class Season {

    private final String name;

    private Season(String name) {

        this.name = name;

    }

    public String toString() {

        return name;

    }

    public static final Season SPRING = new Season("spring");

    public static final Season SUMMER = new Season("summer");

    public static final Season AUTUMN = new Season("autumn");

    public static final Season WINTER = new Season("winter");

}

后一种实现首先通过私有的构造方法阻止了对该类的继承和显式实例化,因而我们只可能取得定义好的四种Season类别,并且提供了方便的toString()方法获取有意义的说明,而且由于这是一个完全意义上的类,所以我们可以很方便的加入自己的方法和逻辑来自定义我们的枚举类。

 

最终,Java决定拥抱枚举,在J2SE(TM) 5.0中,我们看到了这一变化,它所采用的设计思路基本上就是上面提到的typesafe enum模式。它的语法很简单,用一个实际的例子来说,要定义一个枚举,我们可以这样写:

public enum Language {CHINESE, ENGLISH, FRENCH, HUNGARIAN}

接下来我们就可以通过Language.ENGLISH来使用了。呃…这个例子是不是有点太小儿科了,我们来看一个复杂点的例子。使用Java的类型安全枚举,我们可以为所有枚举元素定义公用的接口,然后具体到每个元素本身,可以针对这些接口实现一些特定的行为。这对于那些可以归为一类,又希望能通过统一的接口访问的不同操作,将会相当方便。通常,为了实现类似的功能,我们需要自己来维护一套继承关系或者类似的枚举模式。这里借用Java官方网站上的一个例子:

public enum Operation {

    PLUS   { double eval(double x, double y) { return x + y; } },

    MINUS  { double eval(double x, double y) { return x - y; } },

    TIMES  { double eval(double x, double y) { return x * y; } },

    DIVIDE { double eval(double x, double y) { return x / y; } };

 

    // Do arithmetic op represented by this constant

    abstract double eval(double x, double y);

}

在这个枚举中,我们定义了四个元素,分别对应加减乘除四则运算,对于每一种运算,我们都可以调用eval()方法,而具体的方法实现各异。我们可以通过下面的代码来试验上面这个枚举类:

public static void main(String args[]) {

    double x = Double.parseDouble(args[0]);

    double y = Double.parseDouble(args[1]);

    for (Operation op : Operation.values()) {

        System.out.println(x + " " + op + " " + y + " = " + op.eval(x, y));

    }

}

怎么样,使用枚举,我们是不是能够很方便的实现一些有趣的功能?其实说穿了,Java的类型安全枚举就是包含了有限数量的已生成好的自身实例的一种类,这些现成的实例可以通过类的静态字段来获取。

1.8.        可变长度参数
顾名思义,可变长度参数就是指在方法的参数体中,只要定义恰当,我们可以使用任意数量的参数,类似于使用数组。在J2SE(TM) 5.0中,一个新的语法被引入,就是在参数类型名称后面加上"...",表示该方法可以接受多个该类型的参数。需要说明的是可变长度参数必须放在参数列表的最后,且一个方法只能包含一个这样的参数。在方法体内部,这样的参数被当作数组处理,看上去代码应该类似这个样子:

public String testVararg(String... args) {

    StringBuilder sb = new StringBuilder();

    for (String str : args) {

        sb.append(str);

    }

    return sb.toString();

}

这样的方法签名跟你写成testVararg(String[] args)的区别在于:在调用时,你不再需要传入一个包装好的String数组,你只需要简单的写一连串String参数,以逗号隔开即可,就如同这个方法正好有一个重载的版本是接受那么多个String参数一样。

1.9.        静态引入
所谓静态引入就是指除了引入类之外,我们现在又多了一种选择:引入某个类的静态字段。如:

import static java.lang.Math.PI;

或者

import static java.lang.Math.*;

这样我们在接下来的代码中,当我们需要使用某个被引入的静态字段时,就不用再写上前面的类名了。当然,出现名字冲突时,跟原来的类引入一样,还是需要前缀以示区分。我个人认为这个新语言元素意义不大。当引入太多静态字段后,代码会变得难以阅读和维护。由于静态字段的名字通常不如类名那么具有描述性,我认为原先在静态字段前写上类名才是更好的选择。不过,毕竟每个人的喜好和需求不同,如果你觉得它对你有用,既然提供了,那么就用咯。

1.10.  元数据(注解)
注解是J2SE(TM) 5.0引入的重要语言元素,它所对应的JSR是JSR 175,我们先来看看JSR 175的文档对注解的说明:

 

注解不会直接影响程序的语义,而开发和部署工具则可以读取这些注解信息,并作相应处理,如生成额外的Java源代码、XML文档、或者其他将与包含注解的程序一起使用的物件。

 

在之前的J2SE版本中,我们已经使用到了一部分早期的注解元素,如@deprecated等。这些元素通常被用于产生HTML的Javadoc。在J2SE(TM) 5.0中,注解被正式引入,且推到了Java历史上前所未有的高度。

 

现在,注解不仅仅被用来产生Javadoc,更重要的,注解使得代码的编译期检查更加有效和方便,同时也增强了代码的描述能力。有一些注解是随着J2SE(TM) 5.0一起发布的,我们可以直接使用。除此之外,我们也可以很方便的实现自定义的注解。在此基础上,很多以前我们只能靠反射机制来完成的功能也变得更加容易实现。

 

我们来看现成的有哪些有用的注解:

 

首先是@Override,这个注解被使用在方法上,表明这个方法是从其父类继承下来的,这样的写法可以很方便的避免我们在重写继承下来的方法时,不至于不小心写错了方法签名,且悄悄的溜过了编译器,造成隐蔽性相当高的bug。

 

其次是@Deprecated,表明该项(类、字段、方法)不再被推荐使用。

 

还有一个@SuppressWarnings,表明该项(类、字段、方法)所涵盖的范围不需要显示所有的警告信息。这个注解需要提供参数,如unchecked等等。

 

下面我通过一个例子向大家说明这些现成的注解的用法:

public class Main {

    @Deprecated

    public String str;

    public static void main(String[] args) {

            new SubMain().doSomething();

    }

    public void doSomething() {

            System.out.println("Done.");

    }

}

 

class SubMain extends Main {

    @Override

    @SuppressWarnings("unchecked", "warning")

    public void doSomething() {

          java.util.ArrayList aList = new java.util.ArrayList();

          aList.add(new Integer(0));

            System.out.println("Done by SubMain.");

    }

}

当然,我们也完全可以写自己的注解。注解定义的语法是@interface关键字。J2SE(TM) 5.0支持三种形式的注解:不带参数的标记注解、带一个参数的注解和带多个参数的完整注解。下面分别举例说明:

 

标记注解,类似@Deprecated,如:

@interface SomeEmptyAnnotation {}

单个参数的注解,如:

@interface MySingleElementAnnotation {

    String value();

}

以及多个参数的注解,如:

@interface MyAnnotationForMethods {

    int index();

    String info();

    String developer() default "Sean GAO";

}

 

我们可以看到,注解的定义跟interface的定义相当类似,我们还可以指定默认值。对于这些注解,我们也可以为其添加注解,所谓“注解的注解”。比方讲,我们通常会使用@Target指定注解的作用对象,以及用@Retention指定注解信息写入的级别,如源代码、类文件等等。举个例子:

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public @interface SignedMethod {

}

在使用时,我们需要在注解名称前面写上@,然后()中指定参数值,如:

@MyAnnotationForMethods (

        index = 1, 

        info = "This is a method to test MyAnnotation.",

        developer = "Somebody else"

)

public void testMethod1() {

    // ...

}

注解的最大作用在于它在源代码的基础上增加了有用的信息,使得源代码的描述性更强。这些信息可以被代码之外的工具识别,从而可以很方便的增加外部功能,以及减少不必要的相关代码/文件的维护。这里我想简单提一个超出J2SE(TM) 5.0范畴的话题:在未来的EJB 3.0规范中会有相当多的对注解的应用,让我们预览一下将来的无状态会话bean用注解来定义会是什么样子:

@Stateless public class BookShelfManagerBean {

    public void addBook(Book aBook) {

        // business logic goes here...

    }

    public Collection getAllBooks() {

        // business logic goes here...

    }

    // ...

}

我们甚至不用写任何接口和部署描述符,这些工作将完全由外部工具通过读取注解加上反射来完成,这不是很好吗?

1.11.  C风格格式化输出
Java总算也有类似C的printf()风格的方法了,方法名同样叫作printf(),这一特性依赖于前边提到的可变长度参数。举个例子来说,我们现在可以写:

System.out.printf("%s has a value of %d.%n", someString, a);

 

怎么样,看上去还不错吧?需要注意的是Java为了支持多平台,新增了%n标示符,作为对\n的补充。有关Java格式化输出的具体语法,请参考java.util.Formatter的API文档。

1.12.  结语
在这一篇介绍性的文章中,我们一起领略了J2SE 5.0带来的新的语言元素,不知道大家是否也跟笔者一样,感受到了这些新特性在提高我们的开发效率上所作的巨大努力。其实不只是语言元素,J2SE(TM) 5.0的发布在其他很多方面都作了不小的改进,包括虚拟机、新的API类库等等,性能和功能上都有大幅提升。

 

对于主要靠J2EE吃饭的朋友来讲,也许真正意义上要在工作中充分利用这些新的元素,恐怕要等主流的J2EE服务器都支持J2EE(TM) 5.0的那一天了,对此我充满期待。

posted @ 2006-07-18 20:29 快乐着飞舞着 阅读(1170) | 评论 (0)编辑 收藏

"struts中文问题","struts国际化问题"??终极解决方案[转载]

引用 自:
http://hellocoffeecat.spaces.msn.com/Blog/cns!F0C1403231EB3BB0!151.entry
http://hellocoffeecat.spaces.msn.com/blog/cns!F0C1403231EB3BB0!151.trak


"struts中文问题","struts国际化问题"??终极解决方案
Java本身就支持多国语言编码,不需要写任何程序,可以很简单的
实现。
秘诀就是两点:

1、所有HTML/JSP页面全部采用UTF-8编码

2、客户端浏览器完全支持UTF-8编码

步骤:
1、首先把所有的HTML/JSP的ContentType都设为UTF-8

2、然后对于JSP程序中的非ASCII码提示信息都不应该写在程序里面,都应该放在
application.properties里面统一管理。

3、对HTML用native2ascii工具统一做一次处理,把HTML中的非ASCII码都转换为Unicode编码。

4、针对不同的语言,写不同的application.properties,比如说简体中文是
application_zh_CN.properties,繁体中文是application_zh_TW.properties这样,然后对这些配置信
息文件同样用native2ascii工具处理一次,把非ASCII码统统转为Unicode编码。

5、在Servlet的request.getCharacterEncoding()获得客户端的操作系统默认编码,然后set到Struts
的HTTPSession的Locale中。

OK!现在不同的客户访问,就会显示不同的语言版本了。你可以看看此时你的浏览器的字符集,就是
UTF-8。现在你的网站和Google一样了,嘿嘿,其实你有心的话,看看你的浏览器访问Google的时候是
什么字符集吧

切记:所有的HTML/JSP都要设为UTF-8编码,所有的文件中的非ASCII码字符都要用native2ascii工具转
为用ASCII表示的Unicode编码。
----------------------------------------
----------------------------------------
原创
----------------------------------------
上面所述是我从网上下的一篇于中文问题的解决方案,确切的说应该是关于Struts的国际化问题,下面我结合我的实践谈谈具体如何实现Struts的国际化问题,我对理论不是非常精通,我只能完全凭自己的理解和实践来讲述,所以下面讲的内容可能不是非常正确,还请大家原谅。但有一点可以肯定,我通过自己的努力解决了Struts的中文问题,并实现Struts的国际化,其实一切并不复杂,下面是具体步骤:

0.遇到的问题(这些问题也许不会同时出现)
a.中文数据从数据库中到jsp中后就变成了"????"
b.做好的中文properties文件,其中的中文value在页面显示乱码
c.jsp文件中的中文到浏览器后显示时也是乱码(建议不要在jsp文件中输入中文,尽量放在properties文件中)
d.由jsp传给bean的中文值,再由bean传回页面又是乱码
e.当更换本地浏览器的语言选项时,Web应用程序不能自动根据你的locale选择合适的*.properties文件。导致Web应用程序不能国际化。
1.环境:
Web服务器: Tomcat 5.0.19
操作系统: Win2000 Server
JVM : jdk 1.4
数 据 库: Oracle 8.1.7
开发工具: struts studio 5.2 pro for eclipse
2.先将所有*.jsp 网页中开头处加入

<%@ page language="java" contentType="text/html; charset=utf-8" %>
再设置<html:html locale = "true">

3.然后编辑好两个*.properties文件,放在classes文件夹下你指定的地方,这里是放在/web-inf/classes/com/wiley 下,它们分别是:

ApplicationResources.properties (英文资源文件)
ApplicationResources_zh.properties (中文资源文件)
随便用什么工具编写都行啊!
4.将ApplicationResources_zh.properties转码成gb2312。上面引文说要转成UTF-8,结果我试了,不行。转成gb2312就行了,操作是。
将ApplicationResources_zh.properties更名为ApplicationResources_xx.properties
在DOS命令行进入ApplicationResources_xx.properties所在的文件夹
使用命令:native2ascii -encoding gb2312 ApplicationResources_xx.properties ApplicationResources_zh.properties(至于你为什么会出现“native2ascii不是内部命令”,,请查其它资料,可能你要设置环境变量,因为他是jdk的文件夹bin下的一个应用程序)
5.接下来配置struts-config.xml,很简单,我们加入:

<message-resources parameter="com.wiley.ApplicationResources"/> 就行了;

到此已能解决大多数中文问题。如上面所说的a,b,e 现在打开浏览器,选择菜单:工具》internet选项》语言,将“中文-中国[zh-cn]”删掉,添加一个“英语-英国[zh-gb]”确定后,重启Tomcat,输入网址你就会发现,你的页面的文本信息就会用的是ApplicationResources.properties (英文资源文件)中的内容。如果换回“中文-中国[zh-cn]”,它就会显示ApplicationResources_zh.properties (中文资源文件)中的中文内容。

至于问题“c.jsp文件中的中文到浏览器后显示时也是乱码” 你就要用与第4步类似的方法来重新对*.jsp 文件编码,这时-encoding的参数就要用UTF-8了,如果你用的也是struts studio 5.2 pro for eclipse工具,这一步就免了。它会自动用UTF-8的格式存储。
至于问题“d.由jsp传给bean的中文值,再由bean传回页面又是乱码”的解决,我只是加了个过滤器。
你可以现在web.xml中加入:
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>com.wiley.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<servlet-name>action</servlet-name>
</filter-mapping>

然后在你指定的包内加个java文件 我放在了/web-inf/classes/com/wiley 里,下面是源代码:


/*
* XP Forum

* Copyright (c) 2002-2003 RedSoft Group. All rights reserved.
*
*/
package com.huahang.tj.struts.filters;

import javax.servlet.*;
import java.io.IOException;

/**
* <p>Filter that sets the character encoding to be used in parsing the
* incoming request, either unconditionally or only if the client did not
* specify a character encoding. Configuration of this filter is based on
* the following initialization parameters:</p>
* <ul>
* <li><strong>encoding</strong> - The character encoding to be configured
* for this request, either conditionally or unconditionally based on
* the <code>ignore</code> initialization parameter. This parameter
* is required, so there is no default.</li>
* <li><strong>ignore</strong> - If set to "true", any character encoding
* specified by the client is ignored, and the value returned by the
* <code>selectEncoding()</code> method is set. If set to "false,
* <code>selectEncoding()</code> is called <strong>only</strong> if the
* client has not already specified an encoding. By default, this
* parameter is set to "true".</li>
* </ul>
*
* <p>Although this filter can be used unchanged, it is also easy to
* subclass it and make the <code>selectEncoding()</code> method more
* intelligent about what encoding to choose, based on characteristics of
* the incoming request (such as the values of the <code>Accept-Language</code>
* and <code>User-Agent</code> headers, or a value stashed in the current
* user´s session.</p>
*
@author <a href="mailto:jwtronics@yahoo.com">John Wong</a>
*
@version $Id: SetCharacterEncodingFilter.java,v 1.1 2002/04/10 13:59:27 johnwong Exp $
*/
public class SetCharacterEncodingFilter implements Filter {

// ----------------------------------------------------- Instance Variables


/**
* The default character encoding to set for requests that pass through
* this filter.
*/
protected String encoding = null;


/**
* The filter configuration object we are associated with. If this value
* is null, this filter instance is not currently configured.
*/
protected FilterConfig filterConfig = null;


/**
* Should a character encoding specified by the client be ignored?
*/
protected boolean ignore = true;


// --------------------------------------------------------- Public Methods


/**
* Take this filter out of service.
*/
public void destroy() {

this.encoding = null;
this.filterConfig = null;

}


/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
*
@param request The servlet request we are processing
@param result The servlet response we are creating
@param chain The filter chain we are processing
*
@exception IOException if an input/output error occurs
@exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding 
= selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}

// Pass control on to the next filter
chain.doFilter(request, response);

}


/**
* Place this filter into service.
*
@param filterConfig The filter configuration object
*/
public void init(FilterConfig filterConfig) throws ServletException {

this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value 
= filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;

}


// ------------------------------------------------------ Protected Methods


/**
* Select an appropriate character encoding to be used, based on the
* characteristics of the current request and/or filter initialization
* parameters. If no character encoding should be set, return
* <code>null</code>.
* <p>
* The default implementation unconditionally returns the value configured
* by the <strong>encoding</strong> initialization parameter for this
* filter.
*
@param request The servlet request we are processing
*/
protected String selectEncoding(ServletRequest request) {

return (this.encoding);

}

}
//EOC

到此我遇到的中文问题已全部得到解决,并从中理解到struts的国际化的深刻含义。
我个人觉得struts作为一个功能强大的应用框架,应该早就考虑到它的国际化问题,并在实际应用中不会很复杂,只要我们遵循一些规则,就可以尽情享受struts给我们带来的无穷乐趣。希望以上所述对大家有所帮助。

posted @ 2006-06-13 21:32 快乐着飞舞着 阅读(249) | 评论 (0)编辑 收藏

最近要解决的项目的问题

  1. LoadMap的问题
  2. 数据库的更改
  3. find的更改
  4. GPS 模块的加入

posted @ 2006-05-17 10:20 快乐着飞舞着 阅读(125) | 评论 (0)编辑 收藏

EVC 真不是好东西

用evc以来已经碰到各种各样稀奇古怪的错误无数
要崩溃了


posted @ 2006-05-10 10:52 快乐着飞舞着 阅读(211) | 评论 (0)编辑 收藏

C# 文件编码的问题

本来文件编码是一个很简单的问题 只要用

sw = new  StreamWriter( " ./zz.cvs " , true ,System.Text.Encoding.GetEncoding( " gb2312 " ));



写到文件中就可以了 但是今天死活不行来回折腾了很久

最终发现问题是:

sw = new  StreamWriter( " ./zz.cvs " , true ,System.Text.Encoding.GetEncoding( " gb2312 " ));

注意这个true 我每次改了代码以后都没有把文件删除
所以每次都是往文件的后面写

但是这个文件创建时用了不正确的编码ANSI ,
所以导致即使用了正确的编码往里面写都无法显示正确

删除文件重新运行 打开一切正常 问题解决

posted @ 2006-04-11 15:39 快乐着飞舞着 阅读(1302) | 评论 (0)编辑 收藏

UNIX痛恨者手册

     摘要: http://net.ytu.edu.cn/share/%D7%CA%C1%CF/Unix%CD%B4%BA%DE%D5%DF%CA%D6%B2%E1.htm   UNIX痛恨者手册 第一章 UNIX——世界上第一个电脑病毒 ...  阅读全文

posted @ 2006-04-04 16:57 快乐着飞舞着 阅读(686) | 评论 (1)编辑 收藏

累!

posted @ 2005-11-14 14:10 快乐着飞舞着 阅读(152) | 评论 (1)编辑 收藏

仅列出标题
共10页: 1 2 3 4 5 6 7 8 9 Last 

Clicky