免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1764 | 回复: 8
打印 上一主题 下一主题

关于结构和枚举[求助] [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-04-12 17:23 |只看该作者 |倒序浏览
怎么样在文档中使用这两个“数据类型”,结构这个接口应该怎么实现?枚举类如何使用?

论坛徽章:
0
2 [报告]
发表于 2006-04-12 20:00 |只看该作者

以下文章是在网上找来的,只有讲枚举的一部分,希望你楼主有所帮助

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的类型安全枚举就是包含了有限数量的已生成好的自身实例的一种类,这些现成的实例可以通过类的静态字段来获取。

[ 本帖最后由 perryhg 于 2006-4-12 21:08 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2006-04-12 21:10 |只看该作者
enum的部分这个例子是看明白语法了
不过测试类中

for (Operation op : Operation.values()) {
        System.out.println(x + " " + op + " " + y + " = " + op.eval(x, y));
    }
这个循环的意思也了解了,就是语法没搞懂,为啥这样?有高手讲讲么?还是5.0新引入专门对应枚举的?

[ 本帖最后由 艾斯尼勒 于 2006-4-12 21:29 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2006-04-12 21:43 |只看该作者
再贴另一部分!!!!
我摘过来这篇文章叫《J2SE 5.0专题 之 语言特性》,如果想看的话在网上搜一下就出来了。
1.5.        增强的for循环
你是否已经厌倦了每次写for循环时都要写上那些机械的代码,尤其当你需要遍历数组或者Collection,如:(假设在Collection中储存的对象是String类型的)
public void showAll (Collection c) {
    for (Iterator iter = c.iterator(); iter.hasNext();&nbsp {
        System.out.println((String) iter.next());
    }
}

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

public&nbsp;void&nbsp;showAll&nbsp;(String[]&nbsp;sa)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(String&nbsp;str&nbsp;:&nbsp;sa)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str);
&nbsp;&nbsp;&nbsp;&nbsp;}
}
这样的代码显得更加清晰和简洁,不是吗?具体的语法很简单:使用":"分隔开,前面的部分写明从数组或Collection中将要取出的类型,以及使用的临时变量的名字,后面的部分写上数组或者Collection的引用。加上泛型,我们甚至可以把第一个方法变得更加漂亮:
public&nbsp;void&nbsp;showAll&nbsp;(Collection<String>&nbsp;cs)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(String&nbsp;str&nbsp;:&nbsp;cs)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str);
&nbsp;&nbsp;&nbsp;&nbsp;}
}
有没有发现:当你需要将Collection<String>替换成String[],你所需要做的仅仅是简单的把参数类型"Collection<String>"替换成"String[]",反过来也是一样,你不完全需要改其他的东西。这在J2SE(TM)&nbsp;5.0之前是无法想象的。

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

论坛徽章:
0
5 [报告]
发表于 2006-04-12 21:52 |只看该作者
谢谢,我去搜搜看,虽然一直在用5.0,但新特性一直没有接触过。多谢

这个for很象php中的foreach

[ 本帖最后由 艾斯尼勒 于 2006-4-12 21:53 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-04-13 00:28 |只看该作者
原帖由 艾斯尼勒 于 2006-4-12 22:52 发表
谢谢,我去搜搜看,虽然一直在用5.0,但新特性一直没有接触过。多谢

这个for很象php中的foreach


确实,1。5刚出的时候有一期 程序员 讲tiger新特性,但是这么久了,还从来没写过,懒得去学新招

论坛徽章:
0
7 [报告]
发表于 2006-04-13 13:11 |只看该作者
原帖由 kakasi 于 2006-4-13 00:28 发表


确实,1。5刚出的时候有一期 程序员 讲tiger新特性,但是这么久了,还从来没写过,懒得去学新招



其他的不说,但最少泛型应该是要学习的吧,总听说,但没接触过,昨晚看了看貌似用处很大

论坛徽章:
0
8 [报告]
发表于 2006-04-13 16:40 |只看该作者
谢谢

论坛徽章:
0
9 [报告]
发表于 2006-04-13 17:17 |只看该作者
这个东西其实不大好用的,毕竟习惯了……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP