jdk5.0新特性

以下是网上摘录的: JDK5.0的新特性(2005-2006)
“JDK1.5”(开发代号猛虎)的一个重要主题就是通过新增一些特性来简化开发,
这些特性包括泛型,for-each 循环,自动装包/拆包,枚举,可变参数, 静态导入
C 风格的格式化 I/O、、并发实用程序以及更简单的 RMI 接口生成。
JSR 201 包括如下四个语言变化:增强的 for 循环、枚举类型、静态导入和 autoboxing;JSR 175 指定了新的元数据功能,而 JSR 14 则详细说明了泛型。
javac 编译器执行的默认语言规范是版本 1.4。这意味着要利用以下语言变化的任何好处,需要向 javac 命令传递参数 -source 1.5。
使用这些特性有助于我们编写更加清晰,精悍,安全的代码。
  下面我们简单介绍一下这些新特性。
  1.泛型(Generic)
  C++通过模板技术可以指定集合的元素类型,而Java在1.5之前一直没有相对应的功
能。一个集合可以放任何类型的对象,相应地从集合里面拿对象的时候我们也不得不对
他们进行强制得类型转换。猛虎引入了泛型,它允许指定集合里元素的类型,这样你可
以得到强类型在编译时刻进行类型检查的好处。
 
Collection c = new ArrayList();
c.add(new Date());
 
  编译器会给出一个错误:
 
add(java.lang.String) in java.util.Collection cannot be applied to 
(java.util.Date)
 
  2.For-Each循环
  For-Each循环得加入简化了集合的遍历。假设我们要遍历一个集合对其中的元素进
行一些处理。典型的代码为:
 
void processAll(Collection c){
    for(Iterator i=c.iterator(); i.hasNext();){
        MyClass myObject = (MyClass)i.next();
        myObject.process();
    }
}
 
  使用For-Each循环,我们可以把代码改写成:
 
void processAll(Collection c){
    for (MyClass  myObject :c)
        myObject.process();
}
 
  这段代码要比上面清晰许多,并且避免了强制类型转换。
  3.自动装包/拆包(Autoboxing/unboxing)
  自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
  自动装包:基本类型自动转为包装类.(int >> Integer)
  自动拆包:包装类自动转为基本类型.(Integer >> int)
  在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀,现在自动转换机制
解决了我们的问题。
int a = 3;
Collection c = new ArrayList();
c.add(a);//自动转换成Integer.
Integer b = new Integer(2);
c.add(b + 2);
  这里Integer先自动转换为int进行加法运算,然后int再次转换为Integer.
  4.枚举(Enums)
  JDK1.5加入了一个全新类型的“类”-枚举类型。为此JDK1.5引入了一个新关键字
enmu. 我们可以这样来定义一个枚举类型。
 
public enum Color
{
   Red,
   White,
   Blue
}
  然后可以这样来使用Color myColor = Color.Red.
  枚举类型还提供了两个有用的静态方法values()和valueOf(). 我们可以很方便地
使用它们,例如
for (Color c : Color.values())
            System.out.println(c);
  5.可变参数(Varargs)
  可变参数使程序员可以声明一个接受可变数目参数的方法。注意,可变参数必须是
函数声明中的最后一个参数。假设我们要写一个简单的方法打印一些对象,
util.write(obj1);
util.write(obj1,obj2);
util.write(obj1,obj2,obj3);
  在JDK1.5之前,我们可以用重载来实现,但是这样就需要写很多的重载函数,显得
不是很有效。如果使用可变参数的话我们只需要一个函数就行了
public void write(Object... objs) {
   for (Object obj: objs)
      System.out.println(obj);
}
  在引入可变参数以后,Java的反射包也更加方便使用了。对于
c.getMethod("test", new Object[0]).invoke(c.newInstance(), new 
Object[0])),现在我们可以这样写了
c.getMethod("test").invoke(c.newInstance()),这样的代码比原来清楚了很多。 
  6.静态导入(Static Imports)
  要使用用静态成员(方法和变量)我们必须给出提供这个方法的类。使用静态导入
可以使被导入类的所有静态变量和静态方法在当前类直接可见,使用这些静态成员无需
再给出他们的类名。
import static java.lang.Math.*;
…….
r = sin(PI * 2); //无需再写r = Math.sin(Math.PI);
  不过,过度使用这个特性也会一定程度上降低代码地可读性。
