2015年6月11日 星期四

【Android】Android Studio中NDK開發



這幾可以參考

http://www.race604.com/android-studio-with-ndk/

http://www.cnblogs.com/SamFang/p/4179458.html

http://www.it165.net/pro/html/201212/4433.html

http://www.cnblogs.com/yaozhongxiao/archive/2012/03/06/2382225.html

http://www.metsky.com/archives/614.html

2015年6月9日 星期二

【Android】Json 的建立


建立範例

{
    "type": "2",
    "body": {
        "description": [
            {
                "dns1": "140.113.17.5",
                "dns2": "140.113.1.1",
                "static": "1",
                "gateway": "140.113.17.254",
                "netmask": "255.255.255.0",
                "ip": "140.113.17.178"
            },
            {
                "dhcp": "0"
            },
            {
                "pppoe": "0"
            }
        ]
    },
    "deviceId": "BW-9FEFB676A5DC556C18D3D24D9FC334C4"
}


建立function

    /**
     * setWanInfoJson
     * @param responseJson
     */
    public String setWanInfoJson(Context ctx, String deviceId)  {

        JSONObject sendJson = new JSONObject();

        try {

            sendJson.put("type", "2");
            sendJson.put("deviceId", deviceId);


            // 構造三個JSONObject 、一個static, dhcp 和 pppoe物件
            JSONObject staticJson = new JSONObject();
            staticJson.put("static", "1");
            staticJson.put("ip", "140.113.17.178");
            staticJson.put("netmask", "255.255.255.0");
            staticJson.put("gateway", "140.113.17.254");
            staticJson.put("dns1", "140.113.17.5");
            staticJson.put("dns2", "140.113.1.1");

            JSONObject dhcpJson = new JSONObject();
            dhcpJson.put("dhcp", "0");

            JSONObject pppoeJson = new JSONObject();
            pppoeJson.put("pppoe", "0");

            // We add the object to the description Array
            JSONArray descriptionArr = new JSONArray();
            descriptionArr.put(staticJson);
            descriptionArr.put(dhcpJson);
            descriptionArr.put(pppoeJson);

            // We add the descriptionArr to the body object
            JSONObject body = new JSONObject();
            body.put("description", descriptionArr);

            // We add the object to the main object
            sendJson.put("body", body);



        } catch (JSONException e) {

            e.printStackTrace();
        }

        System.out.println("sendJson:" + sendJson.toString());

        return sendJson.toString();

    }




忘記某些資訊, 可參考

http://stackoverflow.com/questions/18983185/how-to-create-correct-jsonarray-in-java-using-jsonobject

https://code.google.com/p/json-simple/wiki/DecodingExamples#Example_1_-_Convenient_way:_Use_JSONValue

2015年6月8日 星期一

【Android】Google Analytics v4


開發文件
https://developers.google.com/analytics/devguides/collection/android/v4/#setup-overview


AndroidManifest.xml 需要加入下面那個授權
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
不需要使用Application,也可以使用
最重要的就是取得Tracker ,可以設到靜態變數裡,一直重複使用。


GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);

Tracker mTracker = analytics.newTracker(PROPERTY_ID);

PROPERTY_ID 指的是追蹤編號
 應該長的像UA-18208XX-XX

主要有兩個程式要寫。
一個是追蹤畫面(某個Activity),一個是追蹤事件(某個動作,如click)
追蹤畫面,就拿Tracker寫以下的程式



mTracker.setScreenName("myScreen");
// Send a screen view.
mTracker.send(new HitBuilders.AppViewBuilder().build());

追蹤事件,則如下
// Build and send an Event.
mTracker.send(new HitBuilders.EventBuilder()
        .setCategory("Home")
        .setAction("click")
        .setLabel("AboutUs")
        .setValue(0)
        .build());

再到查詢結果,看看有沒有資料,選擇即時,選畫面,或事件,選擇畫面瀏覽量(近30分鐘)

https://www.google.com/analytics/web/



 

2015年6月4日 星期四

2015年6月3日 星期三

【JAVA】switch-case注意事项


在網上看到有一篇寫得很清楚, 留著記憶

http://blog.csdn.net/yangkai_hudong/article/details/8988420

2015年6月2日 星期二

【Android】Android Studio 之中使用 httpcore 與 httpmime


解決2個問題

1. WARNING: Dependency org.apache.httpcomponents:httpclient:4.3.5 is ignored for debug as it may be conflicting with the internal version provided by Android. In case of problem, please repackage it with jarjar to change the class packages
 
2. Duplicate files copied in APK META-INF/NOTICE 





可在 build.gradle 之中, 加入

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.1.1'
    compile 'com.android.support:support-v4:22.1.1'

    compile files('libs/commons-lang-2.6.jar')     // 記得在 Libs 之中加入相對映的 jar 檔
    compile files('libs/httpcore-4.4.jar')
    compile files('libs/httpmime-4.3.5.jar')
}


android {
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'

    }
}

2015年5月30日 星期六

【JAVA】Hashtable


http://www.cnblogs.com/skywang12345/p/3310887.html

http://www.interinfo.com.tw/edoc/ch3/r_n_d.htm

【JAVA】string equals


哪個比較好?
 
 
        String a = "Compal";
        if(a.equals("Compal"));
        if("Compal".equals(a));
  
