1. 程式人生 > >我今天的面試題,註冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意

我今天的面試題,註冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意

註冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意。 

Android 的廣播機制


在 Android 裡面有各種各樣的廣播,比如電池的使用狀態,電話的接收和簡訊的接收都會產生一個廣播,應用程式開發者也可以監聽這些廣播並做出程式邏輯的處理。下面我畫一張粗略的圖來幫助大家理解廣播的執行機制。

Android 中有各式各樣的廣播,各種廣播在Android 系統中執行,當系統/應用程式執行時便會向 Android 註冊各種廣播,Android 接收到廣播會便會判斷哪種廣播需要哪種事件,然後向不同需要事件的應用程式註冊事件,不同的廣播可能處理不同的事件也可能處理相同的廣播事件,這時就需要 Android 系統為我們做篩選。

案例分析:


一個經典的電話黑名單,首先通過將黑名單號碼儲存在資料庫裡面,當來電時,我們接收到來電廣播並將黑名單號碼與資料庫中的某個資料做匹配,如果匹配的話則做出相應的處理,比如掛掉電話、比如靜音等等。。。


Demo 分析:


下面通過一個小DEMO 來講解一下廣播在Android 中如何編寫,在Demo中我們設定了一個按鈕為按鈕設定點選監聽通過點擊發送廣播,在後臺中接收到廣播並列印LOG資訊。程式碼如下:


BroadCastActivity 頁面程式碼


public class BroadCastActivity extends Activity {
    public static final String ACTION_INTENT_TEST = "com.terry.broadcast.test";

     
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btn = (Button) findViewById(R.id.Button01);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub 
                Intent intent = new Intent(ACTION_INTENT_TEST);
                sendBroadcast(intent);
            }
        });
    }
}

    
  
  
接收器程式碼如下: 
 


public class myBroadCast extends BroadcastReceiver {

     
    public myBroadCast() {
        Log.v("BROADCAST_TAG", "myBroadCast");
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub 
        Log.v("BROADCAST_TAG", "onReceive");
    }

}


    
    Android 廣播的生命週期 
在上面的接收器中,繼承了BroadcastReceiver 並重寫了它的onReceive 並構造了一個函式,下面通過圖片來一步一步認識 Android 廣播的生命週期。當我點選一下按鈕,它向Android 傳送了一個廣播,如下圖: 
     
這時我們再點選一下按鈕,它還是會再向 Android 系統傳送廣播,此時日誌資訊如下: 
    
下面本人畫一張影象,描述了Android 中廣播的生命週期,其次它並不像Activity 一樣複雜,執行原理很簡單如下圖: 
     
下面來看一下SDK給出的解釋: 
    
大意為:如果一個廣播處理完onReceive 那麼系統將認定此物件將不再是一個活動的物件,也就會finished掉它。 
至此,大家應該能明白 Android 的廣播生命週期的原理,程式碼也不用多介紹,很簡單的一個傳送廣播並處理廣播的Demo。 
  
    Android 如何判斷並篩選廣播? 
前 面說過 Android 的廣播有各式各樣,那麼Android 系統是如何幫我們處理我們需要哪種廣播併為我們提供相應的廣播服務呢?這裡有一點需要大家注意,每實現一個廣播接收類必須在我們應用程式中的 manifest 中顯式的註明哪一個類需要廣播,併為其設定過濾器,如下圖: 
     
Tip:action 代表一個要執行的動作,在Andriod 中有很action 比如 ACTION_VIEW,ACTION_EDIT

那麼有些人會問了,如果我在一個廣播接收器中要處理多個動作呢?那要如何去處理?

在Android 的接收器中onReceive 以經為我們想到的,同樣的你必須在Intent-filter 裡面註冊該動作,可以是系統的廣播動作也可以是自己需要的廣播,之後你之需要在onReceive 方法中,通過intent.getAction()判斷傳進來的動作即可做出不同的處理,不同的動作。具體大家可以去嘗試測試一下。


小結:

在Android 中如果要傳送一個廣播必須使用sendBroadCast 向系統傳送對其感興趣的廣播接收器中。 
使用廣播必須要有一個intent 物件必設定其action動作物件 
使用廣播必須在配置檔案中顯式的指明該廣播物件 
每次接收廣播都會重新生成一個接收廣播的物件 
在BroadCast 中儘量不要處理太多邏輯問題,建議複雜的邏輯交給Activity 或者 Service 去處理 
  Android廣播機制(兩種註冊方法) 
在android下,要想接受廣播資訊,那麼這個廣播接收器就得我們自己來實現了,我們可以繼承BroadcastReceiver,就可以有一個廣播接受器了。有個接受器還不夠,我們還得重寫BroadcastReceiver裡面的onReceiver方法,當來廣播的時候我們要幹什麼,這就要我們自己來實現,不過我們可以搞一個資訊防火牆。具體的程式碼:


public class SmsBroadCastReceiver extends BroadcastReceiver    
{   
  
    @Override  
    public void onReceive(Context context, Intent intent)   
    {   
        Bundle bundle = intent.getExtras();   
        Object[] object = (Object[])bundle.get("pdus");   
        SmsMessage sms[]=new SmsMessage[object.length];   
        for(int i=0;i<object.length;i++)   
        {   
            sms[0] = SmsMessage.createFromPdu((byte[])object[i]);   
            Toast.makeText(context, "來自"+sms[i].getDisplayOriginatingAddress()+" 的訊息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show();   
        }   
        //終止廣播,在這裡我們可以稍微處理,根據使用者輸入的號碼可以實現簡訊防火牆。    
        abortBroadcast();   
    }   
       

  當實現了廣播接收器,還要設定廣播接收器接收廣播資訊的型別,這裡是資訊:android.provider.Telephony.SMS_RECEIVED

  我們就可以把廣播接收器註冊到系統裡面,可以讓系統知道我們有個廣播接收器。這裡有兩種,一種是程式碼動態註冊:


//生成廣播處理    
smsBroadCastReceiver = new SmsBroadCastReceiver();   
//例項化過濾器並設定要過濾的廣播   


IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");

//註冊廣播    
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter);  


一種是在AndroidManifest.xml中配置廣播


<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
      package="spl.broadCastReceiver"  
      android:versionCode="1"  
      android:versionName="1.0">  
    <application android:icon="@drawable/icon" android:label="@string/app_name">  
        <activity android:name=".BroadCastReceiverActivity"  
                  android:label="@string/app_name">  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  
                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
           
        <!--廣播註冊-->  
        <receiver android:name=".SmsBroadCastReceiver">  
            <intent-filter android:priority="20">  
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  
            </intent-filter>  
        </receiver>  
           
    </application>  
       
    <uses-sdk android:minSdkVersion="7" />  
       
    <!-- 許可權申請 -->  
    <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>  
       
</manifest>  

  兩種註冊型別的區別是:

     1)第一種不是常駐型廣播,也就是說廣播跟隨程式的生命週期。

     2)第二種是常駐型,也就是說當應用程式關閉後,如果有資訊廣播來,程式也會被系統呼叫自動執行。

BroadcastReceiver用於監聽被廣播的事件

必須被註冊,有兩種方法:

1、在應用程式的程式碼中註冊

註冊BroadcastReceiver:

registerReceiver(receiver,filter);

取消註冊BroadcastReceiver:

unregisterReceiver(receiver);

當BroadcastReceiver更新UI,通常會使用這樣的方法註冊。啟動Activity時候註冊BroadcastReceiver,Activity不可見時候,取消註冊。

2、在androidmanifest.xml當中註冊

<receiver>

    <intent-filter>

     <action android:name = "android.intent.action.PICK"/>

    </intent-filter>

</receiver>

使用這樣的方法註冊弊端:它會始終處於活動狀態,畢竟是手機開發,cpu和電源資源比較少,一直處於活動耗費大,不利。


            
        
        
        
    
    10. 請解釋下在單執行緒模型中Message、Handler、Message Queue、Looper之間的關係。
   

1. Android程序
    在瞭解Android執行緒之前得先了解一下Android的程序。當一個程式第一次啟動的時候,Android會啟動一個LINUX程序和一個主執行緒。預設的情況下,所有該程式的元件都將在該程序和執行緒中執行。