元数据
J2SE 1.5 中的元数据特性提供这样的能力,即向 Java 类、接口、方法和字段关联附加的数据。这些附加的数据或者注释,可以被 javac 编译器或其他工具读取,并且根据配置不同,可以被保存在类文件中,也可以在运行时使用 Java 反射 API 被发现。
向 Java 平台增加元数据的一个主要原因是,使得开发工具和运行工具有一个通用的基础结构,以减少开发和部署所需的成本。工具可以使用元数据信息生成附加的源代码,或者在调试时提供附加信息。
下面的例子用元数据工具创建了一个调试元数据注释,这些元数据注释然后又简单地在运行时显示出来。可以想像,大部分的元数据标签形成一个标准,即一个良好规范的集合。
import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface debug {
boolean devbuild() default false;
int counter();
}

public class MetaTest {
final boolean production=true;
@debug(devbuild=production,counter=1) public void testMethod() {
}


public static void main(String[] args) {

MetaTest mt = new MetaTest();
try {
Annotation[] a = mt.getClass().getMethod("testMethod").getAnnotations();
for (int i=0; i<a.length ; i++) {
System.out.println("a["+i+"]="+a+" ");
}
} catch(NoSuchMethodException e) {
System.out.println(e);
}
}
}

利用一个元数据处理工具,许多重复的代码编写步骤可以减少成一个简练的元数据标签。例如,访问某个 JAX-RPC 服务实现时所需的远程接口可以实现为:
原来(J2SE 1.5 以前版本):
public interface PingIF extends Remote {
public void ping() throws RemoteException;
}
public class Ping implements PingIF {
public void ping() {
}
}
 

现在:
public class Ping {
public @remote void ping() {
}
}
二、元数据(注解)
  这是JDK5.0学XDoclt的,有了注解,以后我们可以不必写接口,EJB写起来会方便很多。EJB3.0要精简写法,注解要占一些功劳。
  介绍一个常用的注解:@Override,示例如下:
public class Test extends ATest{

@Override
    public void test() {
    }
}
 在方法前加了这个注解,就限定死了Test的这个方法一定要是覆盖自ATest的方法test,否则就会报错。比如你不心把方法test()写成了tesd(),编译时就会报错。另一个要注意的是@Override用于定义覆盖接口的方法,也就是说ATest必须是一个抽象类、普通类,但不能是接口。
   另一个常见到的注解是@Deprecated,表明该项(类、字段、方法)不再被推荐使用。不过我们自己一般很少用到这个注解。
  好了,注解只讲这两个吧,也不必了解太多,知道个概念,以后用到的时候再说吧。关于注解,建议看看XDoclt,这是一个开源小工具,在项目开发中非常好用。
我喜爱的Java 5.0的五个特性作者:David Flanagan, Java in a Nutshell, 第5版的作者

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
作者:
David Flanagan; xml1123
原文地址:
http://www.onjava.com/pub/a/onjava/2005/04/20/javaIAN5.html
中文地址:
http://www.matrix.org.cn/resource/article/43/43830_Java5.html
关键词: Java5

至今,毫无疑问你已经看过不止一篇网上文章列举了Java5.0的伟大的语言新特性:泛型,标注,枚举类型,自动装箱,可变参数, for/in循环,甚至静态引入。我也认为这些是伟大的特性,但是,你已经读过他们了。因此,在此我将集中于你可能没有听说过的Java5.0的新API特性。

那么,在下面,是我喜欢的Java5.0的五个新API特性。我已经在《果壳中的Java》(《Java in a nut shell》)第五版的第五章中介绍过他们。并且我也在我的网站中记录了其中的一些。那些看完本文后的细心的读者会发现额外的奖励—第六个特性:很少有人知道的Java5.0支持的新语言语法,当然使用者就更少了。我非常喜欢它,因为它很新异。

Callable 和 Future 接口

我喜欢的第一个特性发掘自新的java.util.concurrent包。如它的名字暗示的,这是个并行编程工具包。在此有很多要探索的,而我要提的第一喜欢的特性是TimeUnit枚举类型。TimeUnit让我感兴趣的是它包含有用的时间相关工具--你通过一个枚举常量来调用它们,该常量代表度量时间的单位。例如:
TimeUnit.MILLISECONDS.sleep(200);