寫法一:
常常會遇到NullPointException,因為String a如果是從別處取得的動態值,
那有機會拿到null,這個在編譯時期無法預期的,若要這樣寫,就又要再加上try-catch。

寫法二:
當你a是null時,是不會錯誤的,且不需要加上try-catch,在equals比對也只會回傳false。

結論:
建議使用寫法二。

【JAVA】封裝、繼承、多型


個人覺得寫得很好



作者:蔡學鏞
Welcome to O'Reilly Taiwan!

OO

Java 是物件導向的(object-oriented)語言。物件導向近年來成為顯學,全新的程式語言幾乎都具備物件導向的特色,而舊的程式語言也紛紛在新版本中開始支援物件導向的特色。

所 謂「物件導向的特色」,指的是物件導向的三個機制,三者缺一不可,此三個機制分別為封裝(encapsulation)、繼承 (inheritance)、多型(polymorphism)。我也喜歡把這三個機制稱為三個階段,以突顯出它們之間的次序性:沒有封裝就不可能會有繼 承,沒有繼承就不可能會有多型。為了稱呼上的方便,我們常常將物件導向簡稱為 OO。

有一些程式語言常被誤認為是 OO 的語言,但其實不然。例如:Visual Basic 6 以及更早的版本只支援封裝,不支援繼承和多型,所以不可以被視為 OO 的語言。這種只支援封裝 的語言,只能被稱為 object-based 程式語言。但是 Visual Basic 7(也就是 Visual Basic.NET)開始支援繼承和多型,所以可以被視為 OO 的語言,因此威力大增,語言的複雜度也會大增,因為繼承和多型會帶來許多複雜的特質。

封裝

關於封裝,你可以扮演兩種角色:

‧封裝者:封裝出一個類別(class),以供他人使用。
‧類別使用者:使用別人封裝出來的類別

程 式員都是在這兩種角色之間不斷地轉換:一會兒封裝出一個類別,一會兒使用別人封裝好的類別。 當一個類別使用者顯然比當一個封裝者簡單許多,只要透過 new 這個關鍵字來產生類別的 instance,即可使用。如果欲使用的是 class method/field,甚至連 new 都可以省了。既然當類別使用者比當封裝者來得簡單,我們自然是盡量使用既有的類別, 這樣就可以達到很高的再用性(reusability)。Java 平台提供了數千個已經封裝好的類別,我們可以直接拿來使用, 這可以為我們省下許多時間。這些類別所形成的集合,就稱為 API。

查詢 Java API

J2SE 平台所具備的 API,就稱為 Core API(核心 API)。你可以在你的 Java 2 SDK 路徑下找到 docs/api/index.html,這就是 API 文件,從這裡,你就可以找到每個類別的用法(例如我們在 Hello 程式中使用的 System,就是一個類別)。畫面如下所示:



我 很喜歡把程式設計比喻成設計一個主機板。主機板的設計者不用一切從頭來,因為他們有許多 IC chip(晶片)可以使用(其中有一個 chip 為 CPU)。從市面上的各種 chip 中(SIS、Intel、VIA…), 挑選出各種適合的 chip,再把這些 chip 全都放到主機板上適當的位置固定好,再把這些 chip 的接腳之間互相 連接起來就可以了。這麼一來,設計主機板的工作包含:

1.挑選 chip
2.應用這些 chip 來進行電路佈局(circuit layout)

寫 程式很類似設計主機板,差異在於主機板是硬件,程式是軟件。寫 Java 程式不用一切從頭來,因為我們有許多類別可以使用。從 Java Core API 的類別中, 挑選出各種你需要的類別,把這些類別用在你的程式中,程式中利用 Java 的關鍵字(keyword) 和算符(operator)將這些類別銜接起來就可以了。這麼一來,寫程式的工作包含:

1.挑選適當的類別
2.應用這些類別來完成程式

繼承

既 有的 Java API 已經可以滿足我們大多數時候的需求,但還是有些時候,我們希望有一個類別能提供特定的功能,但是 Java API 不提供這樣的類別。我們通常會找協力廠商(thirty party)購買這樣的類別。有許多軟體公司專門提供類別庫(class library),收納了許多好用的類別,例如繪製統計圖表(chart)的類別、產生報表(report)的類別、複雜科學計算的類別……等。你可以在 WWW 上找到許多這樣的產品。

如果沒有任何廠商提供完全符合你需求的類別,或者你根本不想增加成本購買 third party 的類別(這些類別通常都不單獨出售, 而是許多類別被包在一起成為類別庫,且售價不便宜),那麼你只好自己寫一個這樣的類別。

假設我們現在就有這樣的需求,需要設計一個類別。在下面的程式碼中,我們封裝出一個名為 ClassB 類別:

// code-1
class ClassB
{
    int doThis() {
       // ...
               // ...很多、很多程式碼...
               // ...
   }
    int doThat() {
        // ...
                // ...很多、很多程式碼...
               // ...
   }
}

這時候,你發現有一個叫做 ClassA 的類別,也提供了 doThis() 和 doThat(),其中 ClassA 的 doThis() 完全就是 ClassB 的 doThis() 所需要的功能,但是 ClassA 的 doThat() 卻和 ClassB 的 doThat() 所需要的功能有一些小差異,你希望 ClassB 的 doThat() 傳出值一定是大於等於零的整數。 你可以把 ClassA 拿來運用在 ClassB 中,將 code-1程式改寫如下:
// code-2
class ClassB {
    ClassA a = new ClassA();
    int doThis() {
       return a.doThis();
    }
    int doThat() {
        return Math.abs(a.doThat());
                 // Math.abs() 是取絕對值(正數)的意思
   
}
}

code-2 的版本因為運用 ClassA,所以整個程式比 code-1 更精簡。我們稱 ClassA 被嵌入(embed)到 ClassB 中,ClassB 把 method 遞送給 ClassA 的 method 來處理。

如果 ClassA 除了具有 doThis() 和 doThat() 之外,還具有100 個 method, 分別叫做 method1() method2()、……、method100(),而且這100 個 method 每個都是 ClassB 想要具備的功能,那麼我們的 code-2 程式可以改寫如下:
// code-3
class ClassB {
    ClassA a = new ClassA();
    int doThis() {
        return a.doThis();
   }
    int doThat() {
        return Math.abs(a.doThat());
    }
    int method1() {
        return a.method1();
    }
    int method2() {
        return a.method2();
    }
   // ...一直重複類似的程式碼
   
int method100() {
       return a.method100();
    }
}

這根本就是一場惡夢, 因為我們不斷地把 ClassB 的 methodX() 轉給 ClassA 的 methodX()。這個程式糟透了, 我們應該把它改成下面的版本:
// code-4
class ClassB extends ClassA{
    int doThat() {
        return Math.abs(a.doThat());
    }
}

code-4 的版本用到繼承(inheritance)的技巧。繼承也是封裝的一種,所以語法和封裝很類似,唯一的差異是多了 extends 以及後面的 ClassA。extends 是 Java 的關鍵字,後面接著一個類別的名稱,用來表示繼承的來源。以此例來說,我們稱 ClassA 是 ClassB 的父類別(parent class),或超類別(super class),或基底類別(base class);我們稱 ClassB 是 ClassA 的子類別(child class),或次類別(sub-class),或衍生類別(derived class)。

code-4 的寫法之所以比 code-3 簡潔,是因為 code-4 使用繼承。在 code-4 中,雖然 ClassB 本身只定義了一個 method,也就是 doThat() ,但是 ClassA 中的 method 也會被自動繼承過來。 換句話說,我們可以拿 ClassB 的對象來呼叫 ClassA 中定義的 method,如下例所示:

ClassB b = new ClassB();
b.doThis();
b.method1();

這就是繼承的目的「之一」:達到程式碼的再用性(reusability)。ClassB 輕易地運用了 ClassA 的程式碼。 (繼承的另一個目的是:為多型做準備。)我主張繼承應該被視為一種特殊的封裝,因為繼承只是一種「過程」,繼承的結果仍是封裝,一個全新的封裝。

在繼承的時候,如果子類別定義了和父類別完全相同名稱(包括參數、傳出值、修飾字)的 method,我們就說子類別的此 method 推翻(override)了父類別的同名 method。從 code-4 的例子來看,ClassB 的 doThat() 推翻了 ClassA 的 doThat()。

請注意,在繼承的時候,不只 instance method 會被繼承,連 instance field、class field、class method 都會被繼承。

如果你不希望你所設計出來的類別被其他類別繼承,那麼你可以利用 final 來修飾此 class,如下所示:
// code-5
final class MyClass {
    // ...
}

如果你不希望你所設計出來的某個 method 被子類別推翻(override),那麼你可以利用 final 來修飾此 method,如下所示:
// code-6
class MyClass {
    final int myMethod() {
        // ...
    }
}

java.lang.Object

在 Java 中,每個類別都會有父類別。如果你沒有用 extends 關鍵字來指定父類別,那麼它的父類別就是 java.lang.Object, 例如:code-6 的程式其實等同於下面的程式:
// code-7
class MyClass extends java.lang.Object {
    final int myMethod() {
        // ...
    }
}

java.lang.Object 是一個很特殊的類別,因為:

‧它是唯一沒有父類別的類別
‧Java 所有的類別都直接或間接地繼承了 java.lang.Object

請牢記下面三點:

‧每個類別(java.lang.Object 除外)一定有一個父類別
‧一個父類別可以有許多子類別
‧所有的類別都源自於 java.lang.Object

繼承的使用時機

認清繼承的使用時機很重要。如果存在某個類別(比方說 ClassA), 其功能和我們的需求「差不多」,但有一些不同之處,那麼我們就「可以」 使用繼承的方式來設計一個類別(比方說 ClassB),以將 Class 的功能抄襲過來, 並進行「擴充」或「修改」。

「可以」使用繼承,不代表「一定要」使用繼承。 繼承也不見得全然都只有好處,沒有任何缺點。有些時候,兩個 class 之間的關係,用 association 的關係比用繼承的關係好。也就是說, 有些時候我們不用 code-4 的版本,反而使用 code-2 的版本,因為這樣做有下列的好處:

‧在 code-2 中,a 可以被其他類使用;但在 code-4 中,則無法這麼做。
‧在 code-2 中,a 可以隨時被設定成別的物件;但在 code-4 中,則無法改變。
‧ClassB 可以不提供部份的 method,例如:code-2 就不提供 method1()~method100();但在 ode-4 中, ClassB 無法決定哪些 method/field 要繼承或不繼承。

