1. 程式人生 > >Android開發入門(一)——基本語法

Android開發入門(一)——基本語法

參考資料:《Android系統下Java程式設計詳解》
本文摘錄了該書的一些知識點,適合有面向物件程式設計基礎的開發者。

第1章 Android基本概念
1 Android應用程式框架
每個應用程式其實是一組服務和系統,包括以下內容:
① 檢視(View):豐富的、可擴充套件的檢視集合,用來構建應用程式。包括列表(Lists)、網格(grids)、文字框(Textboxs)、按鈕(Buttons),甚至是可嵌入的網頁瀏覽器。
② 內容提供器(Content Providers):使應用程式可以訪問其他應用程式(如通訊錄)的資料,或共享自己的資料。
③ 資源管理器(Resource Manager):提供對於非程式碼資源的訪問,如本地化字串、圖形和佈局檔案。
④ 訊息管理器(Notification Manager):使得應用程式能夠在狀態列顯示自定義的提示資訊。
⑤ 活動管理器(Activity Manager):管理應用程式的宣告週期,並提供常用的導航回退功能。

2 一個標準的Android程式包括:
Activity:Activity是在Android應用開發中最頻繁、最基本的模組。在Android中,Activity類中主要是與介面資源相關聯。Android系統會自動記錄從首頁到其他頁面的所有跳轉記錄並自動將以前的Activity壓入系統堆疊,使用者可以通過程式設計的方式刪除歷史堆疊中的Activity Instance。
Broadcast Intent ReceiverIntent為不同的Activity之間進行跳轉提供了機制,比如當從A Activity跳轉到B Activity,使用Intent實現如下:

Intent in
=new Intent(A.this, B.class); startActivity(in);

BroadcastReceiver還為各種不同的Android應用程式間進行程序間通訊提供了可能。
ServiceService是一個沒有使用者介面的在後臺執行執行耗時操作的應用元件。使用者可以通過startService(Intent Service)啟動一個Service,也可以偶同過Context.bindService來繫結一個Service。
Content ProviderContent Provider提供了應用程式之間的資料交換機制,一個應用程式通過實現一個Content Provider的抽象介面將自己的資料暴露出區,並且隱蔽了具體的資料儲存實現。

第2章 面向物件程式設計初步
1 類包括:
屬性:用來描述物件的資料元素稱為物件的屬性(也稱為資料/狀態)
方法:對物件的屬性進行的操作稱為物件的方法(也稱為行為/操作)

2 構造器(構造方法):
在Java程式中,每個類必須至少有一個構造器。
利用構造器可以產生一個類的例項,並且提供了一個地方用來定義建立類的例項時都需要執行的初始化程式碼。它和類中的方法很類似,可以將構造器看作一個特殊的方法。
構造器和普通方法的區別
①修飾符:可以有訪問修飾符(public,protected,private),不同的是,構造器不可以有非訪問性質的修飾(abstract,final,native,static或者synchronized)。
②返回值:方法可以返回任何型別的返回值或者沒有返回值,構造器沒有返回值也不需要void。
③命名:構造器和類使用相同的名字

public class Food
{
    private String food_name;
    public Food(String name)
    {
        this.food_name=name;

    }
}

Food myDinner = new Food("pizza");

3 物件的建立和使用
一個物件的宣告實際上只是對該類的引用,需要使用new+構造器建立物件,此時儲存器會給此物件相應的儲存空間。當物件被成功建立後,可以使用“物件名.物件成員”的方式訪問物件成員。

4 Java原始檔結構
① package語句:為了避免類名的重複,使用“包”。Sun建議使用公司Internet域名倒寫來當作包名。package語句只能有0個或1個,必須放在檔案開始
比如目錄cn\con\farsight中的包:

package cn.com.farsight;

② import語句:import語句應該出現在package語句之後(如果有的話),類的定義之前。import語句可以有很多個。
例如:

import cn.com.farsight.college.Student;

Java編譯器預設所有的Java程式引入了JDK的java.lang包中所有的類。

第3章 識別符號、關鍵字與資料型別
1 Java註釋的規則(略,等需要寫文件時補充)

2 成員變數的三種初始化方式:
在宣告時初始化;
在類的構造方法或其他方法中動態初始化;
預設初始化值。

3 值傳遞和引用傳遞:
在Java裡只有基本型別和按照下面這種定義方式的String是按值傳遞,其他的都是按引用傳遞。就是直接使用雙引號定義字串的方式:String str="This is Java.";

第5章 陣列
1 一維陣列的宣告:
資料型別[] 陣列名 或者 資料型別 陣列名[]
這種方式只是宣告陣列變數,沒有建立真正的陣列。

2 一維陣列的建立:
通過new操作符來顯式建立一個數組:

type[] arr_name;
arr_name=new type[length];

示例:

int[] a;
a=new int[10];

獲取陣列長度:陣列名.length

3 初始化

int k[]=new int[5];
k[]={1,3,5,7,9};
String s;
s=new String[]{"abc","cde","efg"};

4 簡單資料型別陣列的記憶體空間
Java在記憶體分配時會涉及以下區域:
暫存器:在程式中無法控制。
:存放基本型別和物件的引用,但物件本身不存放在棧中,而是存放在中。
:存放用new產生的資料。
靜態域:存放在物件中用static定義的靜態成員
常量池:存放常量。
非RAM儲存:硬碟等永久儲存空間。
這裡寫圖片描述

陣列複製:b=a引用堆中同一塊記憶體空間
這裡寫圖片描述

5 多維陣列的建立
正確的建立方式:

boolean[][] b=new boolean[10][3];
int[][] a=new int[5][];

錯誤的建立方式:

int[][] a=nwe int[][5];

第6章 面向物件程式設計進階
1 繼承:用extends進行類的繼承,後面緊跟父類的類名。
在Java中,一個類只能從一個父類繼承,而不能從多個類中繼承。
在java.lang包中有一個Object類,這個類是所有類的頂級父類。
例如:
父類Card:

public class Card
{
    String name;
    String sex;
    String tele;
    public void setName(String theName){...}
    public String getName(){...}
    ...
}

子類friendCard:

public class friendCard extends Card
{
    String address;
    public void setAddress(String theAddress){...}
    public String getAddress(){...}
    ...
}

2 訪問控制
這裡寫圖片描述

3 super關鍵字
用於引用父類的成員,如屬性,方法或者是構造器。
呼叫父類構造器:

public class FriendCard extends Card
{
    public FriendCard(String friendName)
    {
        super(friendNme);
    }
    //其他程式碼
}

父類必須自己負責初始化自己的狀態而不是讓子類來做。因此,如果子類的構造器中沒有顯式地呼叫父類的構造器,也沒有在構造器中呼叫過載的其他構造器,則系統會預設呼叫父類無引數的構造器。所以父類必須定義無引數的預設構造器,否則編譯器將會報錯。
呼叫父類的屬性和方法:

super.屬性
super.方法()

必須是那些protected或者public的屬性或方法。
super用於呼叫父類中的方法主要用於在子類中定義了與父類同名的屬性,或進行了方法的覆蓋,而又要在子類中訪問父類中的同名屬性或覆蓋前的方法的時候。

4 this關鍵字
this代表其所在方法的當前物件,包括:
構造器中指該構造器所建立的新物件;
方法中呼叫該方法的物件;
在類本身的方法或構造器中引用該類的例項變數和方法。
也可以用this在構造器中呼叫構造器,例如:

public class Card
{
    String name;
    String sex;
    String tele;
    public Card()
    {
        System.out.println("Card()被呼叫");
    }
    public Card(String theName)
    {
        this(); //呼叫前面的構造器
        this.name=theName;
        System.out.println("Card(String theName)被呼叫");
    }
    //其他程式碼
}

static的含義:
static方法沒有this的靜態方法,不可以通過this來呼叫靜態方法。在static方法內部不能呼叫非靜態方法,可以在沒有建立任何物件的時候通過類本身來呼叫static方法,這也是static方法的主要用途

5 方法的覆蓋於過載
子類繼承父類,對父類的方法進行改造,是覆蓋。
在一個類中,如果有多個方法具有相同的名稱,而有不同的引數,稱為方法的過載。