然而,TimeUnit并不是最值得夸奖的。java.util.concurrent最强大的特性之一是它的任务-执行/线程-池结构。ExecutorService接口提供了执行任务的能力。Executors类定义了工厂方法用于获取使用线程池的ExecutorService的实现。这是强大的要素。

我所喜欢的任务-执行框架的部分是它如何表现任务以及执行它的结果:Callable和Future接口。我们都熟悉用于定义线程的Runnable接口和它的run()方法。Callable像Runnable,但它的方法叫做call(),并且这个方法可以返回一个结果或者抛出一个异常,而这两点是Runnable.run()做不到的。

Callable是一个泛型,并且它的结果已经参数化。例如,一个计算BigInteger的任务,是Callable<BigInteger>,并且它的方法call()被声明为返回BigInteger。下面是仅有三行代码的Callable接口:

public interface Callable<V> {
      V call() throws Exception;
  }


当我想要异步执行一个Callable任务,我将它传递给ExecutorService的submit()方法。submit()的返回值—这也是我喜欢的部分—是一个Future对象:本质上是一个对将来某时刻的结果的“借条”。如果我准备使用我的任务的结果,我简单的调用Future对象的get()方法即可。如果任务的执行已完成,那么get()立刻返回结果。否则,它将阻塞直到结果可用。如果Callable抛出异常,那么get()方法将该异常包装为ExecutionException并且抛出它。Future还有方法用来对任务的执行进行取消和查询状态,但是你必须自己查找它们(这些方法)。Future也用了泛型,并且结果的类型也参数化了。因此如果我submit()一个Callable<BigInteger>来执行,我将获得一个Future< BigInteger >。

下面是一个简短的例子:

/**
* 这是一个用来计算大素数的Callable。
*/
public class PrimeSearch implements Callable<BigInteger>
{
    static Random prng = new SecureRandom();
    int n;
    public PrimeSearch(int bitsize) { n = bitsize; }
    public BigInteger call() {
        return BigInteger.probablePrime(n, prng);
    }
}

// 尝试同时计算两个素数
ExecutorService pool = Executors.newFixedThreadPool(2);
Future<BigInteger> p = pool.submit(new PrimeSearch(512));
Future<BigInteger> q = pool.submit(new PrimeSearch(512));

// 将两个素数相乘来得到一个合数
BigInteger product = p.get().multiply(q.get());



可变参数和自动装箱

我说过我不想谈论Java5.0的新语言特性,我不会,但是我确实关注由于可变参数和自动装箱才变为可能的(或者被增强的旧API)新的API。

首先,当然,是Java5.0的printf风格的文本格式化能力,通过java.util.Formatter类和类似String.format()的工具方法。这类文本格式化是最常被引用来支持语言的增加的可变参数和自动装箱的那种用例。考虑这个:

String s = String.format("%s:%d: %s%n", filename,
                           lineNumber,
                             exception.getMessage());


关于这段代码没有什么特别值得注意的东西。我将它列在这是为了说明因为可变参数和自动装箱所以比下面的例子显得简单:

String s = String.format("%s:%d: %s%n", new Object[] {
                           filename,
                           new Integer(lineNumber),
                             exception.getMessage()});

一、C风格格式化输出
在JDK5.0后,我们这样写代码:
    public static void main(String[] args) {
        int x = 10;
        int y = 20;
        int sum = x + y;
        System.out.printf("%d + %d = %d", x, y, sum);
    }

可变参数和自动装箱还对java.lang.reflect API有一个实质性的影响。那就是当查找和调用方法时不再需要类和对象数组:

Method m = c.getMethod("put", Object.class,Object.class);
  m.invoke(map, "key", "value");


如果我必须选择一个最喜欢的可变参数方法,那么,将是java.util.Arrays.asList()。这个方法真是个用于创建不变的对象列表的方便的工厂方法。它接受任何数量的类型T的参数并且将它们作为List<T>返回:

List<Integer> smallPrimes =
     Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19);


能力