特別注意:繼承一定需要「擴充」或「修改」,如果不擴充也不修改,這樣的繼承就毫無意義可言。所謂的擴充,指的是:子類別新定義父類別沒有的 method,以擴充功能;所謂的修改,指的是子類別提供 method 推翻父類別的同名 method。

多型

關於多型(Polymorphism),一言以蔽之:「當某變數的實際型態(actual type)和形式型態(formal type)不一致時,呼叫此變數的 method,一定會呼叫到「正確」的版本, 也就是實際型態的版本。

從這句話,我們可以思索下面的問題:

為什麼實際型態和形式型態會不一致?
多型帶來時麼好處?
如果你能夠瞭解這兩點,你就能徹底瞭解多型。

學會多型之後,你不可以對多型有「錯誤的期待」。千萬要小心下面這兩點:

1.多型的機制只用在 method 上,不用在 field 上。
2.多型的機制只用在 instance method上,不用在 class method 上。

在本文章中,我也會對上述兩點提出明確的解釋。

為什麼實際型態和形式型態會不一致?

請看下面的例子:

int a = 3;
long b = a;

因為 a 和 b 是基本型態(primitive type),而非 reference 型態,所以 a 的值會被複製一份到 b。在複製的過程中,a 的值原本是 32 bit 的 int,會被自動地擴充成(widen)64 bit 的 long,再指定(assign)給 b。正因為有擴充和複製,所以對於 b 來說,其實際型態(值的型態)和形式型態(宣告時的型態)都一樣是 long。

所有屬於基本型態的變數都類似如此,在設定其值的時候,會經歷擴充(或縮減)以及複製,製造出實際型態和形式型態一致的值。

但是 reference 型態可就不一樣了。請看下面的例子:
class ClassA {
  void method1() {
    System.out.println("method1() in ClassA");
 }
void method2() {
    System.out.println("method2() in ClassA");
 }
}
class ClassB extends ClassA {
  void method1() {
    System.out.println("method1() in ClassB");
  }
  void method3() {
    System.out.println("method3() in ClassB");
  }
}
public class ClassC {
  public static void main(String[] args) {
    ClassA a = new ClassB();
    a.method1();   // method1() in ClassB
    a.method2();  // method2() in ClassA
    a.method3();  // compile-time error
  }
}

對於 reference 型態來說,使用指定算符(assignment operator)時, 只有記憶體位址會被複製,對象本身不會被複製,所以實際值並不會受到變寬或變窄的破壞。

我們在 ClassC 中,產生一個 ClassB 的對象,並將它設定給 a。但是 a 被宣告成 ClassA 型態,所以 a 的實際型態(ClassB)和形式型態(ClassA)並不一致。 在這樣的情況下,呼叫 a 的 method1() 會 執行到哪一個版本?實際型態的版本或形式型態的版本?正確答案是實際型態的版本。這就是多型!

讓我們再看一次文章一開始對多型所下的定義:「當某變數的實際型態和形式型態不一致時,呼叫此變數的 method,一定會呼叫到正確的版本,也就是實際型態的版本」。現在,你是不是比較能體會了。

如果我們嘗試著呼叫 a 的 method2() 時,結果會呼叫到 ClassA 的 method2(),這是因為 ClassB 沒有定義 method2(),其 method2() 乃是繼承 ClassA 而來的。

如果我們嘗試著呼叫 a 的 method3() 時,則無法通過編譯。 這是因為 Java 是強制型態檢查的語言(strongly-typed language),這意味著 編譯時會檢查形式型態是否有提供該 method。a 的形式型態是 ClassA,不提供 method3(),雖然 a 的實際型態有提供 method3(),但編譯只管形式型態, 可不管實際型態,所以形式型態也稱為編譯期型態(compile-time type), 實際型態也稱為執行期型態(runtime type)。

或許你會覺得「ClassA a = new ClassB();」的寫法很怪,為什麼要把 ClassB 的物件宣告成 ClassA 型態?的確,通常我們不會這麼做,但形式型態和實際型態互異的情況卻往往是在不知不覺中發生,請看下面的例子:
class ClassD {
  static void method4(ClassA a) {
    // a 的形式型態是 ClassA,實際型態則不一定是 ClassA
  a.method1();   //呼叫實際型態的 method1();
  }
}
public classE {
  public static void main(String[] args) {
    ClassB b = new ClassB();
    ClassD.method4(b);
  // ClassD.method4() 需要一個 ClassA的參數,
                 // 因為 ClassB 繼承自 ClassA,
                 // 所以 ClassB 相容於 ClassA,
                 // 也因此我們可以傳入 ClassB 的對象當參數
  }
}

因為我們傳進 ClassD.method4() 的參數其實際型態是 ClassB,但是在 method4() 的定義中將它宣告為 ClassA,造成了形式型態和實際型態不一致。這類似於「ClassA a = new ClassB();」的寫法,只不過一切都是在暗中進行,從程式上來看並不明顯。大部分的多型,都是導因於此。

從上面的例子來加以歸納,我們可以知道多型的發生必須是:

有直接或間接繼承關係的兩個類別,子類別的 method 將父類別的 method 予以override。
實際型態為子類別的物件,被當成父類別來使用,呼叫其 overrided method。

多型帶來什麼好處?

多型是建立在繼承的基礎之上的,沒有繼承,就不會有多型。繼承的目的有兩種:

‧繼承程式碼:達到程式碼再用性(reuse)
‧繼承介面(interface)。達到介面再用性(reuse),為多型預作準備