同 時,Android會為每個應用程式分配一個單獨的LINUX使用者。Android會盡量保留一個正在執行程序,只在記憶體資源出現不足時,Android 會嘗試停止一些程序從而釋放足夠的資源給其他新的程序使用, 也能保證使用者正在訪問的當前程序有足夠的資源去及時地響應使用者的事件。Android會根據程序中執行的元件類別以及元件的狀態來判斷該程序的重要 性,Android會首先停止那些不重要的程序。按照重要性從高到低一共有五個級別:
前臺程序 
前臺程序是使用者當前正在使用的程序。只有一些前臺程序可以在任何時候都存在。他們是最後一個被結束的,當記憶體低到根本連他們都不能執行的時候。一般來說, 在這種情況下,裝置會進行記憶體排程,中止一些前臺程序來保持對使用者互動的響應。
可見程序 
可見程序不包含前臺的元件但是會在螢幕上顯示一個可見的程序是的重要程度很高,除非前臺程序需要獲取它的資源,不然不會被中止。
服務程序 
運 行著一個通過startService() 方法啟動的service,這個service不屬於上面提到的2種更高重要性的。service所在的程序雖然對使用者不是直接可見的,但是他們執行了用 戶非常關注的任務(比如播放mp3,從網路下載資料)。只要前臺程序和可見程序有足夠的記憶體,系統不會回收他們。
後臺程序 
運 行著一個對使用者不可見的activity(呼叫過 onStop() 方法).這些程序對使用者體驗沒有直接的影響,可以在服務程序、可見程序、前臺進 程需要記憶體的時候回收。通常,系統中會有很多不可見程序在執行,他們被儲存在LRU (least recently used) 列表中,以便記憶體不足的時候被第一時間回收。如果一個activity正 確的執行了它的生命週期,關閉這個程序對於使用者體驗沒有太大的影響。
空程序 
未執行任何程式元件。執行這些程序的唯一原因是作為一個快取,縮短下次程式需要重新使用的啟動時間。系統經常中止這些程序,這樣可以調節程式快取和系統快取的平衡。
Android 對程序的重要性評級的時候,選取它最高的級別。另外,當被另外的一個程序依賴的時候,某個程序的級別可能會增高。一個為其他程序服務的程序永遠不會比被服 務的程序重要級低。因為服務程序比後臺activity程序重要級高,因此一個要進行耗時工作的activity最好啟動一個service來做這個工 作,而不是開啟一個子程序――特別是這個操作需要的時間比activity存在的時間還要長的時候。例如,在後臺播放音樂,向網上上傳攝像頭拍到的圖片, 使用service可以使程序最少獲取到“服務程序”級別的重要級,而不用考慮activity目前是什麼狀態。broadcast receivers做費時的工作的時候,也應該啟用一個服務而不是開一個執行緒。
2. 單執行緒模型 
    當一個程式第一次啟動時,Android會同時啟動一個對應的主執行緒(Main Thread),主執行緒主要負責處理與UI相關的事件,如使用者的按鍵事件,使用者接觸螢幕的事件以及螢幕繪圖事件,並把相關的事件分發到對應的元件進行處理。所以主執行緒通常又被叫做UI執行緒。在開發Android應用時必須遵守單執行緒模型的原則: Android UI操作並不是執行緒安全的並且這些操作必須在UI執行緒中執行。
2.1 子執行緒更新UI 
Android的UI是單執行緒(Single-threaded)的。為了避免拖住GUI,一些較費時的物件應該交給獨立的執行緒去執行。如果幕後的執行緒來執行UI物件,Android就會發出錯誤訊息
CalledFromWrongThreadException。以後遇到這樣的異常丟擲時就要知道怎麼回事了!
2.2 Message Queue 
     在單執行緒模型下,為了解決類似的問題,Android設計了一個Message Queue(訊息佇列), 執行緒間可以通過該Message Queue並結合Handler和Looper元件進行資訊交換。下面將對它們進行分別介紹:
1. Message 
    Message訊息,理解為執行緒間交流的資訊,處理資料後臺執行緒需要更新UI,則傳送Message內含一些資料給UI執行緒。