我们在上面谈论了Runnable和Callable,并且你毫无疑问已经听说过重要的Comparable, Serializable,和Cloneable接口。Java5.0新增加了五个重要的能力接口。第一个,当然,是java.lang.Iterable。你或许知道Java5.0新的for/in循环可以迭代数组和集合。你可能不知道它能够对任何实现了可迭代(Iterable)接口的对象工作。因此,如果你想让一个不是集合的数据结构可以简单地迭代,只需实现Iterable接口。你要做的就是增加一个返回java.util.Iterator 的iterator()方法。当然,写这个迭代器(Iterator)可能不是那么简单的。

下面的代码是一个实现了Iterable<String>(是的,Iterable是泛型的)的文本文件类,因而允许文本文件可以用for/in循环逐行的迭代。你可以用类似下面的代码使用它:

TextFile textfile = new TextFile(new File(f), "UTF-8");
  int lineNumber = 0;
  for(String line : textfile)
      System.out.printf("%6d: %s%n", ++lineNumber, line);


下面是TextFile的代码。注意,迭代器不尝试检测对底层文件的并发的修改。如果你想自己做,看一看

java.nio.channels.FileLock。
import java.io.*;
import java.util.Iterator;

public class TextFile implements Iterable<String> {
    File f;
    String charsetName;

    public TextFile(File f, String charsetName)
        throws IOException
    {
        this.f = f;
        this.charsetName = charsetName;

        if (!f.exists())
            throw new FileNotFoundException(f.getPath());
        if (!f.canRead())
            throw new IOException("Can't read: " +
                                  f.getPath());
    }

    public Iterator<String> iterator() {
        try {
            return new TextFileIterator(f, charsetName);
        }
        catch(IOException e) {
            throw new IllegalArgumentException(e);
        }
    }


