精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java和C++在細節上的差異:接口與內部類

開發 后端
本文主要從接口與內部類以及異常和斷言方面講解了Java和C++在細節上的差異。

繼上篇文章:Java和C++在細節上的差異:枚舉與反射

 六、接口與內部類:

1. 接口和抽象類:Java通過interface關鍵字來表示接口,接口中不能包含非靜態域字段,所有的域成員均是公有的抽象方法,如Comparable接口,如果希望利用Arrays.sort方法,數組的成員必須實現該接口。抽象類中包含抽象方法,和接口一樣抽象類也不能被實例化。

1) 接口不能被實例化,但是可以聲明接口的變量指向其實現類的對象。

2) 每個類只能有一個超類,但是可以實現多個接口。

以下為Java的接口和抽象類的定義方式:

  1. public interface Comparable { 
  2. int compareTo(Object other); 
  3.  
  4. public interface Comparable<T> { 
  5. int compareTo(T other); 
  6.  
  7. abstract class Employee implements Comparable { 
  8. public abstract int compareTo(Object other); 

在C++中同樣存在接口和抽象類的概念,也和Java一樣不能被實例化,但是并沒有相應的關鍵字存在,而是以一種潛在規則的方式存在,見如下代碼:

  1. //Comparable對象聲明的方法中只有純虛方法存在(析構函數除外),且沒有任何成員變量。 
  2. class Comparable { 
  3. public
  4. virtual ~Comparable() {} 
  5. //compareTo為純虛方法 
  6. virtual int compareTo(Comparable& other) = 0
  7.  
  8. //Employee對象中存在部分純虛方法,且可以有成員變量存在。 
  9. class Employee { 
  10. public
  11. virtual int compareTo(Comparable& other) { return 0; } 
  12. virtual int backgroud() = 0
  13.  
  14. private
  15. int _age; 

在C++的實現中,基于接口編程,同時導出C接口的工廠方法對于跨編譯器極為重要,該方式比較類似于Windows中的COM技術。

C++支持多重繼承,因此也存在虛基類(菱形結構)等問題帶來的負面影響,既子類的兩個父類中同時存在相同簽名的虛方法。見如下代碼:

  1. class TcpServerTask { 
  2. public
  3. virtual void run() {} 
  4.  
  5. class SentObjectTask { 
  6. public
  7. virtual void run() {} 
  8.  
  9. class TcpServerSentTask : public TcpServerTask, public SentObjectTask { } 

2. 對象克隆: Object對象中存在protected類型的clone方法,該方法將會完成子類對象clone的缺省操作,既對象域字段的淺拷貝,如果該對象的成員均為原始類型,如int、float等,或者為不可變類型,如String。這樣的淺拷貝將能夠達到對象clone的預期。換言之,如果對象內部存在可變對象的引用,淺拷貝將會帶來原始對象和cloned對象引用相同對象引用的問題。如果希望避免該問題的發生,子類需要實現Cloneable接口。這里需要指出的是Cloneable接口并未提供clone方法,只是提供了一種契約簽名。子類真正做的還是重載Object方法中的clone方法,由于Object中該方法為protected方法,所以caller不能直接調用它,只能將子類的clone方法聲明為共有類型,caller才能調用。

  1. //該實現類使用淺拷貝已經可以滿足其需要了 
  2. public class implements Cloneable { 
  3. //這里已經提升了clone方法的級別為public。 
  4. public Employee clone() throws CloneNotSupportedException { 
  5. return (Employee)super.clone(); 
  6. //深拷貝clone方法,必須clone對象內部所有可變的實例域,其中這些可變類 
  7. //必須全部都實現了自己的clone方法,否則將會跑出異常。 
  8. public class Employee implements Cloneable { 
  9. public Employee clone() throws CloneNotSupportedException { 
  10. //缺省clone完成了域字段的按位淺拷貝。 
  11. Employee cloned = (Employee)super.clone(); 
  12. cloned.hireday = (Date)hireday.clone(); 
  13. private Date hireday; 

注:數組對象可以通過Array的clone(public)方法完成元素的拷貝。

在C++中由于并不存在Object這樣的單根結構的框架,因此C++是以另外一種方式表現該問題的,既缺省拷貝構造和缺省等于操作符重載。和Java類似,這兩個方法也是member bitwise拷貝的,但這是由編譯器在生成對象模型時自動完成的缺省行為,如果該類重載了拷貝構造函數和等于操作符,在需要copy的時候則會調用重載后的方法,類的實現者應該在這兩個方法中完成深拷貝。C++中還可以通過將這兩個方法顯示的聲明為private類型的方法來禁用這種對象之間的copy行為,一旦出現,編譯器將會在在編譯器報錯。在C++中還存在一個explicit的關鍵字,可以有效的防止編譯器通過自行推演隱式的調用對象的拷貝構造函數和等于操作符函數,見如下代碼:

  1. //該類將會使用缺省的copy constructor,因此也會出現兩個對象 
  2. //引用相同_name變量地址的問題。 
  3. class Employee { 
  4. private
  5. char* _name; 
  6. }; 
  7. //該類由于將這兩個方法私有化,一旦出現對象的隱式拷貝構造, 
  8. //將會導致編譯錯誤。 
  9. class Employee { 
  10. private
  11. Employee(Employee& other); 
  12. const Employee& operator= (Employee& other); 
  13. private
  14. char* _name; 
  15. }; 
  16. //將會調用重載后的這兩個函數 
  17. class Employee { 
  18. Employee(Employee& other); 
  19. const Employee& operator= (Employee& other); 
  20. private
  21. char* _name; 
  22. }; 

注:C++中有一種被稱為引用計數的技術,經常會用在這個地方,以便提高對象copy的效率。

3. 接口與回調:嚴格意義上講,回調這個屬于更多的應用于C/C++這些支持基于過程編程的語言,Java中的回調是通過接口的方式來實現的,由于在接口的實現類中可以附帶更多的信息,因此其表達能力要由于C/C++中的函數指針,見如下代碼:

  1. public class Thread { 
  2. public Thread(Runnable r) {} 
  3.  
  4. public class MyTask implements Runnable { 
  5. public MyTask(int taskID) { 
  6. _taskID = taskID; 
  7.  
  8. public void setOk(bool ok) { 
  9. _ok = ok; 
  10.  
  11. public void run() {} 
  12.  
  13. public static void main(String[] args){ 
  14. MyTask t = new MyTask(5); 
  15. Thread thrd = new Thread(t); 
  16. t.setOk(true); 
  17. thrd.start(); 

這里的Runnable參數既為接口,Thread對象在啟動的時候會調用該接口實現對象的run方法,但是在調用之前可以給該實現類傳入更多的狀態等相關數據,以便在線程類調用run方法時可以得到更多的信息。
以下為回調函數在C/C++中的實現:

  1. typedef int(*TestCallback)(int,int); 
  2. int testCaller(TestCallback cb,int a,int b) { 
  3. return cb(a,b); 
  4.  
  5. int testCallback(int a,int b) { 
  6. return a * b; 
  7.  
  8. int main() { 
  9. TestCallback cb = testCallback; 
  10. return testCall(cb,5,6); 

在C++中還可以通過模板以更加松散的方式完成類似Java的基于接口的回調(Java的回調方式,C++完全可以做到),見如下代碼:

  1. template<typename T> 
  2. class Thread { 
  3. public
  4. Thread(T* r) _r = r {} 
  5. void start() { if (_r) _r->run(); } 
  6. private
  7. T* _r; 

在以上的實現中,T無需是某個接口的實現類,只要保證該類型包含run()方法即可,注意:C++中的模板是引用才編譯的方式,如果沒有任何Thread<T>的聲明,不會導致任何編譯錯誤,只有當聲明的類型對象中不包含run()方法時才會導致編譯錯誤。

4. 內部類:Java中內部類可以為私有內部類,既只有外部類可以訪問該內部類,而Java外部類的可見性只有包可見和public兩種。C++中的內部類比較類似于Java中的靜態內部類,只是一種作用域限制的行為,以下為Java非靜態內部類的說明:

1) 內部類可以訪問外部類的所有域成員和域字段,這也同樣包括私有的字段和成員。

2) Java的編譯器在構造外部類調用內部類構造方法時,自動將外部類的this變量作為一個隱式參數傳給了內部類的構造函數,內部類則在構造函數中保留了this變量的引用,該行為為編譯器隱式行為。

  1. public class Employee { 
  2. public class InnerClass { 
  3. bool test() { 
  4. //這里的_jobYears為外部類域字段。 
  5. return _jobYears > 10
  6.  
  7. public Employee(int jobYears,String name) {  
  8. _name = name;  
  9. _jobYears = jobYears;  
  10. _salary = 0
  11.  
  12. public void raiseSalary() { 
  13. //編譯器的會將以下構造隱式替換為InnerClass inner = new InnerClass(this); 
  14. //因為Java在為其編譯的時候發現InnerClass為非靜態內部類,則自動添加了以下構造: 
  15. //public InnerClass(Employee e) 
  16. InnerClass inner = new InnerClass(); 
  17. if (test())  
  18. _salary += 1000
  19. private String _name; 
  20. private int _jobYears; 
  21. private int _salary; 

注:針對以上事例,內部類InnerClass可以通過Employee.this._jobYears的全稱來顯式的代替_jobYears > 10 中的_jobYears。反過來在raiseSalary方法中可以通過this.new InnerClass()語法格式更加明確的創建InnerClass的對象。

  1. public class Employee {  
  2. public class InnerClass {  
  3. bool test() {  
  4. //這里的_jobYears為外部類域字段。  
  5. return Employee.this._jobYears > 10;  
  6. }  
  7. }  
  8.   
  9. public Employee(int jobYears,String name) {   
  10. _name = name;   
  11. _jobYears = jobYears;   
  12. _salary = 0;  
  13. }  
  14.   
  15. public void raiseSalary() {  
  16. //這里也可以不使用this作為內部該內部類對象的外部類對象  
  17. //引用,可以根據需要替換為其他外部類對象的引用,如:  
  18. // Employee other = new Employee();  
  19. // InnerClass innser = other.new InnerClass();  
  20. InnerClass inner = this.new InnerClass();  
  21. if (test())   
  22. _salary += 1000;  
  23. }  
  24. ......  
  25. }  

注:在外部類的作用域之外調用public內部類的語法為 OutClass.InnerClass。

3) 局部內部類的可見范圍僅僅限于聲明該局部類的函數內部,見如下代碼:

  1. public void start() { 
  2. class TimePrinter implements ActionListener { 
  3. public void actionPerformed(ActionEvent e) { 
  4. Date now = new Date(); 
  5. System.out.println("At the tone,the time is " + now); 
  6. //beep為外部類的域字段 
  7. if (beep) 
  8. Tookkit.getDefaultToolkit().beep(); 
  9. ActionListener l = new TimePrinter(); 
  10. new Timer(interval,l).start(); 

局部類同樣可以訪問函數內部的局部變量,但是要求該變量必須是final的。

  1. public void start(final bool beep) { 
  2. class TimePrinter implements ActionListener { 
  3. public void actionPerformed(ActionEvent e) { 
  4. Date now = new Date(); 
  5. System.out.println("At the tone,the time is " + now); 
  6. //beep為外部函數的局部變量。 
  7. if (beep) 
  8. Tookkit.getDefaultToolkit().beep(); 
  9. ActionListener l = new TimePrinter(); 
  10. new Timer(interval,l).start(); 

為了規避局部類只能訪問final局部變量的限制,既一次賦值之后不能再被重新賦值。但是我們可以通過數組的方式進行巧妙的規避,在下例中數組counter對象本身是final的,因此他不可以被重新賦值,然而其引用的數組元素則可以被重新賦值,見下例:

  1. public void test() { 
  2. final int[] counter = new int[1]; 
  3. for (int i = 0; i < dates.length; ++i) { 
  4. dates[i] = new Date() { 
  5. public int compareTo(Date other) { 
  6. //這里如果counter不是數組,而是被定義為final int counter, 
  7. //則會導致編譯失敗。 
  8. counter[0]++; 
  9. return super.compareTo(other); 

C++中同樣可以做到這些,其規則和Java的主要差異為C++的內部類無法直接訪問外部類的任何成員。

  1. class OuterClass { 
  2. public
  3. void testOuter() { 
  4. class FunctionInnerClass { 
  5. public
  6. void test() { 
  7. printf("This is FunctionInnerClass.\n"); 
  8. }; 
  9. FunctionInnerClass innerClass; 
  10. innerClass.test(); 
  11. }; 
  12.  
  13. int main() 
  14. OuterClass outer; 
  15. outer.testOuter(); 
  16. return 0; 

4) 匿名內部類,其基本規則和局部內部類相似,差別在于該內部類不能有聲明構造函數,這主要是因為Java要求類的構造函數和類名相同,而匿名內部類自身沒有類名,因此在new新對象的時候,傳入的構造函數參數為超類的構造函數參數。C++中不支持匿名類。見下例:

  1. public void start(final bool beep) { 
  2. ActionListener l = new ActionListener() { 
  3. public void actionPerformed(ActionEvent e) { 
  4. Date now = new Date(); 
  5. System.out.println("At the tone,the time is " + now); 
  6. //beep為外部函數的局部變量。 
  7. if (beep) 
  8. Tookkit.getDefaultToolkit().beep(); 
  9. new Timer(interval,l).start(); 

5) 靜態內部類,其功能和C++中的嵌套類非常相似,但是和Java自身的非靜態內部類之間還是存在一些差異,如靜態內部類不能直接訪問外圍類的對象引用域字段,但是可以訪問外部類的static域字段(包括private)。在Java中只有內部類可以被定義為static的,外圍類是不可以這樣定義的。

  1. public class TestMain { 
  2. private static boolean classField = false
  3. private boolean objectField = false
  4. static class InnerClass { 
  5. public void test() { 
  6. //這里由于classField是靜態域字段,所以靜態內部類可以直接訪問, 
  7. //但是對于objectField對象域字段而言,由于靜態內部類中沒有包含 
  8. //外部類的引用,因此不能直接訪問objectField. 
  9. if (classField)  
  10. System.out.println("Hello."); 
  11.  
  12. public static void main(String[] args) { 
  13. classField = true
  14. new InnerClass().test(); 

以下示例中的內部類只能是靜態內部類,因為該外部類的靜態方法在返回內部類的實例時,無法將一個外部類的對象引用傳遞給該內部類,因為必須要求該內部類為靜態內部類,否則將會報編譯錯誤。

  1. public class TestMain { 
  2. static class InnerClass { 
  3. public void test() { 
  4. System.out.println("Hello.\n"); 
  5.  
  6. private static InnerClass createInnerClass() { 
  7. return new InnerClass(); 
  8. public static void main(String[] args) { 
  9. createInnerClass().test(); 

如果InnerClass不是靜態內部類,則需要將上例改寫為:

  1. public class TestMain { 
  2. class InnerClass { 
  3. public void test() { 
  4. System.out.println("Hello.\n"); 
  5.  
  6. private static InnerClass createInnerClass() { 
  7. //為了確保InnerClass可以得到外部類的對象引用。 
  8. return new TestMain().new InnerClass(); 
  9. public static void main(String[] args) { 
  10. createInnerClass().test(); 

6) 代理類:通過以下代碼step by step解釋代理類的機制

  1. import java.lang.reflect.InvocationHandler; 
  2. import java.lang.reflect.Proxy; 
  3. import java.util.Arrays; 
  4. import java.util.Random; 
  5.  
  6. public class TestMain { 
  7. public static void main(String[] args) { 
  8. Object[] elements = new Object[1000]; 
  9. for (int i = 0; i < elements.length; ++i) { 
  10. Integer v = i + 1
  11. //h(調用處理接口)是代理類的核心處理單元。由于代理類對象只是包含了InvocationHandler 
  12. //這樣一個對象實例,并且是存放于超類Proxy中的,而實際的被代理實例必須存放于InvocationHandler 
  13. //的實現類中,如這里的Integer對象v。其中的核心代理代碼也是在InvocationHandler子類的 
  14. //invoke方法中完成的。 
  15. InvocationHandler h = new TraceHandler(v); 
  16. //1. 第一個參數表示ClassLoader,這里使用缺省加載器,因此傳入null即可。 
  17. //2. 第二個參數表示該代理類需要implement的接口數組(Java中可以實現多個接口)。 
  18. //3. 調用處理器接口,是代理類如果實現代理的核心,后面會介紹該類。 
  19. //4. 將該代理類作為Integer的代理存入數組。 
  20. elements[i] = Proxy.newProxyInstance(nullnew Class[] {Comparable.class}, h); 
  21. Integer key = new Random().nextInt(elements.length) + 1
  22. //1. 由于代理類也都實現Comparable接口,因此可以用于Arrays.binarySearch中。 
  23. //2. 對代理類進行二分查找的比較時,將會直接調用代理類的compareTo方法。 
  24. //3. 該自動生成的Proxy的子類,其中的compareTo方法會將所有外部調用的信息,連同 
  25. // 方法名一并傳給其內部調用處理器對象的invoke方法,并調用該方法(invoke). 
  26. //4. 這里Proxy子類會將所有實例化時指定接口(Comparable)的方法(compareTo),以及 
  27. // Object中toString、equals和hashCode方法的調用都會傳遞給調用處理器的invoke方法。 
  28. //5. 因此在輸出結果中不僅可以看到compareTo方法的調用被打印出,toString也可打印。 
  29. int result = Arrays.binarySearch(elements, key); 
  30. if (result >= 0
  31. System.out.println(elements[result]); 
  32.  
  33. class TraceHandler implements InvocationHandler { 
  34. //由于Proxy的子類是動態生成的,其具體的實現也是編譯器動態生成后傳給JVM的。 
  35. //因此這里是整個代理機制中唯一存放被代理對象的地方。 
  36. public TraceHandler(Object t) { 
  37. target = t; 
  38.  
  39. //在此例中,該方法是被Comparable接口中的compareTo方法調用的,該實現邏輯是位于該 
  40. //動態生成的Proxy子類中,如  
  41. //public MyProxy extends Proxy implements Comparable { 
  42. // int compareTo(Object other) { h.invoke(...); } 
  43. @Override 
  44. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
  45. //打印出實際被調用方法的名稱和參數值。 
  46. System.out.print(target); 
  47. System.out.print("." + method.getName() + "("); 
  48. if (args != null) { 
  49. for (int i = 0; i < args.length; ++i) { 
  50. System.out.print(args[i]); 
  51. if (i < args.length - 1
  52. System.out.print(", "); 
  53. System.out.println(")"); 
  54. //交給被代理類做實際的比較。 
  55. return method.invoke(target, args); 
  56. private Object target = null
  57. /* 輸出結果如下: 
  58. 500.compareTo(128) 
  59. 250.compareTo(128) 
  60. 125.compareTo(128) 
  61. 187.compareTo(128) 
  62. 156.compareTo(128) 
  63. 140.compareTo(128) 
  64. 132.compareTo(128) 
  65. 128.compareTo(128) 
  66. 128.toString() 
  67. 128 */ 

#p#

七、異常和斷言:

1. 異常處理:

1) 異常規范表示對于"已檢查"(checked)異常,如FileNotFoundException等,既在程序運行期間可以預測到的邏輯問題引發的異常,對于該類異常,需要在包含該異常的函數聲明部分標識出來,該函數可能會引發此類異常,如:

  1. public Image loadImage(String s) throws IOException, MalformedURLException 

如果在loadImage中仍然存在其他"已檢查",但是沒有在函數的異常規范中聲明出來,那么將會導致編譯失敗,因此對于函數中所有"已檢查"必須按照Java異常規范的要求,在函數的聲明中予以標識。對于該函數(loadImage)的調用者而言,在調用該函數時,必須將其放入try塊中,同時在catch字句中捕捉異常規范中標識的異常或他們的超類。
對于"運行時異常"(unchecked or runtime),由于大多是程序Bug或JVM問題所致,因此不可預測性極強,如ArrayIndexOutOfBoundException,對于該類異常無需在函數的異常規范部分予以聲明。

在C++標準中也同樣存在異常規范的說法,如

  1. File* loadFile(const char* s) throw std::bad_error 

所不同的是C++沒有明確的要求如果函數內部拋出了該異常,則必須在函數聲明的異常規范部分予以聲明,對于函數調用者而言也同樣沒有這樣的規定,必須捕獲其中的異常,因此異常規范在目前的C++編譯器中只是一種提示性的聲明。Java和C++在異常規范方面還存在的另一個區別是,C++中,如果函數沒有throw字句,那么該函數仍然可以拋出任何異常,但是對于Java的"已檢查"(checked)異常則必須通過throws字句聲明。

2) 如何拋出異常,在此方面,Java和C++沒有太大的差異,唯一的不同是Java拋出的異常必須是Throwable的實現類,C++中則沒有這樣的限制,也不存在這樣的異常接口。見如下代碼:

  1. public void howToThrowException() { 
  2. if (someErrorOccurred) 
  3. //1. 通過throw關鍵字直接拋出指定異常類型的對象即可。 
  4. throw new MyCheckedException(); 

3) 異常捕捉:由于Java中所有的異常均繼承自Throwable,所以catch(Throwable e)可以捕捉所有類型的異常,無論該異常是否為checked or unchecked異常,但是C++中并不存在這樣的異常祖先接口,因此如果想達到這樣的效果需要使用catch(...)關鍵字,這同樣表示捕捉所有的異常。

4) 異常鏈:當異常第一次拋出并且被catch住的時候,catch塊中的代碼可以再次拋出捕捉到的異常,同時也可以為了使上層業務邏輯能夠得到更加清晰的判斷,在第一次捕捉到異常后重新定義一個新的異常并再次拋出。有的時候,如果上層邏輯在需要的時候依然可以看到原始異常,將會對錯誤的處理更加合理。在Java中可以通過異常鏈的方式達到這樣的效果,見如下代碼:

  1. public void testExceptionChain() throws MyCustomizedFileException { 
  2. try { 
  3. FileInputStream in = new FileInputStream("myfile"); 
  4. catch (FileNotFoundException e) { 
  5. //定義了新的,準備再次被拋出的異常對象。 
  6. Throwable te = new MyCustomizedFileException("access file error."); 
  7. //將原始異常鏈接到該異常對象的內部,以供之后需要時通過getCause()方法重新獲取。 
  8. te.initCause(e); 
  9. throw te; 
  10.  
  11. public static void main(String[] args) { 
  12. try { 
  13. testExceptionChain(); 
  14. catch (MyCustomizedFileException e) { 
  15. //獲取該異常對象的原始異常。 
  16. Throwable te = e.getCause(); 
  17. System.out.println(te.getClass().getName()); 
  18. /* 輸出結果如下: 
  19. FileNotFoundException 
  20. */ 

5) finally字句:在Java的異常機制中存在finally這樣的關鍵字,其塊中的代碼無論異常是否發生都將會被執行,從而可以確保函數內部分配或者打開的資源都能在函數內部進行釋放或者關閉,如Socket連接、DB連接,見如下代碼:

  1. public void testFinally() { 
  2. InputStream in = null
  3. try { 
  4. in = new FileInputStream("myfile"); 
  5. catch (IOException e) { 
  6. //TODO: do something for this exception. 
  7. finally { 
  8. in.close(); 
  9. //Do the following code. 

在以上的代碼中,無論try塊中異常是否發生,finally塊中的代碼"in.close()" 都將會在函數退出之前或catch處理之后被執行,從而保證了FileInputStream對象能夠在函數退出之前被關閉。然而這樣的做法仍然可能導致一些影響代碼流程的問題,如果try塊中的代碼沒有產生異常,而是在finally中的in.close引發了異常,那么整個try{}catch{}finally{}代碼塊之后的代碼將不會被執行,而是直接退出該函數,同時拋出in.close()引發的異常給該函數的調用者。修正代碼如下:

  1. public void testFinally() { 
  2. InputStream in = null
  3. try { 
  4. in = new FileInputStream("myfile"); 
  5. catch (IOException e) { 
  6. //TODO: do something for this exception. 
  7. finally { 
  8. try { 
  9. in.close(); 
  10. catch (IOException e) { 
  11. //Do the following code. 

在C++中,由于對象是可以在棧上聲明并且分配空間的,當棧退出后會自行調用該對象的析構函數,因此該對象的資源釋放代碼可以放在類的析構函數中。該方式對于一個多出口的函數而言也是非常有效的,特別是對于加鎖和解鎖操作需要在同一個函數中完成,為了防止在某個退出分支前意外的漏掉解鎖操作,可以采用該技巧,見如下代碼:

  1. template<typename LockT> 
  2. class ScopedLock { 
  3. public
  4. ScopedLock(T& lock) : _lock(lock) { 
  5. _lock.lock(); 
  6.  
  7. ~ScopedLock() { 
  8. _lock.unlock(); 
  9. private
  10. LockT _lock; 
  11. }; 
  12.  
  13. void testFunc() { 
  14. ScopedLock s1(myLock); 
  15. if (cond1) { 
  16. return
  17. else if (cond2) { 
  18. //TODO: do something 
  19. return
  20. else { 
  21. //TODO: do something 
  22. return

對于以上代碼,無論函數從哪個分支退出,s1的析構函數都將調用,因此myLock的解鎖操作也會被調用。

6) 異常堆棧跟蹤:通過Throwable的getStackTrace方法獲取在異常即將被拋出的時間點上程序的調用堆棧,這樣有利于日志的輸出和錯誤的分析,見如下代碼:

  1. public void testStackTrace() { 
  2. try { 
  3. //TODO: call function, which may be raise some exception. 
  4. catch (Throwable e) { 
  5. StackTraceElement[] frames = e.getStackTrace(); 
  6. for (StackTraceElement f : frames) { 
  7. System.out.printf("Filename is = %s\n",f.getFileName()); 
  8. System.out.printf("LineNumber is = %d\n",f.getLineNumber()); 
  9. System.out.printf("ClassName is = %s\n",f.getClassName()); 
  10. System.out.printf("Methodname is = %s\n",f.getMethodName()); 
  11. System.out.printf("isNativeMethod = %s\n",f.isNativeMethod() ? "true" : "false"); 

也可以直接通過Throwable對象函數當前函數的運行棧信息,見如下代碼:

  1. public static void main(String[] args) { 
  2. Throwable e = new Throwable(); 
  3. StackTraceElement[] frames = e.getStackTrace(); 
  4. for (StackTraceElement f : frames) { 
  5. System.out.printf("Filename is = %s\n",f.getFileName()); 
  6. System.out.printf("LineNumber is = %d\n",f.getLineNumber()); 
  7. System.out.printf("ClassName is = %s\n",f.getClassName()); 
  8. System.out.printf("Methodname is = %s\n",f.getMethodName()); 
  9. System.out.printf("isNativeMethod = %s\n",f.isNativeMethod() ? "true" : "false");  
  10. }  
  11. /* 輸入如下: 
  12. Filename is = TestMain.java 
  13. LineNumber is = 3 
  14. ClassName is = TestMain 
  15. Methodname is = main 
  16. isNativeMethod = false */ 

C++語言本身并未提供這樣的方法,只是提供了__FUNCTION__、__LINE__、__FILE__這樣的3個宏來獲取當前函數的函數名、行號和文件名,但是無法得到調用棧信息,如果確實需要這樣的信息,只能通過操作系統的工具包來協助完成(僅針對Debug版本),目前Windows(vc)和Linux(gcc)都提供這樣的開發包。

2. 斷言:是主要用于開發、調試和系統集成測試期間進行Debug的一種方式和技巧,語法如下:

  1. assert condition OR assert condition : expression 

其中assert為關鍵字,當condition為false時,程序運行中斷,同時報出指定的錯誤信息,如果使用assert的后面一種形式,expression的結果將會同時輸出,這樣更有助于錯誤的判斷,見如下兩種代碼形式:

  1. public static void main(String[] args) { 
  2. int a = 5
  3. assert a > 10 : a; 
  4. System.out.println("Ok."); 
  5. /* 輸出結果: 
  6. Exception in thread "main" java.lang.AssertionError: 5 
  7. at TestMain.main(TestMain.java:4) 
  8. */ 
  9. public static void main(String[] args) { 
  10. int[] a = null
  11. assert a != null
  12. System.out.println("Ok."); 
  13. /* 輸出結果: 
  14. Exception in thread "main" java.lang.AssertionError 
  15. at TestMain.main(TestMain.java:4) 
  16. */ 

在eclipse中,缺省情況下斷言是被禁用的,如果需要開啟斷言,則需要在Run(Debug) As->Run(Debug) Configurations...->Arguments->VM arguments中添加"-enableassertions" 運行期參數。如果斷言被禁用,assert中的代碼不會被執行,因此在系統發布后也不會影響程序的運行時效率。使用者也可以通過該命令行參數-ea:MyClass -ea:com.mypackage.mylib 來指定需要啟用斷言的class和package,如果啟用的是package,那么該包內的所有class都將啟用斷言。在C++中,是依靠crt中的assert(cond)函數來實現的,如果cond為false,程序將會立即停止,但是在使用前首先需要保證assert.h文件被包含進當前文件,再有就是當前編譯的程序必須是Debug版本,對于Release版本,無論Win32和Linux,斷言的語句都將不會被執行。

原文鏈接:http://www.cnblogs.com/stephen-liu74/archive/2011/08/09/2131740.html

【系列文章】

  1. Java和C++在細節上的差異:泛型程序設計
  2. Java和C++在細節上的差異:程序設計結構
  3. Java和C++在細節上的差異:枚舉與反射
責任編輯:林師授 來源: Stephen_Liu的博客
相關推薦

2011-12-06 10:48:32

Java

2011-12-06 09:42:51

Java

2011-12-06 12:16:58

Java

2009-06-01 08:48:19

作用域變量作用域對象作用域

2023-10-19 13:24:00

Java工具

2020-01-15 11:14:21

Java算法排序

2020-12-14 10:23:23

Java內部類外部類

2024-07-01 12:48:00

C++內部類開發

2010-01-28 15:22:12

C++嵌套類

2009-08-26 18:00:07

C#內部類

2010-02-05 15:32:33

Java內部類

2012-11-08 09:49:30

C++Java程序員

2009-06-11 13:08:29

Java內部類Java編程思想

2020-09-21 07:00:42

Java內部類接口

2011-03-29 14:11:15

內部類

2011-07-20 16:30:42

C++

2011-07-21 15:44:33

Java內部類

2009-06-11 11:07:25

Java局部內部類Final類型

2010-08-26 10:41:45

C#內部類

2023-03-06 07:53:36

JavaN種內部類
點贊
收藏

51CTO技術棧公眾號

久久久久久免费网| 国产精品69久久久| 99热自拍偷拍| 亚洲图片中文字幕| 天海翼精品一区二区三区| 国产精品久久毛片a| 97人人爽人人喊人人模波多| 香蕉久久免费影视| 国产精品99精品无码视| 韩国精品视频在线观看 | 中文字幕一区免费在线观看 | 黄色片子在线观看| 香蕉伊大人中文在线观看| 国产一区二区三区免费看| 亚洲午夜激情免费视频| 黄色一级视频片| 9色在线观看| 国产欧美日韩在线一区二区| 亚洲va在线va天堂| 电影午夜精品一区二区三区| 神马久久精品综合| 亚洲一区有码| 亚洲欧洲日韩女同| 成人久久久久爱| 无码人中文字幕| 国产极品嫩模在线观看91精品| 久久久精品tv| 国产精品一区二区三区在线 | 无吗不卡中文字幕| 国产91免费视频| 亚洲综合一区中| 天堂一区二区在线免费观看| 国产偷国产偷亚洲清高网站| 亚洲中文字幕无码中文字| 天天摸天天碰天天爽天天弄| 日韩午夜一区| 日韩精品中文字幕在线| 丰满人妻一区二区三区大胸| 欧美人与禽猛交乱配| 国产精品66部| 久久久久久久久久久免费精品 | 99国产麻豆精品| 午夜精品久久久久久久白皮肤 | 午夜精品久久久久久久99樱桃| 亚洲欧美一二三| 99热这里只有精品66| 国产精品久久久乱弄| 欧美一区二区三区小说| 大胆欧美熟妇xx| 奇米影视888狠狠狠777不卡| 日日夜夜免费精品| 精品国产一区二区三区久久久| 午夜不卡福利视频| 波多野结衣中文在线| 久久精品一区二区三区不卡| 久久大香伊蕉在人线观看热2| 久久亚洲天堂网| 日本女优一区| 日韩欧美中文字幕公布| 亚洲熟妇无码另类久久久| 国产高清av在线| 国产麻豆一精品一av一免费| 久久久久久伊人| 日韩激情一区二区三区| 韩日精品视频| 亚洲色图18p| 亚洲一二三不卡| 中文在线а√天堂| 欧美色播在线播放| 免费成人深夜夜行网站视频| 黄色片一区二区三区| 日日噜噜夜夜狠狠视频欧美人| 欧美做受高潮电影o| 在线视频这里只有精品| 欧美国产极品| 91麻豆精品国产91久久久久久| 黄色片视频在线免费观看| 亚洲精品福利电影| 欧美视频在线播放| 毛片在线视频播放| 男人皇宫亚洲男人2020| 一个色在线综合| 婷婷四房综合激情五月| 日本最黄一级片免费在线| 不卡一区中文字幕| 成人免费自拍视频| www国产一区| 美女精品一区二区| yellow中文字幕久久| 欧美精品乱码视频一二专区| 欧美猛男做受videos| 日韩免费视频线观看| 91欧美视频在线| 手机在线观看av| 亚洲制服丝袜av| 欧美成人xxxxx| 2019中文亚洲字幕| 亚洲激情在线观看视频免费| 亚洲女人在线观看| 久久夜夜久久| 精品国产123| 色婷婷狠狠18禁久久| 国产精品伦一区二区| 精品久久五月天| 欧美性猛交乱大交| 香蕉久久夜色精品国产更新时间| 一道本无吗dⅴd在线播放一区| 国产成人无码一区二区在线观看| 91嫩草精品| 日韩女优av电影在线观看| 国精产品一区一区三区免费视频 | 久久av一区二区| 欧美一区二区三区| 国产清纯在线一区二区www| 精品乱色一区二区中文字幕| 日韩在线观看视频一区二区三区| 国产很黄免费观看久久| 欧美重口乱码一区二区| 九一在线视频| 国产欧美一区二区精品婷婷| www婷婷av久久久影片| 美女精品导航| 欧美三区在线观看| 手机av在线网| 日本免费精品| 亚洲第一福利网| 亚洲一区二区三区无码久久| 乱亲女h秽乱长久久久| 日韩精品高清在线| 熟女少妇内射日韩亚洲| 精品精品久久| 久久久久999| 久久久精品91| 在线亚洲欧美| 国产99在线免费| 久久久久久国产精品免费无遮挡| 亚洲欧美日韩国产手机在线| 成人小视频在线观看免费| 国产精品蜜月aⅴ在线| 亚洲人成网7777777国产| www.国产成人| 日韩电影在线看| 鲁丝一区二区三区免费| h网站视频在线观看| 亚洲欧洲日韩在线| 嫩草视频免费在线观看| 青青草91久久久久久久久| 日本欧美精品在线| 国产xxxx在线观看| 国产精品国产三级国产aⅴ无密码| 免费日韩视频在线观看| 久久三级毛片| 丝袜情趣国产精品| 国产在线观看你懂的| 国产真实精品久久二三区| 在线免费一区| 成年男女免费视频网站不卡| 在线观看精品一区| 乳色吐息在线观看| 在线观看国产精品入口| 91av视频在线观看| 国产又粗又大又黄| 99精品欧美一区二区蜜桃免费 | 91社区视频在线观看| 国产精品久久久久蜜臀| 国产在线98福利播放视频| 亚洲免费不卡视频| 午夜私人影院久久久久| 搡老熟女老女人一区二区| 久久久久久自在自线| 亚洲一区二区免费| 久久av少妇| 欧美少妇一区二区| 91 在线视频| 成人午夜伦理影院| 亚洲国产成人不卡| а√天堂资源官网在线资源| 亚洲精品丝袜日韩| 男人天堂视频在线| 成人国产一区二区三区精品| 精品无码一区二区三区在线| 免费看成人哺乳视频网站| 国产精品入口免费视频一| 天天干天天爱天天操| 日本大香伊一区二区三区| 色婷婷免费视频| 天堂影院一区二区| 在线视频一二三区| 五月激激激综合网色播| 成人黄色中文字幕| 成全电影大全在线观看| 亚洲一区二区国产| 亚洲国产精品二区| 亚洲啪啪综合av一区二区三区| 精品免费国产一区二区| 三级小说欧洲区亚洲区| 国产精品视频公开费视频| 欧美性受ⅹ╳╳╳黑人a性爽| 亚洲人成啪啪网站| 亚洲精品成人电影| 欧美影院精品一区| 国产一级免费av| 中文字幕成人在线观看| av无码精品一区二区三区| 狼人精品一区二区三区在线| 国产精品69久久| 久草福利在线| 欧美成人精精品一区二区频| 一级久久久久久| 亚洲不卡一区二区三区| 最新黄色av网址| 久久婷婷综合激情| 熟女人妇 成熟妇女系列视频| 91精品久久久久久久蜜月| 91精品国产自产在线老师啪| 国产无遮挡裸体视频在线观看| 中文字幕在线国产精品| 91亚洲国产成人久久精品麻豆| 午夜精品在线看| 午夜免费激情视频| 国产成人在线观看| 污污网站免费观看| 久久综合九色综合欧美狠狠| 欧美一级免费播放| 日韩激情啪啪| 99在线观看视频| 91福利区在线观看| 日韩激情第一页| 精品人妻无码一区二区三区蜜桃一| 91精品福利在线| 日本va欧美va国产激情| 亚洲精品国产一区二区精华液| 最好看的中文字幕| 蜜桃在线一区二区三区| 91av在线免费播放| 亚洲制服av| 亚洲成人网上| 久久99蜜桃| 免费在线成人av电影| 秋霞影院一区二区三区| 好看的日韩精品视频在线| 99精品国产高清一区二区麻豆| 亚洲自拍中文字幕| 日韩免费高清视频网站| 97免费资源站| 女生影院久久| 日韩av片永久免费网站| 偷拍中文亚洲欧美动漫| 日本一区二区在线免费播放| 中文不卡1区2区3区| 秋霞午夜一区二区| 中文字幕在线视频久| 91黑丝在线观看| 中文字幕成在线观看| 欧洲成人性视频| 666av成人影院在线观看| www.亚洲免费视频| 欧美三级理伦电影| 久久久国产一区| 在线看一级片| 亚洲一二在线观看| 北岛玲一区二区三区| 深夜福利一区二区| 18视频在线观看网站| 久久免费视频在线| 91porn在线观看| www.欧美免费| 国产精品剧情一区二区在线观看| 久久伊人91精品综合网站| 日本在线丨区| 亚洲香蕉在线观看| 老司机精品视频在线观看6| 欧美精品在线免费播放| 国产黄色在线| 北条麻妃久久精品| 久久大胆人体| 欧美综合国产精品久久丁香| 精品免费av在线 | 中文字幕 亚洲视频| 亚洲午夜精品网| 欧美肥妇bbwbbw| 亚洲最色的网站| 亚洲男人的天堂在线视频| 在线精品亚洲一区二区不卡| a级片在线播放| 精品亚洲男同gayvideo网站| 在线观看黄av| 国内揄拍国内精品| 成人免费视频观看| 国产精品毛片va一区二区三区| 亚洲专区视频| 欧美二区在线| 欧美影院天天5g天天爽| 亚洲精品乱码久久久久久蜜桃91| 欧美日韩午夜| 欧美少妇在线观看| 99精品综合| 日韩日韩日韩日韩日韩| 蜜桃一区二区三区在线观看| 国产国语老龄妇女a片| 美国三级日本三级久久99| 麻豆av免费看| 国产精品美女视频| 国产a∨精品一区二区三区仙踪林| 欧美日韩三级一区二区| 日韩手机在线视频| 欧美三级xxx| 精品国精品国产自在久不卡| 亚洲人午夜色婷婷| 91九色美女在线视频| 成人国产亚洲精品a区天堂华泰| 一本色道久久综合亚洲精品酒店 | 国产精品资源站在线| 成人免费av片| 亚洲亚洲人成综合网络| 国产精品无码AV| 欧美一级xxx| av男人的天堂在线| 欧美在线www| 欧美黑人巨大xxxxx| 国产成人av一区二区三区| 久久精品国产www456c0m| 手机看片日韩国产| 日本成人在线不卡视频| 欧美wwwwwww| 久久久精品国产免费观看同学| 日本学生初尝黑人巨免费视频| 激情成人中文字幕| 亚洲不卡免费视频| 另类少妇人与禽zozz0性伦| 久久亚洲精品人成综合网| 日韩高清av| 久久久五月天| 成年网站免费在线观看| 日本一区二区成人| 中文字幕精品视频在线观看| 欧美二区在线观看| 成人久久久精品国产乱码一区二区 | 成人福利在线| 国产成人短视频| 久草精品在线| 凹凸日日摸日日碰夜夜爽1| 91蜜桃网址入口| 91麻豆制片厂| 欧美性猛交xxxxxx富婆| 户外极限露出调教在线视频| 日本精品一区二区三区在线| 伊人成综合网yiren22| 女人扒开屁股爽桶30分钟| 久久亚洲私人国产精品va媚药| 亚洲欧美自拍视频| 在线播放视频一区| 激情视频在线观看| 亚洲一区二区三区sesese| 欧美有码视频| 最近免费中文字幕中文高清百度| 26uuu亚洲婷婷狠狠天堂| 特级做a爱片免费69| 亚洲欧洲国产伦综合| 亚洲不卡系列| 国产手机精品在线| 国产日产一区| 日本激情视频在线播放| zzijzzij亚洲日本少妇熟睡| 黑人と日本人の交わりビデオ| 欧美丝袜自拍制服另类| 免费大片黄在线| av成人在线电影| 亚洲裸体俱乐部裸体舞表演av| www.com黄色片| 亚洲精品v日韩精品| 国内爆初菊对白视频| 98视频在线噜噜噜国产| 深夜福利久久| 欧美又黄又嫩大片a级| 午夜影视日本亚洲欧洲精品| 精品视频一二三| 亚洲自拍小视频免费观看| 国产欧美一区二区三区国产幕精品| 亚洲一级片免费观看| 亚洲精品高清在线观看| 亚洲区小说区图片区| 久久久在线免费观看| 亚洲va久久久噜噜噜久久| 99re精彩视频| 亚洲电影第三页| 国产99视频在线| 91精品国产91久久久久久吃药| 红桃成人av在线播放| 国内av免费观看| 日韩欧美a级成人黄色| 成人ww免费完整版在线观看| 国产精品夜间视频香蕉| 国产精品欧美在线观看| 亚洲18在线看污www麻豆| 欧美日韩国内自拍| 天堂v在线观看| 国产欧美在线播放| 宅男噜噜噜66国产日韩在线观看| 免费一级suv好看的国产网站|