亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android開發筆記之:用Enum(枚舉類型)取代整數集的應用詳解

2020-04-11 12:22:55
字體:
來源:轉載
供稿:網友
在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
}

但至少把問題縮小化了,也可以加上注釋來說明。就不必導致使用者來猜方法的用法和含義了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品在线免费观看视频| 日本精品免费观看| 国产精品一区二区三区成人| 国产精品美女www爽爽爽视频| 中文字幕综合一区| 欧美激情免费视频| 国产成人精品免高潮在线观看| 日韩精品视频三区| 日韩小视频在线观看| 亚洲无限乱码一二三四麻| 久久久精品999| 亚洲欧美中文字幕在线一区| 国产一区二区在线播放| 最近2019中文字幕一页二页| 久久精品国产96久久久香蕉| 亚洲高清久久久久久| 亚洲欧美日本另类| 国产亚洲a∨片在线观看| 日韩欧美在线免费观看| 色综合久久中文字幕综合网小说| 一本一本久久a久久精品牛牛影视| 亚洲第五色综合网| 亚洲精品v欧美精品v日韩精品| 欧美日韩福利视频| 日韩精品视频在线观看网址| 国产亚洲欧美日韩美女| 欧美www视频在线观看| 欧美激情精品久久久久久黑人| 国产精品入口日韩视频大尺度| 成人中心免费视频| 黄色精品一区二区| 日韩精品免费综合视频在线播放| 国产综合福利在线| 中文字幕日韩av综合精品| 国产精品精品国产| 亚洲福利视频二区| 国产精品9999| 在线看欧美日韩| 亚洲精品视频免费在线观看| 97久久久久久| 日韩欧美国产免费播放| 国产精品免费一区二区三区都可以| 亚洲一区av在线播放| 国内伊人久久久久久网站视频| 欧美视频在线观看 亚洲欧| 久久久久久久爱| 热久久免费视频精品| 久久99热精品这里久久精品| 668精品在线视频| 精品久久中文字幕| 日韩精品视频在线免费观看| 在线性视频日韩欧美| 国产欧美婷婷中文| 精品亚洲精品福利线在观看| 欧美人在线视频| 国产suv精品一区二区| 成人午夜激情免费视频| 久久久99久久精品女同性| 国产视频久久久久| 久久露脸国产精品| 日韩中文字幕国产精品| 亚洲第一区中文99精品| 久久免费视频在线| 日韩最新在线视频| 色一情一乱一区二区| 精品国产一区二区三区四区在线观看| 国产精品海角社区在线观看| 伊人久久综合97精品| 中文字幕欧美亚洲| 日本成人激情视频| 日韩精品视频在线观看免费| 亚洲国产精彩中文乱码av在线播放| 国精产品一区一区三区有限在线| 国产成人在线播放| 欧美激情伊人电影| 美日韩精品视频免费看| 欧美日韩在线影院| 成人免费网站在线观看| 日韩av在线网站| 久久男人av资源网站| 久久综合电影一区| 成人在线小视频| 国产做受69高潮| 亚洲黄一区二区| 一区二区三区视频观看| 国产成人亚洲综合| 最近2019中文免费高清视频观看www99| 亚洲午夜激情免费视频| 欧美午夜www高清视频| 国产免费一区二区三区在线观看| 日本亚洲精品在线观看| 成人在线激情视频| 国产精品视频久久久久| 欧美专区日韩视频| 欧美国产激情18| 亚洲新中文字幕| 国产欧美日韩最新| 亚洲品质视频自拍网| 欧美视频精品一区| 亚洲国产小视频| 992tv成人免费影院| 国产精品久久一区主播| 欧美做受高潮1| 亚洲成人黄色网址| 亚洲人成网站777色婷婷| 91欧美日韩一区| 欧美精品电影在线| 成人久久久久久久| 欧美激情伊人电影| 日韩欧美在线网址| 国产精品一区电影| 在线日韩欧美视频| 国产精品88a∨| 国产精品久久久久福利| 亚洲奶大毛多的老太婆| 91在线高清视频| 亚洲成人精品av| 国产成人一区二区三区小说| 欧美国产日产韩国视频| 日本午夜精品理论片a级appf发布| 中文字幕精品久久久久| 久久久爽爽爽美女图片| 亚洲天堂网站在线观看视频| 欧美日韩国产丝袜另类| 色哟哟入口国产精品| 国产日韩欧美电影在线观看| 在线观看久久av| 国产91成人在在线播放| 亚洲美女动态图120秒| 97国产精品视频人人做人人爱| 91精品国产91| 亚洲女人初尝黑人巨大| 中文字幕欧美精品在线| 国产精品免费一区二区三区都可以| 97视频在线观看播放| 成人伊人精品色xxxx视频| 国色天香2019中文字幕在线观看| 亚洲成人激情小说| 国产精品国产三级国产专播精品人| 国产精品国产三级国产aⅴ9色| 成人免费视频网址| 国产激情视频一区| 日韩av手机在线看| 亚洲黄色av网站| 欧美日韩福利视频| 91精品综合视频| 91爱爱小视频k| 久久久久久国产免费| 九九热精品在线| 57pao精品| 久久久久久91| 国精产品一区一区三区有限在线| 亚洲精品国产综合区久久久久久久| 欧美亚洲日本网站| 热99精品里视频精品| 亚洲第一区第二区| 欧美亚洲视频在线看网址| 国产精品久久久av久久久| 久久久久久久久亚洲| 国产精品久久久久久久av大片| 欧美高清在线播放| 亚洲免费高清视频| 中文字幕日韩综合av| 中文字幕亚洲综合久久筱田步美|