更明白地說:多型是仰賴介面的繼承。至於程式碼的繼承,完全無涉於多型。

讓我打個比喻:電腦主機板(Main Board)上面能夠插上 Intel 的 CPU,也能插上 AMD 的 CPU,一切運作順利,那是因為 Intel 的 CPU 和 AMD 的 CPU 都遵守該主機板要求的介面(interface)。 這麼一來,任何廠商只要能符合此介面,就能和該主機板搭配使用,主機板不需要做出任何修改。

同樣地,ClassD 的 method4() 需要 ClassA 的介面,不管是 ClassA 的 instance 和 ClassB 的 instance 都能符合這樣的要求(ClassB 繼承了 ClassA 的介面), 所以都能當作 method4() 的參數,和 ClassD.method4() 合作無間。任何對象只要能符合 ClassA 的介面,就能和 ClassD 合作無間,ClassD 的程式碼不需要進行任何修改。 多型的機制,讓程式具備了動態的擴充性。

Reflection 也可以讓程式具備動態的擴充性,甚至比多型更動態,所以有些場合可以使用 reflection 來取代多型,但 reflection 通常效率較差,而且有的語言不提供 Reflection 機制。 Java 早在 1.1 以後就開始支援 Reflection API 了 ,而 Java1.4 版的 Reflection API 速度也大幅地提升了。 如果你對於 Java Reflection API 感興趣的話,可以參考 java.lang.reflect.*。

多型的機制只用在 method 上,不用在 field 上

簡單來說,只要符合下兩點,就可能會有多型:

1.有直接或間接繼承關係的兩個類別,子類別的 method 將父類別的 method 予以 override。
2.實際型態為子類別的對象,被當成父類別來使用,呼叫其 overrided method。

請注意:上述兩點指的是 method,而非 field。對於 field 來說,根本沒有多型這一回事。請看下面的例子:
class ClassA {
  String field1 = 'A1';
  String field2 = 'A2';
}

class ClassB extends ClassA {
  String field1 = 'B1';
  String field3 = 'B3';
  }

public class ClassC {
  public static void main(String[] args) {
    ClassA a = new ClassB();
    System.out.println(a.field1());  // "A1"
    System.out.println(a.field2());  // "A2"
    System.out.println(a.field3());  // compile-time error
  }
}

對於 field 來說,形式型態決定了一切,完全和實際型態無關。 雖然 a 的實際型態是 ClassB,但是形式型態是 ClassA,所以 a.field1 得到的結果是”A1”,a.field2 得到的結果是”A2”。

如果子類別提供了和父類別一樣名稱與參數的 method, 我們說子類別的 method 把父類別的同名 method 給 override 了。如果子類 別提供了和父類別一樣名稱的 field,我們說子類別的 field 把父類別的同名 field 給 shadow 了。

針對 method 和 field 的作法居然如此大的不同,這絕對不是 Java 語言的設計者故意想折磨你。事實上,這樣的設計有其巧妙之處。在 Java 的思維中:介面是對象之間溝通的管道,而介面只包含了類別的名稱和 method 的集合。至於 field,則是不屬於介面的一部份。既然如此,而多型又是完全是 依靠介面,所以當然多型會把 field 排除在外。

多型的機制只用在 instance method 上,不用在 class method 上

被 static 修飾的 field/method 是屬於 class field/method。繼承的時候,依然可以繼承這些 static field/method。封裝和繼承的效果可以同時用在 class 或 instance 上。換句話說:封裝不只封裝 instance field/method,也可以封裝 class field/method;繼承不只繼承父類的 instance field/method,也繼承父類別的 class field/method。

但是,切記,多型只能對 instance 產生作用,不能對 class 產生作用,這可以從我對多型的定義看出端倪,定義如下:

當某變數的實際型態和形式型態不一致時,呼叫(invoke)此變數的 method,一定會呼叫到正確的版本,也就是實際型態的版本。

class 是形式型態,沒有實際型態,根本就和多型無關。只有 instance 才可能會造成形式型態和實際型態不一致。

請看下面的例子:
class ClassA {
  static void method1() {
    System.out.println("method1() in ClassA");
 }
     static void method2() {
    System.out.println("method2() in ClassA");
  }
}
class ClassB extends ClassA {
  static void method1() {
     System.out.println("method1() in ClassB");
   }
  static void method3() {
    System.out.println("method3() in ClassB");
   }
}
public class ClassC {
  public static void main(String[] args) {
    ClassA a = new ClassB();
    a.method1();  // method1() in ClassA
    a.method2();  // method2() in ClassA
    a.method3();  // compile-time error
   }
}

因為這裡的 method1()、method2()、method3() 都是 static,所以和多型無關,編譯器直接使用靜態連結(static link),而不會留到執行期才動態地決定真正該呼叫的 method 為何。因為編譯器在編譯期就做必須決定 method, 所以編譯器完全依賴形式型態,這麼一來「a.method1()」等於是「ClassA.method1()」, 「a.method2()」等於是「ClassA.method2()」。

多型的英文是 polymorphism,poly 是「多」的意思,morph 是「型」的意思,這個「型」可做「型態」解。 也就是說,只有當一件事物有多種型態時,才會有的一種機制。


 轉載於 http://andyshyu.blogspot.tw/2009/06/java_11.html