2. Handler 
    Handler處理者,是Message的主要處理者,負責Message的傳送,Message內容的執行處理。後臺執行緒就是通過傳進來的 Handler物件引用來sendMessage(Message)。而使用Handler,需要implement 該類的 handleMessage(Message)
方法,它是處理這些Message的操作內容,例如Update UI。通常需要子類化Handler來實現handleMessage方法。
3. Message Queue 
    Message Queue訊息佇列,用來存放通過Handler釋出的訊息,按照先進先出執行。
    每個message queue都會有一個對應的Handler。Handler會向message queue通過兩種方法傳送訊息:sendMessage或post。這兩種訊息都會插在message queue隊尾並按先進先出執行。但通過這兩種方法傳送的訊息執行的方式略有不同:通過sendMessage傳送的是一個message物件,會被 Handler的handleMessage()函式處理;而通過post方法傳送的是一個runnable物件,則會自己執行。
4. Looper 
    Looper是每條執行緒裡的Message Queue的管家。Android沒有Global的Message Queue,而Android會自動替主執行緒(UI執行緒)建立Message Queue,但在子執行緒裡並沒有建立Message Queue。所以呼叫Looper.getMainLooper()得到的主執行緒的Looper不為NULL,但呼叫Looper.myLooper() 得到當前執行緒的Looper就有可能為NULL。
    對於子執行緒使用Looper,API Doc提供了正確的使用方法:


    這個Message機制的大概流程:
    1. 在Looper.loop()方法執行開始後,迴圈地按照接收順序取出Message Queue裡面的非NULL的Message。
    2. 一開始Message Queue裡面的Message都是NULL的。當Handler.sendMessage(Message)到Message Queue,該函式裡面設定了那個Message物件的target屬性是當前的Handler物件。隨後Looper取出了那個Message,則呼叫 該Message的target指向的Hander的dispatchMessage函式對Message進行處理。
    在dispatchMessage方法裡,如何處理Message則由使用者指定,三個判斷,優先順序從高到低:
    1) Message裡面的Callback,一個實現了Runnable介面的物件,其中run函式做處理工作;
    2) Handler裡面的mCallback指向的一個實現了Callback介面的物件,由其handleMessage進行處理;
    3) 處理訊息Handler物件對應的類繼承並實現了其中handleMessage函式,通過這個實現的handleMessage函式處理訊息。
    由此可見,我們實現的handleMessage方法是優先順序最低的!
    3. Handler處理完該Message (update UI) 後,Looper則設定該Message為NULL,以便回收!
    在網上有很多文章講述主執行緒和其他子執行緒如何互動,傳送資訊,最終誰來執行處理資訊之類的,個人理解是最簡單的方法——判斷Handler物件裡面的Looper物件是屬於哪條執行緒的,則由該執行緒來執行! 
    1. 當Handler物件的建構函式的引數為空,則為當前所線上程的Looper; 
    2. Looper.getMainLooper()得到的是主執行緒的Looper物件,Looper.myLooper()得到的是當前執行緒的Looper物件。 
現在來看一個例子,模擬從網路獲取資料,載入到ListView的過程:

這個例子,我自己寫完後覺得還是有點亂,要稍微整理才能看明白執行緒間互動的過程以及資料的前後變化。隨後瞭解到AsyncTask類,相應修改後就很容易明白了!

    11. AIDL的全稱是什麼?如何工作?能處理哪些型別的資料
詳情請參看:http://buaadallas.blog.51cto.com/399160/372090
部分概念:
        在Android中, 每個應用程式都可以有自己的程序. 在寫UI應用的時候, 經常要用到Service. 在不同的程序中, 怎樣傳遞物件呢?  顯然, Java中不允許跨程序記憶體共享. 因此傳遞物件, 只能把物件拆分成作業系統能理解的簡單形式, 以達到跨界物件訪問的目的. 在J2EE中,採用RMI的方式, 可以通過序列化傳遞物件. 在Android中, 則採用AIDL的方式. 理論上AIDL可以傳遞Bundle,實際上做起來卻比較麻煩.    
   