6 ==和equals
用法:if(a==b) if(a.equals(b))
比較簡單型別資料(如int):一定要用==進行比較
比較兩個引用變數物件的值是否相等(如String):用equals進行比較
比較兩個引用變數物件是否指向同一個物件:用==比較
對自定義的類:預設情況下equals方法在比較的兩者指向同一個物件時返回true,所以要視情況覆蓋Object或者父類中的equals方法。

7 物件初始化的過程
① 設定例項變數的值為預設值,不同的資料型別有不同的初始值
② 呼叫類的構造器(但是還沒有執行構造方法體),繫結構造器引數
③ 如果構造器中有this()呼叫,則根據this()呼叫的引數呼叫相應的過載構造器,然後轉到步驟⑤,否則轉到步驟④
④ 除了java.lang.Object類外,呼叫父類中的初始化塊初始化父類的屬性,然後呼叫父類構造器,如果在構造器中有super()呼叫,則根據super()中的引數呼叫父類中相應的構造器
⑤ 使用初始化程式和初始化塊初始化成員
⑥ 執行構造器方法體中的其他語句
不管用哪個構造器建立物件,初始化塊都會被首先執行,然後才構造器的主體部分。

8 封裝類
Java的8種基本資料型別不支援面向物件的程式設計機制,有時會帶來不便,為了解決此類問題,Java語言引入了封裝類的概念,在JDK中針對各種基本資料型別分別定義相應的引用型別,並稱之為封裝類
所有的封裝類物件都可以向各自的構造器傳入一個簡單型別資料來構造:

boolean b=true;
Boolean B=new Boolean(b);

byte by='42';
Byte by=new Byte(by);

int i=123;
Integer I=new Integer(i);

封裝在封裝類中的值,可以通過各自的xxxValue()方法來轉換成簡單型別。

自動裝箱:Integer iObject=100;
自動拆箱:int i=new Integer(100);

在Java中,為了節省建立物件的時間和空間,對於一些常用的物件,會將它在記憶體中快取起來。比如String物件,當直接用String s="str"產生物件時,如果記憶體中已經存在一個使用這種方式產生的字串物件,那麼就不會再新鍵物件,而是直接使用已經存在的那個String物件。實際上,對於如下範圍內的簡單資料型別:
boolean型別的值
所有byte型別的值
在-128和127之間的short型別的值
在-128和127之間的int型別的值
在\u0000~\u007F之間的char型別的值
使用自動裝箱轉換成相關封裝型別物件的時候,行為也和String類似。

public class TestAutoBoxing
{
    public static void main(String[] args)
    {
        Integer t1=new Integer(127);
        Integer t2=new Integer(127);
        System.out.println("t1==t2?"+(t1==t2)) //false
        Integer t3=127;
        Integer t4=127;
        System.out.println("t3==t4?"+(t3==t4)) //true
        Integer t5=128;
        Integer t6=128;
        System.out.println("t5==t6?"+(t5==t6)) //false
    }
}

第7章 高階類特性
1 static關鍵字
通常我們建立一個類時,是在描述這個類的外觀與行為。只有用new建立類的物件,資料儲存空間才被分配,其方法才供外界呼叫。但是有如下兩種情形:第一種是只想為特定域分配單一的儲存空間,不考慮究竟建立多少物件,甚至根本不用建立任何物件;另一種是,希望某個方法不與包含它的類的任何物件關聯在一起,也就是說即使沒有建立物件,也可以呼叫這個方法。通過static關鍵字可以滿足這方面的需要
使用時,在宣告類的成員如方法、屬性乃至自由程式碼塊前面加上“static”這個修飾符。
在Java中,static最常用在Java應用程式入口方法main()前面,用於修飾main()方法,表示main()方法是一個類方法。我們在指向一個應用程式的時候,解析器會尋找這個main()方法,之所以將它設定為類方法,是因為在呼叫這個main()方法之前,還沒有任何物件存在,所以如果不將它設定為類相關的,則沒有辦法得到任何物件,也就無法呼叫main()方法。
引用static變數時:可以通過物件定位變數,也可以通過類名直接引用。