【JAVA】 String、StringBuffer、StringBuilder的差別


1. String
 
String:字符串常量,字符串長度不可變。

2. StringBuffer
 
StringBuffer:字符串變量(Synchronized,即線程安全)。如果要頻繁對字符串內容進行修改,出於效率考慮最好使用StringBuffer,如果想轉成String類型,可以調用StringBuffer的toString()方法。
 
Java.lang.StringBuffer線程安全的可變字符序列。在任意時間點上它都包含某種特定的字符序列,但通過某些方法調用可以改變該序列的長度和內容。可將字符串緩沖區安全地用於多個線程。
 
StringBuffer 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每個方法都能有效地將特定的數據轉換成字符串,然後將該字符串的字符追加或插入到字符串緩沖區中。 append 方法始終將這些字符添加到緩沖區的末端;而 insert 方法則在指定的點添加字符。例如,如果 z 引用一個當前內容是“start”的字符串緩沖區對象,則此方法調用 z.append("le") 會使字符串緩沖區包含“startle”,而 z.insert(4, "le") 將更改字符串緩沖區,使之包含“starlet”。


3. StringBuilder
 
StringBuilder:字符串變量(非線程安全)。
java.lang.StringBuilder是一個可變的字符序列,是 JDK5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩沖區被單個線程使用的時候(這種情況很普遍)。如果可能,建議優先采用該類,因為在大多數實現中,它比 StringBuffer 要快。兩者的方法基本相同。
在大部分情況下,StringBuilder > StringBuffer。


4. 三者區別
 
String 類型和StringBuffer的主要性能區別:String是不可變的對象, 因此在每次對 String 類型進行改變的時候,都會生成一個新的 String 對象,然後將指針指向新的 String 對象,所以經常改變內容的字符串最好不要用 String ,因為每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了以後, JVM 的 GC 就會開始工作,性能就會降低。

使用 StringBuffer 類時,每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象並改變對象引用。所以多數情況下推薦使用 StringBuffer ,特別是字符串對象經常改變的情況下。
在某些特別情況下, String 對象的字符串拼接其實是被 JVM 解釋成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度並不會比 StringBuffer 對象慢,

例如:


  String S1 = “This is only a” + “ simple” + “ test”;
 StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

生成 String S1 對象的速度並不比 StringBuffer慢。其實在 JVM 裏,自動做了如下轉換:
 String S1 = “This is only a” + “ simple” + “test”; 
 
JVM直接把上述語句當作:
 
String S1 = “This is only a simple test”;
 
所以速度很快。但要注意的是,如果拼接的字符串來自另外的String對象的話,JVM就不會自動轉換了,速度也就沒那麼快了,例如:

String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;

這時候,JVM 會規規矩矩的按照原來的方式去做。
在大部分情況下,StringBuffer > String。

5 使用策略
(1)基本原則:如果要操作少量的數據,用String ;單線程操作大量數據,用StringBuilder ;多線程操作大量數據,用StringBuffer。
(2)不要使用String類的"+"來進行頻繁的拼接,因為那樣的性能極差,應該使用StringBuffer或StringBuilder類,這在Java的優化上是一條比較重要的原則。舉個例子:在使用String 的時候,拼接字符串時使用“+”在JVM上形成臨時的StringBuffer對象,同時在每一個字符串上都建立一個對象,拼接了兩個字符串一共需要創建 4個對象!(一個保存結果的String,兩個字符串對象,一個臨時的StringBuffer對象)。而使用StringBuffer的話,只需創建2 個對象!一個StringBuffer對象和保存最後結果的的String對象 。
(3)為了獲得更好的性能,在構造 StirngBuffer 或 StirngBuilder 時應盡可能指定它們的容量。當然,如果你操作的字符串長度不超過 16 個字符就不用了。不指定容量會顯著降低性能。
(4)StringBuilder一般使用在方法內部來完成類似"+"功能,因為是線程不安全的,所以用完以後可以丟棄。StringBuffer主要用在全局變量中。
(5)相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。而在現實的模塊化編程中,負責某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環境中運行,因 此:除非確定系統的瓶頸是在 StringBuffer 上,並且確定你的模塊不會運行在多線程模式下,才可以采用StringBuilder;否則還是用StringBuffer。

資料來源:http://rritw.com/a/JAVAbiancheng/JAVAzonghe/20130702/377964.html

2015年5月28日 星期四

【JAVA】在網站找到 的JAVA面試考題

第一,談談final, finally, finalize的區別。

這三個沒什麼關係。
final是修飾的關鍵字,可修飾類別、方法 和變數。
final class該類別無法被繼承,final method 該方法不能被override,final variable
該變數一經設定後就無法修改。

finally 在例外處理中(try…catch….finally)最後一定會被執行的區塊。

finalize 當 garbage collector發現某物件已經不被任何物件所參考(reference)

會呼叫該物件的finalize(),finalize()內沒有什特別的動作一般會被

OVERRIDE拿來作為資源的釋放。


第二,Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其他類,是否可以implements(實現)interface(介面)?

可以,但不能同時extends和implements。(Anonymous inheritance)

Ex:
new ClassName ([參數列]) { 類別內容 }
new InterfaceName (){ 類別內容 }

第三,Static Nested Class 和 Inner Class的不同,說得越多越好。

