摘要:還為該枚舉類生成了一個方法,這個方法就是本文要講的方法,我們來具體看下其操作獲取靜態變量。
Java中的枚舉類是我們平時寫代碼時經常會用到的一個類型,在我們創建枚舉類之后,Java會默認在該類中為我們生成values、valueof 等方法。
但你知道嗎,values方法可是個拷貝操作。
寫個例子驗證下:
$ cat Type.java public enum Type { T1, T2, ; public static void main(String[] args) { System.out.println(Type.values() == Type.values()); } } $ java Type.java false
如果values方法不是拷貝操作的話,那兩次方法調用返回的對象應該是一樣的,但結果卻輸出了false,可見該方法應該就是拷貝操作。
有同學可能會發現,我們沒編譯,直接執行的java Type.java,而且還成功了,java不是要先編譯后才能執行嗎?
有關這個問題,可以看我上一篇文章:Java也可以不用編譯直接執行了?
繼續回到本文的話題。
上文我們說到,values方法是拷貝操作,但這只是我們的猜測,有什么證據能明確證明嗎?
我們看下上面類對應的字節碼:
$ javac Type.java $ javap -c -p Type Compiled from "Type.java" public final class Type extends java.lang.Enum{ public static final Type T1; public static final Type T2; private static final Type[] $VALUES; public static Type[] values(); Code: 0: getstatic #1 // Field $VALUES:[LType; 3: invokevirtual #2 // Method "[LType;".clone:()Ljava/lang/Object; 6: checkcast #3 // class "[LType;" 9: areturn # 省略無關字節碼 # static {}; Code: 0: new #4 // class Type 3: dup 4: ldc #10 // String T1 6: iconst_0 7: invokespecial #11 // Method " ":(Ljava/lang/String;I)V 10: putstatic #12 // Field T1:LType; 13: new #4 // class Type 16: dup 17: ldc #13 // String T2 19: iconst_1 20: invokespecial #11 // Method " ":(Ljava/lang/String;I)V 23: putstatic #14 // Field T2:LType; 26: iconst_2 27: anewarray #4 // class Type 30: dup 31: iconst_0 32: getstatic #12 // Field T1:LType; 35: aastore 36: dup 37: iconst_1 38: getstatic #14 // Field T2:LType; 41: aastore 42: putstatic #1 // Field $VALUES:[LType; 45: return }
由字節碼可見,javac自動為我們生成了很多東西,其中就包括一個static代碼塊。
該代碼塊的大致邏輯是:
創建類型為Type的實例,new Type("T1", 0),賦值給靜態變量T1。
創建類型為Type的實例,new Type("T2", 1),賦值給靜態變量T2。
創建類型為Type數組,并將靜態變量T1、T2依次放到數組中,然后再將該數組賦值給靜態變量 $VALUES。
javac還為該枚舉類生成了一個values方法,這個values方法就是本文要講的方法,我們來具體看下其操作:
獲取靜態變量$VALUES。
調用$VALUES的clone方法。
將clone方法返回的對象強轉成Type數組。
返回該數組。
由此我們可以看到,values方法的確是拷貝操作。
上文我們說到,values等方法是javac動態生成的,是這樣嗎?
我們還是通過源碼來確認下這個疑問。
// com.sun.tools.javac.comp.TypeEnter.MembersPhase private void addEnumMembers(JCClassDecl tree, Envenv) { ... // public static T[] values() { return ???; } JCMethodDecl values = make. MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), names.values, valuesType, List.nil(), List.nil(), List.nil(), // thrown null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), null); ... }
該方法向Enum類里添加了values方法,但還沒有方法體。
// com.sun.tools.javac.comp.Lower private void visitEnumDef(JCClassDecl tree) { ... Symbol valuesSym = lookupMethod(tree.pos(), names.values, tree.type, List.nil()); ... if (useClone()) { // return (T[]) $VALUES.clone(); JCTypeCast valuesResult = make.TypeCast(valuesSym.type.getReturnType(), make.App(make.Select(make.Ident(valuesVar), syms.arrayCloneMethod))); valuesBody = List.of(make.Return(valuesResult)); } else { // template: T[] $result = new T[$values.length]; ... // template: System.arraycopy($VALUES, 0, $result, 0, $VALUES.length); ... // template: return $result; ... } ... }
該方法向Enum類的values方法里添加了方法體。
怎么樣,現在一切都非常明朗了吧,values方法會拷貝數組$VALUES的值,然后返回給我們。
希望能對大家有所幫助。
完。
更多原創文章,請關注我微信公眾號:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/76128.html
摘要:原文你真的會克隆對象嗎開始之前在開始聊克隆之前,我們還是先來看看數據類型。值通過函數生成,是獨一無二的。同時,中規定了對象的屬性名有兩種類型,一種是字符串,另一種就是類型。返回一個數組,包含對象自身的所有屬性的鍵名。 原文:你真的會克隆對象嗎 開始之前 在開始聊克隆之前,我們還是先來看看js數據類型。js的數據類型分為基本數據類型和復雜數據類型。 基本數據類型:Number、Bool...
摘要:它接受任意數量的源對象,枚舉它們的所有屬性并分配給。所以現在怎么辦有幾種方法可以創建一個對象的深拷貝。為了防止發生任何意外,請使用而不是。我想測量哪種方法是最高性能的。圖表以下是,和中不同技術的性能。 原文:Deep-copying in JavaScript - DasSur.ma 如何在 JavaScript 中拷貝一個對象?對于這個很簡單的問題,但是答案卻不簡單。 引用傳值 在...
摘要:介一回,偶們來聊一下用中的類,有些盆友可能用過或者的,知道語法糖,可是在中并沒有,中需要用到構造函數來模擬類。而且要注意一點,構造函數沒有語句,是自動返回。 本回內容介紹 上一回聊到JS的Function類型,做了柯里化,數組去重,排序的題。 介一回,偶們來聊一下用JS中的類,有些盆友可能用過ES6或者TypeScript的,知道Class語法糖,可是在ES5中并沒有,ES5中需要用到...
摘要:網站的面試專題學習筆記非可變性和對象引用輸出為,前后皆有空格。假定棧空間足夠的話,盡管遞歸調用比較難以調試,在語言中實現遞歸調用也是完全可行的。棧遵守規則,因此遞歸調用方法能夠記住調用者并且知道此輪執行結束之返回至當初的被調用位置。 ImportNew 網站的Java面試專題學習筆記 1. 非可變性和對象引用 String s = Hello ; s += World ; s.tr...
摘要:木易楊注意原始類型被包裝為對象木易楊原始類型會被包裝,和會被忽略。木易楊原因在于時,其屬性描述符為不可寫,即。木易楊解決方法也很簡單,使用我們在進階期中介紹的就可以了,使用如下。 引言 上篇文章介紹了賦值、淺拷貝和深拷貝,其中介紹了很多賦值和淺拷貝的相關知識以及兩者區別,限于篇幅只介紹了一種常用深拷貝方案。 本篇文章會先介紹淺拷貝 Object.assign 的實現原理,然后帶你手動實...
閱讀 3245·2021-11-15 11:37
閱讀 2460·2021-09-29 09:48
閱讀 3827·2021-09-22 15:55
閱讀 3023·2021-09-22 10:02
閱讀 2646·2021-08-25 09:40
閱讀 3238·2021-08-03 14:03
閱讀 1705·2019-08-29 13:11
閱讀 1579·2019-08-29 12:49