- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Android开发笔记之:用Enum(枚举类型)取代整数集的应用详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
在android的api中可以发现有很多用整数集来作为参数的地方,先来看一下实例。 linearlayout是大家所熟知的一个ui基本元素,它里面有一个方向的属性,可以通过以下方法来设置:
复制代码 代码如下
linearlayout.setorientation(int),
使用的时候,通常都是这样:
复制代码 代码如下
linearlayout.setorientation(linearlayout.horizontal); linearlayout.setorientation(linearlayout.vertical),
但也可以这样使用:
复制代码 代码如下
linearlayout.setorientation(0); // linearlayout.horizontal = 0 linearlayout.setorientation(1); // linearlayout.vertical = 0x01 。
甚至可以这样:
复制代码 代码如下
linearlayout.setorientation(integer.max_value); linearlayout.setorientation(integer.min_value); linearlayout.setorientation(2012),
因为方法setorientation接收的参数是一个整数,所以你可以传任意合法的整数---至少这在编译时不会有任何问题。它只会在运行时可能引发问题,但如你所知,开发者只关注程序能否编译成功,至于运行时,那是用户关心的事儿,因为开发者不一定使用他们所开发出的程序。 除了这个例子,在android的api中到处可以看到这种api,比如设置view的可见性,设置wifi状态等等。都是定义了整数集,然后用整数来做为参数,并寄希望开发者能传递整数集中定义的常量来作为参数。但如你所知,并不是每个人都那么的守规矩,如果每个人都能遵守规则,这个世界就真的和谐了,蛋扯远了。 因为开发者通常只能关注编译,所以如果能把这个规则应用在编译时,那么就会大大减少出错的可能。有兴趣的朋友可以去试试看,给这些接收整数参数的方法传一些“平常”的数值,比如2012,integer.max_value,integer.min_value等等,看会出现什么状况。 另外,如果开发者传递与常量定义一致的整数值,虽然编译运行都不会有错,但代码的可读性会大大的降低,比如:
复制代码 代码如下
linearlayout.setorientation(0); linearlayout.setorientation(1),
这完全没有错,但是代码的阅读者和维护者通常都会蛋疼的。 当然,android自身还是有保护措施的,如果对api传递不合法参数,不会造成其他影响,只是设置不能生效,但api会使用默认值,因为对于每个内置参数,都有相应的默认值。如linearlayout的orientation,默认值就是linearlayout.horizontal,所以如果对setorientation()传入非法值,linearlayout会保持水平排列,无其他影响。后面有个对linearlayout的orientation做的试验。 另外,如果在layout xml文件中设置这些属性就不会有些问题,如:
复制代码 代码如下
<linearlayout android:orientation="vertical" android:gravity="center"> 。
因为xml布局会在编译时被处理,如果有非法的值,会有编译错误的。我想这也就是android特别鼓励开发者用xml来制作所有的布局的一个原因吧。实例,三个没有设置指向的线性布局,默认是水平放置,在代码中设置了几个离谱的值,发现它们还是水平的,也就是说设置离谱的值不会出错,但也不起作用:运行结果如下:
代码如下:
复制代码 代码如下
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" > <linearlayout android:id="@+id/linearlayout_test_1" android:layout_width="fill_parent" android:layout_height="wrap_content"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ff00ff00" android:background="#aa331155" android:layout_weight="1" android:textsize="18sp" android:text="microsoft" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ffff0000" android:background="#aa117711" android:layout_weight="1" android:textsize="18sp" android:text="apple" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ff0000ff" android:background="#aa774411" android:layout_weight="1" android:textsize="18sp" android:text="google" /> </linearlayout> <linearlayout android:id="@+id/linearlayout_test_2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ff00ff00" android:background="#aa331155" android:layout_weight="1" android:textsize="18sp" android:text="microsoft" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ffff0000" android:background="#aa117711" android:layout_weight="1" android:textsize="18sp" android:text="apple" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ff0000ff" android:background="#aa774411" android:layout_weight="1" android:textsize="18sp" android:text="google" /> </linearlayout> <linearlayout android:id="@+id/linearlayout_test_3" android:layout_width="fill_parent" android:layout_height="wrap_content"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ff00ff00" android:background="#aa331155" android:layout_weight="1" android:textsize="18sp" android:text="microsoft" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ffff0000" android:background="#aa117711" android:layout_weight="1" android:textsize="18sp" android:text="apple" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#ff0000ff" android:background="#aa774411" android:layout_weight="1" android:textsize="18sp" android:text="google" /> </linearlayout> </linearlayout> 。
和
复制代码 代码如下
package com.android.explorer; import android.app.activity; import android.os.bundle; import android.widget.linearlayout; public class linearlayouttest extends activity { @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.linearlayout_test); linearlayout one = (linearlayout) findviewbyid(r.id.linearlayout_test_1); one.setorientation(2012); linearlayout two = (linearlayout) findviewbyid(r.id.linearlayout_test_2); two.setorientation(integer.max_value); linearlayout three = (linearlayout) findviewbyid(r.id.linearlayout_test_3); three.setorientation(integer.min_value); } } 。
用enum代替整数集 其实很简单,用enum(枚举)就可以很方便的解决这个问题,使用起来也不比定义整数集繁琐,同样的可读。另外的优点就是,它的封装更好,最重要的是它会在编译时被检查。因为java是一种strong type,也就是说在编译时,编译器会对所有原型类型和参数类型进行检查,如果类型不对,并且没有强制转型的,就会报出编译错误,当然编译器所支持的自动转型除外。比如一个需要int,而传的参数是long,虽然都差不多,没有溢出等,但还是会有编译错误。 所以,如果linearlayout使用enum,就像这样定义:
复制代码 代码如下
public class linearlayout extends viewgroup { private orientation morientation; public enum orientation { horizontal, vertical }; public void setorientation(orientation dir) { morientation = dir; } } 。
然后这样使用:
复制代码 代码如下
import android.widget.linearlayout; linearlayout.setorientation(orientation.horizontal); linearlayout.setorientation(orientation.vertical),
那么,开发者就不会用错了,因为首先,它看到setorientation所需要的参数是一个orientation的枚举类型,就会自然的传送orientation中定义的类型;另外,如果传其他的值,比如0或者1,编译器也不会答应的。 可悲的是android中几乎所有的api都是以整数集的方式来定义的,所以就要时刻提醒自己和组里的人,一定要传所定义的整数集中的常量。 那么我们能做的,除了要传整数集中定义的常量,对于那些以整数集方式定义的api,以外。更重要的是当自己定义接口的时候,尽量用enum而不要使用整数集。 还有一点需要注意的是,对于某些弱类型语言,也就是说在编译时不会对类型做特别细致的检查,比如c++,c等,那么即使使用了enum,也不一定安全,因为对于c++和c来讲enum中的常量与整数常量完全一样,连编译器都分不清。所以,对于这类语言,只能寄希望于开发者了。 后记: 写完这篇,让我想起了另外一些与参数定义相关的问题,比如布尔型参数也不是一个很好的设计,因为使用者很难到底应该传true还是传false,特别是当方法名字不能体现boolean参数作用时和文档不够清楚的时候。如果只有一个参数还好,根据方法名字和常识都能知道,比如:
复制代码 代码如下
button.setenabled(true); // enable the button button.setenabled(false); // disable the button 。
但对于某些情况,当方法的名字不能体现boolean参数的作用时,或是多于一个参数时,而方法的主要目的又不能体现boolean参数的作用时,就很不清楚,比如:
复制代码 代码如下
// com/android/mms/data/contactlist.java public string[] getnumbers(boolean),
您能猜出来这个boolean变量是决定是否要为彩信对联系人做特殊的处理吗?您在使用这个api的时候能很快知道该传true还是该传false吗?当读到这些语句的时候:
复制代码 代码如下
string[] mms = getnumbers(true); string[] sms = getnumbers(false),
您能知道true和false的含义与作用吗?至少我看到这样的代码时,如果不去跟踪它的实现,是猜不出来的。 但现实的问题是,api通常又需要从调用者那里得到做还是不做的决定。一个可行的途径是用方法来封装和隐藏,比如:
复制代码 代码如下
button.setenabled(true); // enable the button button.setenabled(false); // disable the button 。
可以改成:
复制代码 代码如下
button.enable(); button.disable(),
这是简单的情况,对于稍复杂的情况,比如后一个例子,可以添加另外的接口,而不是用重载方法,但内部的实现,可能还是需要重载,但是这就把问题缩小了,起码对使用者来说是隐藏的:
复制代码 代码如下
// com/android/mms/data/contactlist.java public string[] getnumbersforsms(); public string[] getnumbersformms(),
这样一来,对外来讲就是良好的封装。内部实现可能还是需要一个类似这样的私有方法:
复制代码 代码如下
// com/android/mms/data/contactlist.java public string[] getnumbersforsms() { return getnumbers(false); } public string[] getnumbersformms() { return getnumbers(true); } private string[] getnumbers(boolean) { // implementation } 。
但至少把问题缩小化了,也可以加上注释来说明。就不必导致使用者来猜方法的用法和含义了.
最后此篇关于Android开发笔记之:用Enum(枚举类型)取代整数集的应用详解的文章就讲到这里了,如果你想了解更多关于Android开发笔记之:用Enum(枚举类型)取代整数集的应用详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是一名优秀的程序员,十分优秀!