Static Nested Class不能直接參考它的封裝類別(enclosing class)中的實
體變數或方法,僅能透過object instance的方式存取。
Inner Class可以直接存取它的封裝類別(enclosing class)中的變數或方法。
inner class中不能定義任何的static成員。


第四,&和&&的區別。

& 位元運算符號 && 邏輯運算符號

第五,HashMap和Hashtable的區別。

Hashtable 是thread safe class,HashMap不是。
HashMap 接受 null, 而 Hashtable 不接受。

第六,Collection 和 Collections的區別。
Collection是Interface,Collections是Class。

第七,什麼時候用assert。

測試驗證時。

第八,GC是什麼? 為什麼要有GC?

garbage collector,由JVM做記憶體管理,開發人員無須考慮這部分。

第九,String s = new String("xyz");創建了幾個String Object?

兩個… 一個是”xyz”另一個是new String(“xyz”)。

第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5) = 12 , Math.round(-11.5) = -11

第十一,short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?

S1 +1會回傳int,int不能指定給short;
S1 += 1 沒錯。

第十二,sleep() 和 wait() 有什麼區別?

Sleep()無法由其他thread喚起,wait()可以。

第十三,Java有沒有goto?

有,屬於沒有被實作的keyword。

第十四,陣列有沒有length()這個方法? String有沒有length()這個方法?

陣列僅有length的屬性,String有。

第十五,Overload和Override的區別。Overloaded的方法是否可以改變
返回值的類型?

Overload發生在同一類別裡,Override發生在繼承關係間。
Overload為靜態連結,Override為動態連結。
可改變返回值的型態,前提是參數也要變,參數相同傳回值不同是
不被允
許的。

第十六,Set裏的元素是不能重複的,那麼用什麼方法來區分重複與否呢?
是用==還是equals()? 它們有何區別?

用equals()。
==是比較refrence variables的內容,equals()是比較物件的內容。


第十七,給我一個你最常見到的runtime exception。
IndexOutOfBoundsException

第十八,error和exception有什麼區別?

Error 通常為不可補救的嚴重的錯誤,由 Java API或
Java virtual machine 自己丟出。

Exception 指較不嚴重的不正常狀況,他底下又定義了許多不同種類的子類別,
其中一類為 RuntimeException,表示 JVM 在執行期間發生的不正常情形。


第十九,List, Set, Map是否繼承自Collection介面?
List和Set是 ,Map不是

第二十,abstract class和interface有什麼區別?

當一個類別裡面包含有一個(含)以上的abstract method該稱類別為abstract class。
但在java中可故意宣告無abstract method的類別為abstract class。
在abstract class中可有屬性(資料成員),也可有已實作的method。

介面中全部都是abstract method並不能有constructor且僅能有
static final的屬性。


第二十一,abstract的method是否可同時是static,是否可同時是native,
是否可同時是synchronized?

不可,abstract method不可包含private, final, static, native,
synchronized
等關鍵字

第二十二,介面是否可繼承介面? 抽象類是否可實現(implements)介面?
抽象類別是否可繼承實體類別(concrete class)?

介面可繼承介面,抽象類別可implements介面,抽象類別可繼承實體類別
但前提是該實體類別要有明確的建構函數。。

第二十三,啟動一個執行緒是用run()還是start()?
start()會啟動一執行緒並呼叫其run()。

第二十四,構造器Constructor是否可被override?

No.

第二十五,是否可以繼承String類?

否,String是final Class。

第二十六,當一個執行緒進入一個物件的一個synchronized方法後,其他執行緒是否可進入此物件的其他方法?

可以。

第二十七,try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的code會不會被執行,什麼時候被執行,在return前還是後?

會在return前執行。

第二十八,程式設計題: 用最有效率的方法算出2乘以8等於幾?

2 <<3

第二十九,兩個物件值相同(x.equals(y) == true),但卻可有不同的
hash code,這句話對不對?

java.lang.Object規範equals()傳回true時,必須擁有一樣的hashcode。
實作還是可以做到不一樣的hashcode。


第三十,當一個物件被當作參數傳遞到一個方法後,此方法可改變這個物件的屬性,
並可返回變化後的結果,那麼這裏到底是值傳遞還是引用傳遞?

Call by reference.

第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

Switch(exp),exp為整數運算式,故僅有int、 short、 char 或者 byte可以作用。

第三十二,程式設計題: 寫一個Singleton出來。

too easy...

619:
public class ClassicSingleton {

private static ClassicSingleton instance = null;

protected ClassicSingleton() {

   // Exists only to defeat instantiation.

}

public static ClassicSingleton getInstance() {

   if(instance == null) {

      instance = new ClassicSingleton();

   }

   return instance;

}

}


From~http://chihhsiang-javaidea.blogspot.com/2007/07/java_29.html


=============

Concrete class:
當class 是 abstract class,所以無法實體化(instantiated),也就是說不能產生一個物件由於我們不能產生一個抽象類別的物件,所以對於非抽象類別,我們一般稱之為實體類別(concrete class)

Polymorphism:
Polymorphism又稱為多型,簡單來說,多型是指子類別繼承父類別時,同時改寫父類別的函式或變數,而我們可以宣告一個屬於父類別的變數,去存取子類別中改寫自父類別的函式或變數,這我們稱之為多型。
舉個生活一點的例子,若有一個父類別是動物,那麼有一個子類別鳥繼承自動物這個類別,當我們看到鳥的時侯,可以說牠是一隻鳥,也可以說牠是一隻動物。同樣的東西,卻有不同的表示型態。