    static class TextFileIterator
        implements Iterator<String>
    {
        BufferedReader in;
        String nextline;
        boolean closed = false;

        public TextFileIterator(File f, String charsetName)
            throws IOException
        {
            InputStream fis = new FileInputStream(f);
            Reader isr =
                new InputStreamReader(fis, charsetName);
            in = new BufferedReader(isr);
            getNextLine();
        }

        public boolean hasNext() {
            return nextline != null;
        }

        public String next() {
            String returnValue = nextline;
            getNextLine();
            return returnValue;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

        void getNextLine() {
            if (!closed) {
                try { nextline = in.readLine(); }
                catch(IOException e) {
                    throw new IllegalArgumentException(e);
                }
                if (nextline == null) {
                    try { in.close(); }
                    catch(IOException ignored) {}
                    closed = true;
                }
            }
        }
    }
}


Iterable是到目前为止最重要的新能力接口,但是其它的也是非常的漂亮。接下来,我们碰到java.lang.Appendable。一个Appendable对象可以追加字符或字符序列(或者一个字符序列的子序列)。实现者包括StringBuffer和StringBuilder(如果你还没有听说过它,一定要看一看),Writer(及其子类),PrintStream,还有java.nio.CharBuffer。将可追加性从这些类中分离出来成为Appendable接口,使得新的java.util.Formatter类更强大:它能将文本格式化为任何可追加的对象,包括你自己的实现。(练习留给读者:你能否将上面的TextFile类变得既可迭代又可追加么?)。


java.lang.Readable接口和Appendable相反:一个可读对象可以将字符传输给给定的CharBuffer。java.io.Reader和它的全部子类都是可读的(当然了),CharBuffer本身也一样。就像Appendable是为了java.util.Formatter的利益而创造,Readable是为了java.util.Scanner的利益而创造。(Java5.0增加了Scanner,连同Formatter。这是Java对C的scanf()函数的适应,但是它(Scanner)不像Formatter之对应于printf()的关系那样密切。)

我想讨论的最后两个能力接口是java.io.Closeable和java.io.Flushable。如它们的名字暗示的,它们趋向于被任何类实现,通过一个close()或者flush()方法。Closeable被所有的输入和输出流类,RandomAccessFile和Formatter实现。Flushable被输出流类和Formatter实现。这些接口也是为了Formatter类的利益而定义。注意,Appendable对象(像StringBuilder)不总是可关闭或者可冲刷(flushable)。通过将可关闭性和可冲刷性分解出来成为这些接口,Formatter的close()和flush()方法能够决定它们操作的Appendable对象是否需要被关闭或被冲刷。(Java5.0还增加了第六个能力接口,并且它也是有关Formatter类的。那些想要控制它们的实例怎样被格式化的类可以实现java.util.Formattable接口。然而这个接口的API是难用的,我不想谈论它。)

@Override

毫无疑问,你已经听说过能用元数据标注Java5.0的类型和方法。但是你可能不熟悉增加到java.lang的标准标注类型。我喜欢的第四个特性就是java.lang.Override标注。当你写一个方法准备覆盖另一个的方法时,用@Override来标注它,这样编译器会进行检查来确保你确实,实际上,覆盖了你想覆盖的方法。

如果你拼写错了方法名字或者弄错了方法参数,那么你实际上并没有覆盖那个你认为你覆盖了的方法。这样就造成了一个如果不用@Override很难捕捉的臭虫。我所以知道是因为我的关于Java1.4的新API特性的文章就讲到了这个臭虫,并且这个错误至少有一年一直没被检测到(至少没有被报告)。在那篇文章中,你可以在第一页结尾看到我犯的错误。那篇文章现在包含一个链接到我的博客入口,在那里我改正了这个臭虫并且在代码中增加了@Override声明。

MatchResult
我喜欢的Java5.0的最后一个特性是java.util.regex.MatchResult。对于用于正则表达式的模式/匹配API我从来没有真正非常满意。Java5.0增加的MatchResult在让我大大地更加满意。当使用一个不太平凡的模式(Pattern),每次调用匹配者(Matcher)的find()方法会生成许多状态:开始位置,结束位置,匹配的文本,同时还有模式的开始,结束,每个子表达式的文本。在Java5.0以前,你只能从Matcher获取它们,通过在调用find()后再调用start(),end(),还有group(),如果需要的话。

然而,到了Java5.0,你可以只调用toMatchResult()来获取MatchResult对象再获取全部的状态,MatchResult对象可以保存并且可以以后再检查。MatchResult像Matcher一样有start(),end(),以及group()方法,并且,实际上,Matcher现在实现了MatchResult。
这里是一个有用的返回MatchResult的方法:

public static List<MatchResult> findAll(Pattern pattern,
                                        CharSequence text)  {
    List<MatchResult> results =
        new ArrayList<MatchResult>();
    Matcher m = pattern.matcher(text);
    while(m.find()) results.add(m.toMatchResult());
    return results;
}


还有使用这个方法的代码:

List<MatchResult> results = findAll(pattern, text);
for(MatchResult r : results) {
    System.out.printf("Found '%s' at (%d,%d)%n",
                      r.group(), r.start(), r.end());
}



十六进制浮点数字面值

我承诺谈论Java5.0的最晦涩的新语言特性。这就是:十六进制格式的浮点常量!这里是奇异的详情:一个十六进制符号的浮点常量以0X或者0x开头。随后的十六进制数字形成了数的基数。关键是这些数字可以包含一个小数点(一个十六进制小数点?)。在基数后面是指数,是必需的。十六进制浮点常量使用p或者P而不是e或者E来引入指数。(想一下“幂”来帮助记忆)。P或者P后面是指数,必须是一个十进制数,而不是十六进制数。而且这是个以二为根的指数,而不是以十为根。那就是,表示基数要乘以的2的幂。最后,整个常量可以跟随一个f或者F来表示一个浮点常量,或者一个d或者D表示一个双精度常量,就像一个十进制浮点数一样。
下面是一些例子:

double x = 0XaP0;    // 10 * 2^0 = 10.0
  double y = 0XfP2D;   // 15 * 2^2 = 60.0
  float z  = 0Xf.aP1F; // (15 + 10/16ths) * 2^1 = 31.25f
  // 用十进制来打印
  System.out.printf("%f %f %f%n", x, y, z);
  // 用十六进制来打印
  System.out.printf("%a %a %a%n", x, y, z);


为什么Sun要对语言做这些?5.0的发行说明说:
为了允许特定浮点值实现精确及可预见的规范,十六进制符号可用于Float和Double的浮点字面值和字符串到浮点数的转换方法中。

这点是合理的。十进制小数像0.1是不能精确地用浮点格式表示的,并且如果你真的需要确切知道在一个浮点或者双精度值中比特位是怎么设的,那么你真的想要一个十六进制字面值。例如,Float.MAX_VALUE的Javadoc指出最大的浮点值是0x1.fffffeP+127f。

如果你知道并且喜欢IEEE-754浮点标准,那么十六进制浮点字段值或许是你喜欢的一个特性。我只是认为他们有趣。
一 从xml中装载属性
 
格式:

<properties>
<comment>Hi</comment>
<entry key="id">1</entry>
<entry key="name">rocie</entry>
<entry key="email">rocie@sina.com</entry>
</properties>

 
 
 
通过以下方法加载:

Properties prop = new Properties();
FileInputStream fis =  new FileInputStream("d:/jdk5/properties/test.xml");
prop.loadFromXML(fis);
prop.list(System.out);
System.out.println("Name: " + prop.getProperty("name"));

 
 
 
将xml文件放在WEB-INF/classes/目录下,可以防止对路径的硬编码

InputStream is = PropertiesTest.class.getClassLoader().getResourceAsStream("rocie.xml");
Properties ps = new Properties();
ps.loadFromXML(is);
System.out.println("name:"+ps.getProperty("name"));        

 
 
 
通过以下方法保存:

Properties prop = new Properties();
prop.setProperty("id", "2");
prop.setProperty("name", "彭大双");
prop.setProperty("email", "pds@dotraining.com");
FileOutputStream fos = new FileOutputStream("d:/jdk5/properties/pds.xml");
prop.storeToXML(fos, "彭大双","gbk");
fos.close();

 
 
 
xml文件细节:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Hi</comment>
<entry key="id">1</entry>
<entry key="name">rocie</entry>
<entry key="email">rocie@sina.com</entry>
</properties>

 
 
 
DTD文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- DTD for properties -->
<!ELEMENT properties ( comment?, entry* ) >
<!ATTLIST properties version CDATA #FIXED "1.0">
<!ELEMENT comment (#PCDATA) >
<!ELEMENT entry (#PCDATA) >
<!ATTLIST entry key CDATA #REQUIRED>

注:?表示0或1;*表示0至无限;+表示至少一个
 
 
 
二 并发集合
问题:ConcurrentModificationExceptionfail-fast
 
 
当遍历一个Iterator时,如果该Iterator对应的List里的元素发生改变,则抛出这个异常。
解决方法:java.util.concurrent
 
 
用CopyOnWriteArrayList代替原来的ArrayList
copy-on-write:这意味着如果有大量的读(即 get() ) 和迭代,不必同步操作以照顾偶尔的写(即 add() )调用。对于新的 CopyOnWriteArrayList 和 CopyOnWriteArraySet 类,所有可变的(mutable)操作都首先取得后台数组的副本,对副本进行更改,然后替换副本。这种做法保证了在遍历自身更改的集合时,永远不会抛出 ConcurrentModificationException 。遍历集合会用原来的集合完成,而在以后的操作中使用更新后的集合。
 
 
 
用 for/in 在 Java 5.0 中增强循环

public static List<Integer> list = new ArrayList<Integer>();
      
       public static int[] is = new int[]{1,2,3,4,65,456};
      
       static
       {           
              for(int i=0;i<100;i++)
                     list.add(i);             
       }
      
       public static void main(String args[])
       {
              for(Integer i:list)
                     System.out.println(i);    
              System.out.println("-------other for each--------");
              for(int i:is)
                     System.out.println(i);
       }

枚举类型 enum

public class EnumTest {
       private Color color;
      
       public static enum Color {red,yellow,blue,green};    
      
       public Color getColor() {
              return color;
       }
 
 
 
       public void setColor(Color color) {
              this.color = color;
       }
 
 
 
       public static void main(String args[])
       {
              for(Color c:Color.values())
              {
                     System.out.println("name:"+c.name()+"ordinal:"+c.ordinal());
              }    
              EnumTest et = new EnumTest();
              et.setColor(Color.red);
              Color c = et.getColor();
              switch(c)
              {
              case red: System.out.println("red:"+c.name()+c.ordinal());
                                   break;
              case yellow: System.out.println("yellow"+c.name()+c.ordinal());
                                   break;
              default : System.out.println("over");
              }
             
       }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值