AIDL(AndRoid介面描述語言)是一種藉口描述語言; 編譯器可以通過aidl檔案生成一段程式碼,通過預先定義的介面達到兩個程序內部通訊程序的目的. 如果需要在一個Activity中, 訪問另一個Service中的某個物件, 需要先將物件轉化成AIDL可識別的引數(可能是多個引數), 然後使用AIDL來傳遞這些引數, 在訊息的接收端, 使用這些引數組裝成自己需要的物件.

AIDL的IPC的機制和COM或CORBA類似, 是基於介面的,但它是輕量級的。它使用代理類在客戶端和實現層間傳遞值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相關類.; 2. 呼叫aidl產生的class.

AIDL的建立方法:

AIDL語法很簡單,可以用來宣告一個帶一個或多個方法的介面,也可以傳遞引數和返回值。 由於遠端呼叫的需要, 這些引數和返回值並不是任何型別.下面是些AIDL支援的資料型別:

1. 不需要import宣告的簡單Java程式語言型別(int,boolean等)

2. String, CharSequence不需要特殊宣告

3. List, Map和Parcelables型別, 這些型別內所包含的資料成員也只能是簡單資料型別, String等其他比支援的型別.

相關推薦

今天試題註冊廣播方式這些方式優缺點談談Android引入廣播機制用意

註冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意。  Android 的廣播機制 在 Android 裡面有各種各樣的廣播,比如電池的使用狀態,電話的接收和簡訊的接收都會產生一個廣播,應用程式開發者也可以監聽這些廣播並做出程式邏輯的處理

Java試題之在多線程情況下單例模式中懶漢和餓漢會什麽問題呢?