Overloaded methods
are methods with the same name signature but either a different number of parameters or different types in the parameter list. For example 'spinning' a number may mean increase it, 'spinning' an image may mean rotate it by 90 degrees. By defining a method for handling each type of parameter you achieve the effect that you want.

Overridden methods are methods that are redefined within an inherited or subclass. They have the same signature and the subclass definition is used.

Polymorphism is the capability of an action or method to do different things based on the object that it is acting upon. This is the third basic principle of object oriented programming. Overloading and overriding are two types of polymorphism .

【JAVA】File簡單應用



判斷方法

1.boolean canExecute()判斷檔是否可執行
2.boolean canRead()
判斷檔是否可讀
3.boolean canWrite()
判斷檔是否可寫
4.boolean exists()
判斷檔是否存在
5.boolean isDirectory()
6.boolean isFile()
7.boolean isHidden()
8.boolean isAbsolute()
判斷是否是絕對路徑 檔不存在也能判斷

獲取方法

1.String getName()
2.String getPath()
3.String getAbsolutePath()
4.String getParent()//
如果沒有父目錄返回null
5.long lastModified()//
獲取最後一次修改的時間
6.long length()
7.boolean renameTo(File f)
8.File[] liseRoots()//
獲取機器盤符
9.String[] list()
10.String[] list(FilenameFilter filter)


java code


                //以當前路徑來創建一個File物件
                File file = new File(".");
                //直接獲取檔案名,輸出一點
                System.out.println(file.getName());
                //獲取相對路徑的父路徑可能出錯,下面輸出null
                System.out.println(file.getParent());
                //獲取絕對路徑 
                System.out.println(file.getAbsoluteFile());
                //獲取上一級路徑
                System.out.println(file.getAbsoluteFile().getParent());
                //在當前路徑下創建一個暫存檔案
                File tmpFile = File.createTempFile("aaa",".txt",file);
                //指定當JVM退出時刪除該檔
                tmpFile.deleteOnExit();
                //以系統當前時間為檔案名創建一個新檔
                File newFile = new File(System.currentTimeMillis() + "");
                System.out.println("newFile物件是否存在" + newFile.exists());
                //以指定newFile物件來創建一個檔
                newFile.createNewFile();
                //newFile物件來創建一個目錄,因為newFile物件已經存在
                //所以下面方法傳回false,無法創建該目錄
                newFile.mkdir();
                //List方法來列出當前路徑下所有檔和路徑
                String[] fileList = file.list();
                System.out.println("====當前路徑下的所有檔和路徑如下====");
                for(String fileName : fileList)
                {
                        System.out.println(fileName);
                }
                //listRoots方法列出所有的磁片根路徑
                File[] roots = File.listRoots();
                System.out.println("====系統所有根路徑如下====");
                for(File root : roots)
                {
                        System.out.println(root);
                }




2015年5月26日 星期二

【Android】 取得正在執行的 app 專案名



A : Get Running Processes Lists 

 

        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfo = am.getRunningAppProcesses();

        for (int i = 0; i < runningAppProcessInfo.size(); i++) {

            Log.d("", "processName:" + runningAppProcessInfo.get(i).processName);

            if(runningAppProcessInfo.get(i).processName.equals("app.you.are.looking.for")) {

                // Do you stuff
            }
        }

 

 

B: Get Top Task ( Foreground Tasks)

 

 public static boolean isForeground(Context ctx, String myPackage){
    ActivityManager manager = (ActivityManager) ctx.getSystemService(ACTIVITY_SERVICE);
    List< ActivityManager.RunningTaskInfo > runningTaskInfo = manager.getRunningTasks(1);

    ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
    if(componentInfo.getPackageName().equals(myPackage)) {
        return true;
    }     
    return false;
}

 

c. 權限 

<uses-permission android:name="android.permission.GET_TASKS"></uses-permission>

 

 

 

【Android】 判斷GPS是否開啟及開啟GPS



    /**
     * 判斷GPS是否開啟,GPS或者AGPS開啟一個就認為是開啟的
     */
    private boolean isOpenGps() {

        LocationManager locationManager
                = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        // 通過GPS衛星定位,定位級別可以精確到街(通過24顆衛星定位,在室外和空曠的地方定位準確、速度快)
        boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        // 通過WLAN或移動網路(3G/2G)確定的位置(也稱作AGPS,輔助GPS定位。主要用於在室內或遮蓋物(建築群或茂密的深林等)密集的地方定位)
        boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        if (gps || network) {
            return true;
        }

        return false;
    }









    /**
     * 強制幫用戶打開GPS (android 2.X 版可用, 但4.0以上就不行了, 用下面方法)
     *
     * @param context
     */
    public static final void openGPS(Context context) {
        Intent GPSIntent = new Intent();
        GPSIntent.setClassName("com.android.settings",
                "com.android.settings.widget.SettingsAppWidgetProvider");
        GPSIntent.addCategory("android.intent.category.ALTERNATIVE");
        GPSIntent.setData(Uri.parse("custom:3"));
        try {
            PendingIntent.getBroadcast(context, 0, GPSIntent, 0).send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }
    }


 // 導引到定位頁面
 Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
 startActivity(intent);





AndroidManifest.xml檔裡需要添加的許可權




    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />