自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java和C++在細(xì)節(jié)上的差異:枚舉與反射

開發(fā) 后端
文章主要從枚舉與反射方面講解了Java和C++在細(xì)節(jié)上的差異。

繼上篇文章:Java和C++在細(xì)節(jié)上的差異:程序設(shè)計(jì)結(jié)構(gòu)

四、枚舉:

枚舉的是在Java 1.5SE 中開始支持的,以下為Java枚舉的基本概念和應(yīng)用技巧:

1. 所有的enum對象均是由class對象作為底層支持的,該對象繼承自JDK中的Enum<E>,但是該底層類確實(shí)final類,既不能再被其他的類繼承。

2. 枚舉的出現(xiàn)完全替代了原有的"public static final"常量表示法,枚舉以一種更加合理、優(yōu)雅和安全的方式替換了原有的方案。其最基本的聲明方式如下:

  1. public enum Color { 
  2. RED, BLUE, BLACK, YELLOW 

3. Enum<E>中構(gòu)造函數(shù)的原型為protected Enum(String name, int ordinal),自定義的枚舉對象會將自身的名字以字符串的形式,同時(shí)將自己在整個(gè)常量從聲明的順序作為超類構(gòu)造函數(shù)的兩個(gè)參數(shù)傳給超類并由超類完成必要的初始化,如:RED枚舉常量將調(diào)用super("RED",0)。

4. 枚舉中可以定義構(gòu)造函數(shù)、域方法和域字段,但是枚舉中的構(gòu)造器必須是私有(private)的,如果自定義枚舉中有了自定義的構(gòu)造函數(shù),那么每個(gè)枚舉常量在聲明時(shí)必須按照自定義構(gòu)造函數(shù)的規(guī)則傳入?yún)?shù)。枚舉對象的構(gòu)造函數(shù)只是在枚舉常量對象聲明的時(shí)刻才調(diào)用一次,之后再也不能像普通對象那樣通過new的方法創(chuàng)建,見如下代碼:

  1. public enum Size { 
  2. SMALL(0.8), 
  3. MEDIUM(1.0), 
  4. LARGE(1.2); 
  5. double pricingFactor; 
  6. private Size(double p) { 
  7. pricingFactor = p; 

注:枚舉常量列表必須寫在最前面聲明,否則編譯器報(bào)錯(cuò)。

5. 可以給自定義枚舉添加域方法,見如下代碼:

  1. public enum Size { 
  2. SMALL(0.8), 
  3. MEDIUM(1.0), 
  4. LARGE(1.2); 
  5. private double pricingFactor; 
  6. Size(double p) { 
  7. pricingFactor = p; 
  8. public double getPricingFactor() { 
  9. return pricingFactor; 

6. 枚舉中常用域方法:

  1. public enum Size{ 
  2. SMALL, 
  3. MEDIUM, 
  4. LARGE; 
  5. public static void main(String[] args){ 
  6. //兩種獲得枚舉類型的方法 
  7. Size s1 = Size.SMALL; 
  8. //valueOf的函數(shù)原型為<T extends Enum<T>> T valueOf(Class<T> enumType,String name) 
  9. Size s2 = Enum.valueOf(Size.class"SMALL"); 
  10. //Size(自定義枚舉)的valueOf方法是Java編譯器在生成字節(jié)碼的時(shí)候自動(dòng)插入的。 
  11. Size s3 = Size.valueOf("MEDIUM");//1 
  12.  
  13. //結(jié)果同上,枚舉重載了equals方法 
  14. System.out.println("Size.MEDIUM.equals(Enum.valueOf(Size.class, \"MEDIUM\")):"
  15. Size.MEDIUM.equals(Enum.valueOf(Size.class"MEDIUM"))); 
  16.  
  17. //遍歷枚舉類型中所有的成員,這里應(yīng)用的Size.values方法和Size.valueOf方法 
  18. //一樣均是編譯器在生成字節(jié)碼的時(shí)候自動(dòng)插入的。 
  19. for(Size s:Size.values()){//2 
  20. //ordinal()和name()方法均為Enum提供的方法,返回枚舉常量在聲明時(shí)的構(gòu) 
  21. //造函數(shù)中自動(dòng)調(diào)用超類構(gòu)造函數(shù)時(shí)傳入的自身字符串名和在聲明列表中的序號 
  22. System.out.println(s.ordinal()+" "+s.name()+" "+s.toString()); 
  23. //compareTo方法缺省比較的是枚舉常量的ordinal()的返回值。 
  24. if (s1.compareTo(s3) < 0
  25. System.out.println("Size.SMALL is less than Size.MEDIUM"); 

7. 在枚舉中可以聲明基于特定常量的類主體,見如下代碼:

  1. public enum Size { 
  2. //Small、ExtraLarge和ExtraExtraLarge均使用自定義的getPricingFactor 
  3. //方法覆蓋Size提供的缺省getPricingFactor方法。 
  4. Small { 
  5. @Override 
  6. public double getPricingFactor() { 
  7. return 0.8
  8. }, 
  9. //Medium和Large將使用Size內(nèi)部缺省實(shí)現(xiàn)的getPricingFactor方法。 
  10. Medium, 
  11. Large, 
  12. ExtraLarge { 
  13. @Override 
  14. public double getPricingFactor() { 
  15. return 1.2
  16. }, 
  17. ExtraExtraLarge { 
  18. @Override 
  19. public double getPricingFactor() { 
  20. return 1.2
  21. }; 
  22. public double getPricingFactor() { 
  23. return 1.0
  24. public static void main(String args[]) { 
  25. for (Size s : Size.values()) { 
  26. double d = s.getPricingFactor(); 
  27. System.out.println(s + " Size has pricing factor of " + d); 
  28. /* 結(jié)果如下: 
  29. Small Size has pricing factor of 0.8 
  30. Medium Size has pricing factor of 1.0 
  31. Large Size has pricing factor of 1.0 
  32. ExtraLarge Size has pricing factor of 1.2 
  33. ExtraExtraLarge Size has pricing factor of 1.2 */ 

8. 枚舉在switch語句中的用法,見如下代碼:

  1. public enum Color { 
  2. RED, BLUE, BLACK, YELLOW 
  3. public static void main(String[] args) { 
  4. Color m = Color.BLUE; 
  5. //case語句中引用枚舉常量時(shí)不需要再加上枚舉的類型名了。 
  6. switch (m) { 
  7.     case RED: 
  8. System.out.println("color is red"); 
  9. break
  10. case BLACK: 
  11. System.out.println("color is black"); 
  12. break
  13. case YELLOW: 
  14. System.out.println("color is yellow"); 
  15. break
  16. case BLUE: 
  17. System.out.println("color is blue"); 
  18. break
  19. default
  20. System.out.println("color is unknown"); 
  21. break

9. 和枚舉相關(guān)的兩個(gè)容器EnumMap和EnumSet,聲明和主要用法如下。

  1. EnumMap<K extends Enum<K>, V>  
  2. EnumSet<E extends Enum<E>> 
  3. //Code Example 1 
  4. public enum State {  
  5. ON, OFF  
  6. };  
  7. public static void main(String[] args) {  
  8. //EnumSet的使用  
  9. EnumSet stateSet = EnumSet.allOf(State.class);  
  10. for (State s : stateSet) 
  11. System.out.println(s);  
  12.  
  13. //EnumMap的使用  
  14. EnumMap stateMap = new EnumMap(State.class);  
  15. stateMap.put(State.ON, "is On");  
  16. stateMap.put(State.OFF, "is off");  
  17. for (State s : State.values())  
  18. System.out.println(s.name() + ":" + stateMap.get(s));  
  19.  
  20. //Code Example 2 
  21. public enum Size { 
  22. Small,Medium,Large 
  23. public static void main(String args[]) { 
  24. Map<Size, Double> map = new EnumMap<Size, Double>(Size.class); 
  25. map.put(Size.Small, 0.8); 
  26. map.put(Size.Medium, 1.0); 
  27. map.put(Size.Large, 1.2); 
  28. for (Map.Entry<Size, Double> entry : map.entrySet()) 
  29. helper(entry); 
  30. private static void helper(Map.Entry<Size, Double> entry) { 
  31. System.out.println("Map entry: " + entry); 

10. Java枚舉和C++枚舉的主要區(qū)別為兩點(diǎn),一是C++中的枚舉中只能定義常量,主要用于switch子句,二是C++中的枚舉常量可以直接和數(shù)值型變量進(jìn)行各種數(shù)學(xué)運(yùn)算。

#p#

五、反射:

1. Java的反射機(jī)制主要表現(xiàn)為四點(diǎn):

1) 在運(yùn)行中分析類的能力;

2) 在運(yùn)行中查看對象;

3) 實(shí)現(xiàn)數(shù)組的操作代碼;

4) 利用Method對象,這個(gè)對象很像C++中的函數(shù)指針。

注:Java的基于反射的應(yīng)用主要用于一些工具類庫的開發(fā),在實(shí)際的應(yīng)用程序開發(fā)中應(yīng)用的場景較少。

2. 獲取對象的名稱(字符串形式) vs 通過對象的名稱(字符串形式)創(chuàng)建對象實(shí)例,見如下代碼:

  1. public static void main(String args[]) { 
  2. //1. 通過對象獲取其字符串表示的名稱  
  3. Date d = new Date(); 
  4.       //or Class<? extends Date> c1 = d.class; 
  5. Class<? extends Date> c1 = d.getClass();  
  6. String className = c1.getName(); 
  7.  
  8. //2. 通過字符串形式的名稱創(chuàng)建類實(shí)例。 
  9. className = "java.util." + className; 
  10. try { 
  11. Class c2 = Class.forName(className); 
  12. //這里用到的newInstance用于創(chuàng)建c2所表示的對象實(shí)例,但是必須要求待創(chuàng)建的類實(shí)例 
  13. //具有缺省構(gòu)造函數(shù)(無參數(shù)),很明顯newInstance調(diào)用并未傳入任何參數(shù)用于構(gòu)造對象。 
  14. Date d2 = (Date)c2.newInstance(); 
  15. catch (ClassNotFoundException e) { 
  16. e.printStackTrace(); 
  17. catch (InstantiationException e) { 
  18. e.printStackTrace(); 
  19. catch (IllegalAccessException e) { 
  20. e.printStackTrace(); 

如果需要通過調(diào)用帶有參數(shù)的構(gòu)造函數(shù)來創(chuàng)建對象實(shí)例,需要使用java.lang.reflect.Constructor對象來完成,見如下代碼:

  1. public static void main(String args[]) { 
  2. String className = "java.util.Date"
  3. try { 
  4. Class c2 = Class.forName(className); 
  5. //找到只接受一個(gè)long類型參數(shù)的構(gòu)造器 
  6. Constructor cc = c2.getConstructor(long.class); 
  7. long ll = 45L; 
  8. //將該Constructor期望的指定類型(long)的參數(shù)實(shí)例傳入并構(gòu)造Date對象。 
  9. Date dd = (Date)cc.newInstance(ll); 
  10. System.out.println("Date.toString = " + dd); 
  11. catch (Exception e) { 
  12. e.printStackTrace(); 

3. 遍歷一個(gè)未知類型的所有域、構(gòu)造方法和域方法,見如下函數(shù)原型:

Field[] getFields(); 返回指定對象域字段數(shù)組,主要包含該類及其超類的所有公有(public)域。

Field[] getDeclaredFields();返回指定對象域字段數(shù)組,主要包含該類自身的所有域,包括private等。

Method[] getMethods(); 返回指定對象域方法數(shù)組,主要包含該類及其超類的所有公有(public)域方法。

Method[] getDeclaredMethods();返回指定對象域方法數(shù)組,主要包含該類自身的所有域方法,包括private等。

Constructor[] getConstructors(); 返回指定對象構(gòu)造函數(shù)數(shù)組,主要包含該類所有公有(public)域構(gòu)造器。

Constructor[] getDeclaredConstructors();返回指定對象構(gòu)造函數(shù)數(shù)組,主要包含該類所有域構(gòu)造器。

int getModifiers(); 返回一個(gè)用于描述構(gòu)造器、方法或域的修飾符的整型數(shù)值,使用Modifier類中的靜態(tài)方法可以協(xié)助分析這個(gè)返回值。

String getName(); 返回一個(gè)用于描述構(gòu)造器、方法和域名的字符串。

Class[] getParameterTypes(); 返回一個(gè)用于描述參數(shù)類型的Class對象數(shù)組。

Class[] getReturnType(); 返回一個(gè)用于描述返回值類型的Class對象。

  1. private static void printConstructors(Class c1) { 
  2. Constructor[] constructors = c1.getDeclaredConstructors(); 
  3. for (Constructor c : constructors) { 
  4. String name = c.getName(); 
  5. System.out.print(" "); 
  6. String modifiers = Modifier.toString(c.getModifiers()); 
  7. if (modifiers.length() > 0
  8. System.out.print(modifiers + " "); 
  9. System.out.print(name + "("); 
  10.  
  11. Class[] paramTypes = c.getParameterTypes(); 
  12. for (int j = 0; j < paramTypes.length; ++j) { 
  13. if (j > 0
  14. System.out.print(","); 
  15. System.out.print(paramTypes[j].getName()); 
  16. System.out.println(");"); 
  17.  
  18. private static void printMethods(Class c1) { 
  19. Method[] methods = c1.getDeclaredMethods(); 
  20. for (Method m : methods) { 
  21. Class retType = m.getReturnType(); 
  22. String name = m.getName(); 
  23. System.out.print(" "); 
  24.  
  25. String modifiers = Modifier.toString(m.getModifiers()); 
  26. if (modifiers.length() > 0
  27. System.out.print(modifiers + " "); 
  28. System.out.print(retType.getName() + " " + name + "("); 
  29. Class[] paramTypes = m.getParameterTypes(); 
  30. for (int j = 0; j < paramTypes.length; ++j) { 
  31. if (j > 0)  
  32. System.out.print(", "); 
  33. System.out.print(paramTypes[j].getName()); 
  34. System.out.println(");"); 
  35.  
  36. private static void printFields(Class c1) { 
  37. Field[] fields = c1.getDeclaredFields(); 
  38. for (Field f : fields) { 
  39. Class type = f.getType(); 
  40. String name = f.getName(); 
  41. System.out.print(" "); 
  42. String modifiers = Modifier.toString(f.getModifiers()); 
  43. if (modifiers.length() > 0
  44. System.out.print(modifiers + " "); 
  45. System.out.println(type.getName() + " " + name + ";"); 
  46.  
  47. public static void main(String args[]) { 
  48. String name = "java.lang.Double"
  49. try { 
  50. Class c1 = Class.forName(name); 
  51. Class superc1 = c1.getSuperclass(); 
  52. String modifier = Modifier.toString(c1.getModifiers()); 
  53. if (modifier.length() > 0
  54. System.out.print(modifier + " "); 
  55.  
  56. System.out.print("class " + name); 
  57. if (superc1 != null && superc1 != Object.class
  58. System.out.print(" extends " + superc1.getName()); 
  59.  
  60. System.out.print("\n{\n"); 
  61. printConstructors(c1); 
  62. System.out.println(); 
  63. printMethods(c1); 
  64. System.out.println(); 
  65. printFields(c1); 
  66. System.out.println("}"); 
  67. catch (Exception e) { 
  68. e.printStackTrace(); 
  69. /* 輸出結(jié)果如下: 
  70. public final class java.lang.Double extends java.lang.Number 
  71. { 
  72. public java.lang.Double(java.lang.String); 
  73. public java.lang.Double(double); 
  74.  
  75. public boolean equals(java.lang.Object); 
  76. public java.lang.String toString(); 
  77. public static java.lang.String toString(double); 
  78. public int hashCode(); 
  79. public static native long doubleToRawLongBits(double); 
  80. public static long doubleToLongBits(double); 
  81. public static native double longBitsToDouble(long); 
  82. public int compareTo(java.lang.Double); 
  83. public volatile int compareTo(java.lang.Object); 
  84. public byte byteValue(); 
  85. public short shortValue(); 
  86. public int intValue(); 
  87. public long longValue(); 
  88. public float floatValue(); 
  89. public double doubleValue(); 
  90. public static java.lang.Double valueOf(double); 
  91. public static java.lang.Double valueOf(java.lang.String); 
  92. public static java.lang.String toHexString(double); 
  93. public static int compare(double, double); 
  94. public boolean isNaN(); 
  95. public static boolean isNaN(double); 
  96. public boolean isInfinite(); 
  97. public static boolean isInfinite(double); 
  98. public static double parseDouble(java.lang.String); 
  99.  
  100. public static final double POSITIVE_INFINITY; 
  101. public static final double NEGATIVE_INFINITY; 
  102. public static final double NaN; 
  103. public static final double MAX_VALUE; 
  104. public static final double MIN_NORMAL; 
  105. public static final double MIN_VALUE; 
  106. public static final int MAX_EXPONENT; 
  107. public static final int MIN_EXPONENT; 
  108. public static final int SIZE; 
  109. public static final java.lang.Class TYPE; 
  110. private final double value; 
  111. private static final long serialVersionUID; 
  112. } 
  113. */ 

4. 通過反射編寫泛型數(shù)組代碼,見如下代碼比較:

  1. static Object[] badArrayGrow(Object[] a) { 
  2. int newLength = a.length * 11 / 10 + 10
  3. //該對象數(shù)組的在創(chuàng)建時(shí)是基于Object的,所以返回后, 
  4. //再裝回其他類型數(shù)組時(shí)將會拋出ClassCastException的異常。 
  5. Object[] newArray = new Object[newLength]; 
  6. System.arraycopy(a,0,newArray,0,a.length); 
  7. return newArray; 
  8.  
  9. static Object goodArrayGrow(Object a) {//這里的參數(shù)務(wù)必為Object,而不是Object[]  
  10. Class c1 = a.getClass(); 
  11. if (!c1.isArray())  
  12. return null
  13. //這里用于獲取數(shù)組成員的類型 
  14. Class componentType = c1.getComponentType(); 
  15. //獲取數(shù)組的長度。 
  16. int length = Array.getLength(a); 
  17. int newLength = length * 11 / 10 + 10
  18. //通過數(shù)組成員的類型和新的長度值來創(chuàng)建一個(gè)和參數(shù)類型相同的數(shù)組, 
  19. //并增加他的空間,***再返回。 
  20. Object newArray = Array.newInstance(componentType,newLength); 
  21. System.arraycopy(a,0,newArray,0,length); 
  22. return newArray; 

5. 在運(yùn)行時(shí)使用反射的對象或動(dòng)態(tài)調(diào)用反射之后的方法。

1) 獲取域字段和設(shè)置域字段:

  1. public void testField() { 
  2. Employee harry = new Employee("Harry Hacker",35000,10); 
  3. Class c1 = harry.getClass(); 
  4. Field f = c1.getDeclaredField("name"); 
  5. //由于name字段有可能是Employee類的私有域字段,如果直接調(diào)用會致使JVM 
  6. //拋出安全異常,為了避免該異常的發(fā)生,需要調(diào)用下面的語句來得以保證。 
  7. f.setAccessible(true); 
  8. Object v = f.get(harry); 
  9. System.out.println(v); 

2) 通過Method的invoke函數(shù)動(dòng)態(tài)調(diào)用反射后的方法:

該方式有些類似于C#的委托(delegate)和C++的函數(shù)指針。

  1. public int add(int param1, int param2) {  
  2. return param1 + param2;  
  3. }  
  4.  
  5. public static void main(String[] args) throws Exception {  
  6. Class classType = MyTest.class;  
  7. Object myTest = classType.newInstance();  
  8. Method addMethod = classType.getMethod("add",int.class,int.class); 
  9. //如果add為靜態(tài)方法,這里的***個(gè)參數(shù)傳null 
  10. Object result = addMethod.invoke(myTest, 100,200);  
  11. System.out.println(result);  

6. C++自身并沒有提供像Java這樣完備的反射機(jī)制,只是提供了非常簡單的動(dòng)態(tài)類型信息,如type_info和typeid。然而在一些C++的第三方框架類庫中提供了類似的功能,如MFC、QT。其中MFC是通過宏的方式實(shí)現(xiàn),QT是通過自己的預(yù)編譯實(shí)現(xiàn)。在目前的主流開發(fā)語言中,也只有C#提供的反射機(jī)制可以和Java的相提并論。

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

【系列文章】

  1. Java和C++在細(xì)節(jié)上的差異:接口與內(nèi)部類
  2. Java和C++在細(xì)節(jié)上的差異:泛型程序設(shè)計(jì)
  3. Java和C++在細(xì)節(jié)上的差異:程序設(shè)計(jì)結(jié)構(gòu)
責(zé)任編輯:林師授 來源: Stephen_Liu的博客
相關(guān)推薦

2011-12-06 11:12:59

Java

2011-12-06 09:42:51

Java

2011-12-06 12:16:58

Java

2009-06-01 08:48:19

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

2011-04-11 13:00:08

C++結(jié)構(gòu)體枚舉

2012-11-08 09:49:30

C++Java程序員

2020-12-31 05:35:53

MySQL 8.0MySQL 5.7JSON

2012-11-05 10:37:52

IBMdw

2010-01-27 13:53:40

強(qiáng)大的CC++編譯器

2011-04-01 13:21:26

SQL ServerOracle數(shù)據(jù)庫查詢優(yōu)化

2010-02-01 16:40:14

C++枚舉子

2010-02-03 10:05:48

C++ enum枚舉

2011-06-01 14:06:44

復(fù)印機(jī)技巧

2015-03-20 10:00:34

LinuxCC++

2011-12-25 15:35:05

ibmdwJavaC++

2010-01-28 14:54:01

C++資源管理

2011-04-06 08:57:07

C++java多態(tài)

2010-02-03 16:04:34

C++標(biāo)準(zhǔn)類庫

2009-05-22 11:01:53

C++JavaC#

2010-01-11 15:29:13

引用C++語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號