餓漢模式 問題 之間 static 代碼 clas ava public 餓漢 懶漢模式和餓漢模式: public class Demo { //private static Single single = new Single();//餓漢模式

設定差分對好幾方法下面就來一一介紹:

轉自https://www.sohu.com/a/152779501_744981 <晶片之家> 原標題:AD PCB-如何設定差分對 設定差分對,有好幾種方法,下面我就來一一介紹: 方法一: 原理圖中直接設定好,然後匯入到PCB中,如圖,給要設定的

Java試題(一個一個來慢慢解決吧做個記錄)

  【基礎】 官方參考答案:基礎答案 Java執行緒的狀態 程序和執行緒的區別,程序間如何通訊,執行緒間如何通訊 HashMap的資料結構是什麼?如何實現的。和HashTable,ConcurrentHashMap的區別 Cookie和Session的區

試題:一個字串包含英文和特殊字元特殊字元不變英文順序反過來比如string str="[email 

public class Reverse { public static void main(String[] args) { String str = "[email protected]!tk"; char[] chars = str.toCh

試題16——簡述類成員函式的重寫過載和隱藏的區別

重寫與過載主要有以下不同: (1)範圍的區別:被重寫的和重寫的函式在兩個類中,而過載和被過載的函式在同一個類中; (2)引數的區別:被重寫函式和重寫函式的引數列表一定相同,而被過載函式和過載函式的引數列表一定不同; (3)virtual的區別:重寫的基類中被重寫的函式必須要有virtual修

試題5——C中的malloc和C++中的new什麼區別?

malloc和new有以下區別: (1)new,delete是操作符,只能在C++中使用; (2)malloc,free是函式,可以覆蓋,C,C++中都可以使用; (3)new可以呼叫物件的建構函式,對應的delete呼叫相應的解構函式; (4)malloc僅僅分配記憶體,free僅僅回收記

試題14:剪繩子(動態規劃貪心演算法)

一、題目: 一根長度為n的繩子,剪成m段,m,n都大於1,且都為整數,每段長度記為k[0],k[1]…,k[m].求k[0]*k[1]…*k[m]可能的最大乘積 1.1解法: 兩種不同的方法解決這個問題,先用常規的需要O(n²)時間和O(n)空間的動態規劃,接著用只需要O(1)的

試題】給多個無序正整數求中位數

題目:給你很多很多正整數,但它們是無序的,找出它們的中位數。 最開始就想說使用快排,先將這些整數進行排序,然後找到中位數,但又想到可能不是面試官想要的答案,於是又採用了其他方法,最終也沒完全解決出來。 【經驗總結:當面試官問了一個演算法題後,如果想不到優化一點的方法,就先

java試題及答案(基礎題122道程式碼題19道)

      JAVA相關基礎知識   1、面向物件的特徵有哪些方面    1.抽象:   抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象並不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽

【人生很短做自己喜歡的事情罷。】人生是一場旅程我們經歷了次輪迴才換來這個旅程而這個旅程很短因此不妨大膽一些不妨大膽一些去愛一個人去攀一座山去追一個夢······很多事都不明白相信一件事上天讓我們來到這個世界上就是為了讓我們創

人生是一場旅程,我們經歷了幾次輪迴,才換來這個旅程,而這個旅程很短,因此不妨大膽一些,不妨大膽一些去愛一個人,去攀一座山,去追一個夢······有很多事我都不明白,但我相信一件事,上天讓我們來到這個世...

試題收集-java試題及答案(基礎題122道程式碼題19道)

JAVA相關基礎知識 1、面向物件的特徵有哪些方面  1.抽象: 抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象並不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是資料抽象。

人生很短做自己喜歡的事情罷。(人生是一場旅程我們經歷了次輪迴才換來這個旅程而這個旅程很短因此不妨大膽一些不妨大膽一些去愛一個人去攀一座山去追一個夢······很多事都不明白相信一件事上天讓我們來到這個世界上就是為了讓我們創造

人生是一場旅程,我們經歷了幾次輪迴,才換來這個旅程,而這個旅程很短,因此不妨大膽一些,不妨大膽一些去愛一個人,去攀一座山,去追一個夢······有很多事我都不明白,但我相信一件事,上天讓我們來到這個世...

試題&試題:30個人一共花費50先令求解男人女人和小孩的人數分別為多少?

馬克思手稿中有一道趣味數學題:有30個人,其中有男人、女人和小孩,在一家飯館裡吃飯共花了50先令,每個男人各花3先令,每個女人各花2先令,每個小孩各花1先令,問男人、女人和小孩各有幾人? #include <stdio.> int main() { int

淘寶試題:如何充分利用多核CPU計算很大的List中所有整數的和

引用 前幾天在網上看到一個淘寶的面試題:有一個很大的整數list,需要求這個list中所有整數的和,寫一個可以充分利用多核CPU的程式碼,來計算結果。 一:分析題目從題中可以看到“很大的List”以及“充分利用多核CPU”,這就已經充分告訴我們要採用多執行緒(任務)進行

【好文】淘寶試題:如何充分利用多核CPU計算很大的List中所有整數的和

引用 前幾天在網上看到一個淘寶的面試題:有一個很大的整數list,需要求這個list中所有整數的和,寫一個可以充分利用多核CPU的程式碼,來計算結果。 一:分析題目 從題中可以看到“很大的List”以及“充分利用多核CPU”,這就已經充分告訴我們要採用多執行緒(任務)進行

試題5:標頭檔案中的ifndef/define/endif什麼作用?

在一個大的軟體工程裡面,可能會有多個檔案同時包含一個頭檔案,當這些檔案編譯連結成一個可執行檔案時,就會出現大量重定義的錯誤。在標頭檔案中實用#ifndef #define #endif能避免標頭檔案

SQLServer中約束Primary Key約束、Foreign Key約束、Unique約束、Default約束和Check約束今天使用SQL Server2008來演示下這約束的

SQLServer中有五種約束,Primary Key約束、Foreign Key約束、Unique約束、Default約束和Check約束,今天使用SQL Server2008來演示下這幾種約束的建立和使用的方法。 1、Primary Key約束     在表中常有一列或多列的組合,其值能唯一標識表

試題:一個字串包含英文和特殊字元特殊字元不變英文順序反過來比如string str="[email prot

public class Reverse { public static void main(String[] args) { String str = "[email protected]!tk"; char[] char

客觀試題--8.執行緒的生命週期是什麼?執行緒建立方式?

1.執行緒的生命週期執行緒是一個動態執行的過程,它也有一個從產生到死亡的過程。(1)生命週期的五種狀態新建(new Thread)當建立Thread類的一個例項(物件)時,此執行緒進入新建狀態(未被啟動)。例如:Thread  t1=new Thread();就緒(runna