public class StaticTest
{
    static int i=27;
    public static void main(String args[])
    {
        StaticTest st1=new StaticTest();
        StaticTest st2=new StaticTest();
        System.out.println(st1.i+st2.i);//通過物件定位變數
    }
}
StaticTest.i++; //通過類名直接引用

靜態方法只能呼叫類中的靜態成員。

2 final關鍵字
表示它修飾的類、方法或變數不可被改變。
如果不是引用型別的變數,表示值不能改變

final int CONST_VAR=30;

如果是引用型別的變數,表示不能改變這個變數的引用

final Aclass aClass=new Aclass();

一個既是static又是final的域只佔據一段不能改變的儲存空間。
final方法:final關鍵字可以將方法鎖定,以防繼承類修改它的含義,確保在繼承中使方法的行為保持不變,並且不會被覆蓋。
例如:
父類:

public class A
{
    public final void methodA()
    {...}
    //...
}

子類:

public class B extends A
{
    public void methodA() //報錯
    //如果A中的methodA是private,則這樣做不會報錯,因為這樣B本來就不能覆蓋A的方法
    {...}
}

final類:如果將final關鍵字放在類的定義之前,則將這個類整體定義為final。這樣的類不可以被繼承。final類中的方法都隱式指定為final,在final類中可以給方法新增final修飾詞,但是這沒意義。

3 抽象類
包含抽象方法的類叫做抽象類,抽象類不能被例項化。
在類名前加abstract關鍵字,就可以將一個類定義為抽象類。在抽象類中定義抽象方法是在方法返回值型別前加上關鍵字abstract。抽象方法只需要宣告,不需要實現。

public abstract class IconShape //抽象類
{
    public abstract double iconArea();//抽象方法
}

子類繼承抽象類時,語法和繼承普通父類相同。
子類必須覆蓋所有抽象方法才能被例項化,否則這個子類還是抽象類。
在以下一個條件成立時,類必須定義為抽象類:
① 類中至少有一個抽象方法;
② 類繼承了父類中的抽象方法,但是至少有一個抽象方法沒有實現;
③ 類實現了某個介面,但沒有全部實現介面中的方法。
區分沒有實現的方法和空方法:

public int methodA();//沒有實現的方法,可以用abstract修飾
public int methodB()//空方法,不能用abstract修飾
{}

4 介面
介面是方法宣告和常量值定義的集合。在介面中,沒有提供任何具體的實現。一個介面可以理解為:所有實現了該特定介面的類都應該長這樣。
一個類可以實現多個介面。
定義介面不用class,用interface。介面中可以定義常量但是不能有變數。介面的成員屬性都會被自動加上public、static和final,而對於介面中的方法,也會自動將它們設定為public。介面中的方法只需要宣告,不需要方法體, 也不需要加上關鍵字abstract來將它宣告為抽象方法。

public interface ScreenBrightness
{
    public int DEFAULT_BRIGHTNESS=10;
    //自動加上public static final
    void brightUp();
    void brightDown();
}

實現介面要用implements,一個類只能繼承一個父類,並且可以同時實現一個或多個介面,多個介面之間用“,”來分隔開,通過介面可以模擬實現多繼承。
一個實現了介面的類必須實現介面的所有方法,或者將沒有實現的方法定義為抽象的方法,此時類也必須為抽象類。

public class MobileSet implements ScreenBrightness,Volume
//實現兩個介面,ScreenBrightnessVolumn
{
 //實現的內容
}

介面中的方法預設是public的,所以類在實現介面方法時一定要用public來修飾
介面也可以從父介面中派生,介面的繼承也用extends關鍵字。一個介面可以繼承多個介面。

public interface MobileSet extends ScreenBrightness,Volumn
{
    void showData();
    //...
}

這裡寫圖片描述

5 多型
在Java中,物件變數是多型的,一個型別為Aclass的變數既可以指向型別為Aclass的物件,又可以指向Aclas的任何子類的物件。實際上多臺的作用是消除型別之間的耦合關係。
比如Aclass派生了一個子類Bclass:

Aclass a=new Bclass();

如果一個引用型別變數宣告為父類的型別,但實際引用的是子類的物件,那麼該變數就不能在訪問子類中新增的屬性和方法。
綜上,引用變數的宣告型別和其實際引用物件的型別可能不一致。可以用instanceof操作符鑑別一個物件真正的型別。 它返回true或者false。
原本是子類型別的物件被宣告為父類型別時,可以使用強制轉換的方式回覆其本來面目。

pulic void getNumber(Card c)
{
    if(c instanceof FriendCard)
    {
        FriendCard fc=(FriendCard)c; //強制轉換
    }
    if(c instanceof ColleagueCard)
    {
        ColleagueCard cc=(ColleagueCard)c;
    }
}

綜上,父類物件和子類物件的轉換需要注意以下原則:
① 子類物件可以被視為父類的一個物件;
② 父類物件不能當成某一個子類的物件;
③ 如果一個方法的形參定義的是父類物件,那麼呼叫這個方法時,可以使用子類物件作為形參;
④ 如果父類物件引用指向的實際是一個子類物件,那麼這個父類物件的引用可以用強制型別轉換轉化成子類物件的引用。在轉換之前要用instanceof運算子進行判斷。

6 內部類
也稱為巢狀類,是定義在一個類內部的類,可以是其他類的成員,也可以在一個語句塊中定義。
一個內部類的物件能夠方位建立它的物件的實現,包括私有資料。
對於同一個包中的其他類來說,內部類能夠隱藏起來。
匿名內部類可以方便地用在回撥方法中,典型應用時圖形程式設計中的事件處理。
可以將一個內部類定義成一個靜態內部類,只要在內部類定義前加static即可。

public class Outer
{
    private int a=5;
    public class Inner
    {
        private int i=1;
        public void innerMethod()
        {
            System.out.println("a="+a+",i="+i);
        }
    }
}
public void testTheInner()
{
    Inner i=new Inner();
    i.innerMethod();
}

例項化內部類必須首先有一個外部類例項存在,然後通過外部類例項來例項化內部類。

Outer.inner in=new Outer().new Inner();

如果內部類是static的,也可以用以下方法:

Outer.inner in=new Outer().Inner();

但是,非static的內部類的成員不能宣告為static型別。只有在頂層類或者static的內部類中才能宣告static成員。
內部類可以用protected或private修飾,以限制在它的外部類以外的地方對它訪問。
Inner類也可以定義在方法內部,或是一個類的自由塊中,此時,內部類是一個區域性內部類,只能在方法體或是自由塊中使用。區域性內部類不能有訪問說明符,因為它不是外部類的一部分,但是它可以訪問當前程式碼塊內的常量以及次外部類的所有成員。在類外不能直接訪問區域性內部類。
匿名內部類可以看作是另一種區域性內部類,它通過匿名類實現介面。如果恰好只要建立一個區域性內部類的物件,可以使用匿名內部類(肯定存在於一個表示式中)。

public class AnInnerTest
{
    interface AnInfc //定義一個介面
    {
        public void printInfo();
    }
    public static void main(String[] args)
    {
        AnInnerTest a=new AnInnerTest();
        Aninfc af=a.testAn();
        af.printInfo();
    }
    public AnInfc testAn()//AnInfc為介面,此處返回該介面的一個實現類的例項
    {
        return new AnInfc()
        {
            public void printInfo()
            {
                System.out.println("anonymous class")
            }
        }
    }
}

滿足下面的條件使用匿名內部類比較合適:
① 只用到類的一個例項;
② 類在定以後馬上用到;
③ 類非常小;
④ 給類命名不會導致你的程式碼更容易理解。
使用匿名內部類的原則:
① 不能有構造方法;
② 不能定義任何靜態成員,方法和類;
③ 不能是public,protected,private,static;
④ 只能建立匿名內部類的一個例項;
⑤ 一個匿名內部類一定是在一個new後面,用其隱含實現一個介面或實現一個類;
⑥ 區域性內部類的所有限制都對匿名內部類生效。

7 修飾符的適用範圍
這裡寫圖片描述