<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 題記 JDK,Java Development Kit。 我們必須先認識到,JDK只是,僅僅是一套Java基礎類庫而已,是Sun公司開發的基礎類庫,僅此而已,JDK本身和我們自行書寫總結的類庫,從技術含量來說,還是在一個層級上,它們都是需要被編譯成字節碼,在JRE中運行的,JDK編譯后的結果就是jre/lib下的rt.jar,我們學習使用它的目的是加深對Java的理解,提高我們的Java編碼水平。 本系列所有文章基于的JDK版本都是1.7.16。 源碼下載地址:[https://jdk7.java.net/source.html](https://jdk7.java.net/source.html) # 本節內容 在本節中,簡析java.lang包所包含的基礎類庫,當我們新寫一個class時,這個package里面的class都是被默認導入的,所以我們不用寫import java.lang.Integer這樣的代碼,我們依然使用Integer這個類,當然,如果你顯示寫了import java.lang.Integer也沒有問題,不過,何必多此一舉呢![大笑](https://box.kancloud.cn/2016-01-19_569e21abc5518.gif) # Object 默認所有的類都繼承自Object,Object沒有Property,只有Method,其方法大都是native方法(也就是用其他更高效語言,一般是c實現好了的), Object沒有實現clone(),實現了hashCode(),哈希就是對象實例化后在堆內存的地址,用“==”比較兩個對象,實際就是比較的內存地址是否是一個,也就是hashCode()是否相等, 默認情況下,對象的equals()方法和==符號是一樣的,都是比較內存地址,但是有些對象重寫了equals()方法,比如String,使其達到比較內容是否相同的效果 另外兩個方法wait()和notify()是和多線程編程相關的,多線程里面synchronized實際就是加鎖,默認是用this當鎖,當然也可以用任何對象當鎖,wait()上鎖,線程阻塞,notify()開鎖,收到這個通知的線程運行。以下代碼示例: ~~~ class Test implements Runnable { private String name; private Object prev; private Object self; public Test(String name,Object prev,Object self) { this.name=name; this.prev = prev; this.self = self; } @Override public void run() { int count = 2; while(count>0) { synchronized(prev) { synchronized(self) { System.out.println(name+":"+count); count--; self.notify(); //self解鎖 } try { prev.wait(); //prev上鎖 } catch(InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); Test ta = new Test("A",c,a); Test tb = new Test("B",a,b); Test tc = new Test("C",b,c); new Thread(ta).start(); Thread.sleep(10); new Thread(tb).start(); Thread.sleep(10); new Thread(tc).start(); } } ~~~ 以上代碼將順序輸出:A:2、B:2、C:2、A:1、B:1、C:1 。 Object類占用內存大小計算:[http://m.blog.csdn.net/blog/aaa1117a8w5s6d/8254922](http://m.blog.csdn.net/blog/aaa1117a8w5s6d/8254922) Java如何實現Swap功能:[http://segmentfault.com/q/1010000000332606](http://segmentfault.com/q/1010000000332606) # 構造函數和內部類 構造函數不能繼承,是默認調用的,如果不顯示用super指明的話,默然是調用的父類中沒有參數的構造函數。 ~~~ class P { public P() {System.out.println("P");} public P(String name) {System.out.println("P" + name);} } class S extends P { public S(String name) { super("pname"); //不過不指定的話,默認是調用的父類的沒有參數的構造函數 System.out.println("name"); } } ~~~ 關于內部類,在應用編程中較少用到,但是JDK源碼中大量使用,比如Map.Entry,ConcurrentHashMap,ReentrantLock等,enum本身也會被編譯成static final修飾的內部類。 關于內部類的更多內容,可以參閱這篇文章:[http://android.blog.51cto.com/268543/384844/](http://android.blog.51cto.com/268543/384844/) # Class和反射類 Java程序在運行時每個類都會對應一個Class對象,可以從Class對象中得到與類相關的信息,Class對象存儲在方法區(又名Non-Heap,永久代),當我們運行Java程序時,如果加載的jar包非常多,大于指定的永久代內存大小時,則會報出PermGen錯誤,就是Class對象的總計大小,超過永久代內存的緣故。 Class類非常有用,在我們做類型轉換時經常用到,比如以前用Thrift框架時,經常需要在Model類型的對象:Thrift對象和Java對象之間進行轉換,需要手工書寫大量模式化代碼,于是,就寫了個對象轉換的工具,在Thrift對象和Java對象的Property名字一致的情況下,可以使用這個工具直接轉換,其中大量使用了Class里面的方法和java.lang.reflect包的內容。 關于Calss類,方法眾多,不詳述。下面附上這個Thrift工具的代碼。 ~~~ import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Thrift前綴的對象和不含Thrift前綴的對象相互轉換. * 參考: * http://blog.csdn.net/it___ladeng/article/details/7026524 * http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html * http://www.cnblogs.com/bingoidea/archive/2009/06/21/1507889.html * http://java.ccidnet.com/art/3539/20070924/1222147_1.html * http://blog.csdn.net/justinavril/article/details/2873664 */ public class ThriftUtil { public static final Integer THRIFT_PORT = 9177; /** * Thrift生成的類的實例和項目原來的類的實例相關轉換并賦值 * 1.類的屬性的名字必須完全相同 * 2.當前支持的類型僅包括:byte,short,int,long,double,String,Date,List * 3.如果有Specified列,則此列為true才賦值,否則,不為NULL就賦值 * @param sourceObject * @param targetClass * @param toThrift:true代表把JavaObject轉換成ThriftObject,false代表把ThriftObject轉換成JavaObject,ThriftObject中含有Specified列 * @return */ public static Object convert(Object sourceObject,Class<?> targetClass,Boolean toThrift) { if(sourceObject==null) { return null; } //對于簡單類型,不進行轉換,直接返回 if(sourceObject.getClass().getName().startsWith("java.lang")) { return sourceObject; } Class<?> sourceClass = sourceObject.getClass(); Field[] sourceFields = sourceClass.getDeclaredFields(); Object targetObject = null; try { targetObject = targetClass.newInstance(); } catch (InstantiationException e1) { e1.printStackTrace(); } catch (IllegalAccessException e1) { e1.printStackTrace(); }; if(targetObject==null) { return null; } for(Field sourceField:sourceFields) { try { //轉換時過濾掉Thrift框架自動生成的對象 if(sourceField.getType().getName().startsWith("org.apache.thrift") ||sourceField.getName().substring(0,2).equals("__") ||("schemes,metaDataMap,serialVersionUID".indexOf(sourceField.getName())!=-1) ||(sourceField.getName().indexOf("_Fields")!=-1) ||(sourceField.getName().indexOf("Specified")!=-1) ) { continue; } //處理以DotNet敏感字符命名的屬性,比如operator String sourceFieldName = sourceField.getName(); if(sourceFieldName.equals("operator")) { sourceFieldName = "_operator"; } else { if(sourceFieldName.equals("_operator")) { sourceFieldName = "operator"; } } //找出目標對象中同名的屬性 Field targetField = targetClass.getDeclaredField(sourceFieldName); sourceField.setAccessible(true); targetField.setAccessible(true); String sourceFieldSimpleName = sourceField.getType().getSimpleName().toLowerCase().replace("integer", "int"); String targetFieldSimpleName = targetField.getType().getSimpleName().toLowerCase().replace("integer", "int"); //如果兩個對象同名的屬性的類型完全一致:Boolean,String,以及5種數字類型:byte,short,int,long,double,以及List if(targetFieldSimpleName.equals(sourceFieldSimpleName)) { //對于簡單類型,直接賦值 if("boolean,string,byte,short,int,long,double".indexOf(sourceFieldSimpleName)!=-1) { Object o = sourceField.get(sourceObject); if(o != null) { targetField.set(targetObject, o); //處理Specified列,或者根據Specified列對數值對象賦NULL值 try { if(toThrift) { Field targetSpecifiedField = targetClass.getDeclaredField(sourceFieldName+"Specified"); if(targetSpecifiedField != null) { targetSpecifiedField.setAccessible(true); targetSpecifiedField.set(targetObject, true); } } else { Field sourceSpecifiedField = sourceClass.getDeclaredField(sourceFieldName+"Specified"); if(sourceSpecifiedField != null && "B,S,B,I,L,D".indexOf(targetField.getType().getSimpleName().substring(0,1))!=-1 ) { sourceSpecifiedField.setAccessible(true); if(sourceSpecifiedField.getBoolean(sourceObject)==false) { targetField.set(targetObject, null); } } } } catch (NoSuchFieldException e) { //吃掉NoSuchFieldException,達到效果:如果Specified列不存在,則所有的列都賦值 } } continue; } //對于List if(sourceFieldSimpleName.equals("list")) { @SuppressWarnings("unchecked") List<Object> sourceSubObjs = (ArrayList<Object>)sourceField.get(sourceObject); @SuppressWarnings("unchecked") List<Object> targetSubObjs = (ArrayList<Object>)targetField.get(targetObject); //關鍵的地方,如果是List類型,得到其Generic的類型 Type targetType = targetField.getGenericType(); //如果是泛型參數的類型 if(targetType instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) targetType; //得到泛型里的class類型對象。 Class<?> c = (Class<?>)pt.getActualTypeArguments()[0]; if(sourceSubObjs!=null) { if(targetSubObjs==null) { targetSubObjs = new ArrayList<Object>(); } for(Object obj:sourceSubObjs) { targetSubObjs.add(convert(obj,c,toThrift)); } targetField.set(targetObject, targetSubObjs); } } continue; } } //轉換成Thrift自動生成的類:Thrift沒有日期類型,我們統一要求日期格式化成yyyy-MM-dd HH:mm:ss形式 if(toThrift) { if(sourceFieldSimpleName.equals("date")&&targetFieldSimpleName.equals("string")) { Date d = (Date)sourceField.get(sourceObject); if(d!=null) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); targetField.set(targetObject,sdf.format(d)); } continue; } } else { if(sourceFieldSimpleName.equals("string")&&targetFieldSimpleName.equals("date")) { String s = (String)sourceField.get(sourceObject); if(s!=null) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); targetField.set(targetObject,sdf.parse(s)); } continue; } } //對于其他自定義對象 targetField.set(targetObject, convert(sourceField.get(sourceObject),targetField.getType(),toThrift)); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } return targetObject; } } ~~~ ### ClassLoader 類裝載器是用來把類(class)裝載進JVM的,JVM規范定義了兩種類型的類裝載器:啟動內裝載器 (bootstrap) 和用戶自定義裝載器 (user-defined class loader) 。 JVM在運行時會產生三個ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader.。 Bootstrap是用C++編寫的,我們在Java中看不到它,是null,是JVM自帶的類裝載器,用來裝載核心類庫,如java.lang.*等。 AppClassLoader 的 Parent 是ExtClassLoader ,而 ExtClassLoader 的 Parent 為 Bootstrap ClassLoader 。? Java 提供了抽象類 ClassLoader ,所有用戶自定義類裝載器都實例化自 ClassLoader 的子類。? System Class Loader 是一個特殊的用戶自定義類裝載器,由 JVM 的實現者提供,在編程者不特別指定裝載器的情況下默認裝載用戶類 ,系統類裝載器可以通過ClassLoader.getSystemClassLoader() 方法得到。 **代碼演示如下:** ~~~ class ClassLoaderTest { public static void main(String[] args) throws Exception{ Class c; ClassLoader cl; cl = ClassLoader.getSystemClassLoader(); System.out.println(cl); while(cl != null) { cl = cl.getParent(); System.out.println(cl); } c = Class.forName("java.lang.Object"); cl = c.getClassLoader(); System.out.println("java.lang.Object's loader is " + cl); c = Class.forName("ClassLoaderTest"); cl = c.getClassLoader(); System.out.println("ClassLoaderTest's loader is " + cl); } } ~~~ # 八種基本數據類型 | 類類型 | 原生類型(primitive) | 代表意義 | |-----|-----|-----| | Boolean | boolean | 布爾 | | Character | char | 單個Unicode字符,占用兩個字節,例如'a','中',范圍0-65535 | | Byte | byte | 8位有符號整型 | | Short | short | 16位有符號整型 | | Integer | int | 32位有符號整型 | | Long | long | 64位有符號整型 | | Float | float | 單精度浮點 | | Double | double | 雙精度浮點 | 了解到數據類型,就要了解一點編碼(數字在計算機中的01編碼)的知識,計算機是用01表示所有類型的,第一位是符號位,0+1-,java中得整型都是有符號的。 對于數字,定義了原碼、反碼和補碼。 正數的原碼、反碼和補碼都是一樣的,負數的反碼是除符號位之外,所有位取反,補碼是反碼+1,以Byte類型為例: 能表示的數字范圍是-128~127,總計256個數,對于0~127,表示為:0000000~01111111,即0~2^7-1,對于負數,-128~-1,表示如下: -127~-1,其原碼分別為11111111~10000001,換算成補碼是10000001~11111111,然后10000000代表-128,-128只有補碼,沒有原碼和反碼。 **補碼的設計目的:** 使符號位能與有效值部分一起參加運算,從而簡化運算規則。補碼機器數中的符號位,并不是強加上去的,是數據本身的自然組成部分,可以正常地參與運算。 使減法運算轉換為加法運算,進一步簡化計算機中運算器的線路設計。 反碼是原碼與補碼轉換的一個中間過渡,使用較少。 所有這些轉換都是在計算機的最底層進行的,而在我們使用的匯編、c等其他高級語言中使用的都是原碼。 除此之外,JDK原碼還經常使用>>、>>>運算符,>>是有符號移位,高位補符號位,右移;>>>是無符號移為,高位補0,右移。 關于數據類型的內存存儲,如下描述一下: 原生類型,比如int i = 3,不論是變量,還是值,都是存儲在棧中的; 類類型,比如Integer i = 300,則變量是存儲在棧中,對象是存儲在堆中的一個對象,既然Integer是這樣,那么Integer a = 300,Integer b = 300,請問 a == b,是否成立? 答案是:不成立的,因為兩個對象的內存地址不同了; 既然這樣,那么Integer a = 1,Integer b = 1,請問a == b,是否成立? 答案是:成立的,這其實是Java的一個坑,我們可以看Integer對于int進行封箱操作的源碼,如下: ~~~ public static Integer valueOf(int i) { if(i >= -128 && i<= IntegerCache.high) return IntegerCache.cache[i+128]; else return new Integer(i); } ~~~ 由此可見,對于128之內的數字,是進行了Cache存儲的 ,所以在堆中的內存地址是一樣的,所以成立。 在編程中,可以對于數字前面加0x表示16進制數,加0表示8進制數,默認是10進制數;在數字的后面增加L表示long類型,默認是整型;對于浮點數,在后面增加F表示float類型,模式是double型。 對于類型轉換,比如int i=(int)1.5,會直接把小數后面的部分去掉,對于數學函數Math.round()、Math.ceil()、Math.floor(),可以把數字想象成0為水平線,負數在水平線下,正數在水平線上,ceil是轉換成天花板,floor是轉換成地板,round()是四舍五入,等于+0.5之后求floor。 # String String a = "abc",String b = "abc",a == b是成立的,這是String的編譯時優化,對于字符串常量,在內存中只存一份(JDK6是存儲在“方法區”的“運行時常量區”,JDK7是存儲在堆中); 我們對于String進一步分析: String a = "a" + "b" + "c",String b = "abc",a == b依然是成立的,原理同上; String t = "a",String a = t + "b" + "c",String b = "abc",則a == b是不成立的,因為對于變量,編譯器無法進行編譯時優化;但是a.intern() == b是成立的,因為當調用intern()方法時,是到運行時常量池中找值相對的對象,找到了b,所以a.intern() == b。 final String t = "a",String a = t + "b" + "c",String b = "abc",則a == b是成立的,因為final是不可以重新賦值的,編譯器可以進行編譯時優化; 對于String s = a + b這樣的操作,每次操作,都會在堆中開辟一塊內存空間,所以對于頻繁大量的字符操作,性能低,所以對于大量字符操作,推薦使用的StringBuffer和StringBuilder,其中StringBuffer是線程安全的,StringBuilder是1.5版本新加的,是非線程安全的。 ### 實現36進制加法,及字符串替換代碼演示 ~~~ public class RadixAndReplace { public static void main(String[] args) { //1.36進制加法(不允許使用字符串整體轉換為10進制再相加的辦法,所以只能按位加) System.out.println(add("ZZ","ZZZ")); System.out.println(add("3A","2")); //2.替換字符串(考慮替換之后符合要求的情況,只用一次循環) System.out.println(replace("acbd")); System.out.println(replace("abcd")); } //36進制加法 public static String add(String s1,String s2) { int l1 = s1.length(),l2 = s2.length(); int maxLength = l1 > l2 ? l1 : l2; int carrybit = 0; //進位 StringBuilder sb = new StringBuilder(); for(int i = 0 ; i < maxLength ; i++) { int r1 = i < l1 ? convertToNumber(s1.charAt(s1.length()-1-i)) : 0; int r2 = i < l2 ? convertToNumber(s2.charAt(s2.length()-1-i)) : 0; String r = convertToString(r1 + r2 + carrybit); carrybit = r.length() == 2 ? 1 : 0; sb.append(r.charAt(r.length()-1)); } if(carrybit == 1) { sb.append("1"); } return sb.reverse().toString(); } //把字符(A-Z代表10-36,a-z代表37-72) private static int convertToNumber(char ch) { int num = 0; if(ch >= 'A' && ch <= 'Z') num = ch - 'A' + 10; else if(ch >= 'a' && ch <= 'z') num = ch - 'a' + 36; else num = ch - '0'; return num; } //轉換數字為36進制的字符串表示 //A的ASCII碼是65,a的ASCII碼是97 private static String convertToString(int n) { if(n >= 0 && n <= 9) { return String.valueOf(n); } if(n >= 10 && n <= 35) { return String.valueOf((char)(n-10+65)); } if(n >= 36 && n <= 71) { return "1" + convertToString(n-36); } return "0"; } //替換字符串“ac”,“b”,考慮b在ac中間的情況 public static String replace(String str) { StringBuilder sb = new StringBuilder(); Boolean flag = false; //連續判斷標志位 for(int i = 0; i < str.length(); i++) { char c = str.charAt(i); if(c == 'b') continue; if(c == 'a') { flag = true; continue; } if(c == 'c' && flag) { flag = false; continue; } if(flag) { sb.append('a').append(c); } else { sb.append(c); } } return sb.toString(); } } ~~~ # 異常和錯誤 Exception和Error都繼承自Throwable對象,Exception分為兩類,RuntimeException(運行時異常,unchecked)和一般異常(checked),Error是比較嚴重的錯誤,也是unchecked。 簡單地講,checked是必須用try/catch 或者throw處理的,可以在執行過程中恢復的,比如java.io.FileNotFoundException;而unchecked異常則是不需要try/catch處理的,比如java.lang.NullPointerException。 在比較流行的語言中,Java是唯一支持checked異常,要求我們必須進行處理的語言,這有利有弊。 關于異常類、錯誤類,在JDK中定義了很多,用來描述我們的代碼可能遇到的各種類型的錯誤,這里不一一整理描述。 ### UnsupportedOperationException 舉個例子,如下: 在其他語言(比如C#),如果一個類中,某些方法還沒有完成,但是需要提供一個名字給別人調用,我們可以先對這個方法加行代碼throw new Exception("xxx"); 剛用Java時,我們可能也想只是給一行代碼throw new Exception,這是不合理的,因為:對于非RuntimeException,必須try/catch,或者在方法名后面增加throws Exception(這導致調用這個方法的地方都要try/catch,或者throws,是不合理的);所以,對于這個功能,我們正確的做法是:throws new UnsupportedOperationException("xxx"),這個是運行時異常,unchecked。 # Runtime java.lang包里有很多運行時環境相關的類,可以查看運行時環境的各種信息,比如內存、鎖、安全、垃圾回收等等。見過如下鉤子代碼,在JVM關閉時,執行一些不好在程序計算過程中進行的資源釋放工作,如下: ~~~ public class MongoHook { static void addCloseHook(){ Runtime.getRuntime().addShutdownHook( new Thread(){ @Override public void run() { MongoDBConn.destoryAllForHook() ; } }) ; } } ~~~ 關于這個推出鉤子,實際是java.lang包種的以下3個類配合完成的:Runtime、Shutdown、ApplicationShutdownHooks。 # 多線程 Thread、Runnable、ThreadLocal等,關于多線程的更多知識,可以[參閱](http://blog.csdn.net/puma_dong/article/details/37597261)。 # 接口 Clonable:生命式接口 Comparable:對象比較,泛型類 Appendable: CharSequence:統一的字符串只讀接口,共有4個方法,length()、charAt()、subSequence()、toString()。 Readable: Iterable:迭代器 # 注解類 主要在java.lang.annotation包中,注解類用@interface來進行定義,注解類的作用范圍可以是方法、屬性、包等,作用失效可以是Source、Runtime、Class。 比如Override就是一個注解類,用來標記實現接口中定義的類,其源碼如下; ~~~ package java.lang; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { } ~~~ 注解本身不做任何事情,只是像xml文件一樣起到配置作用。注解代表的是某種業務意義,spring中@Resource注解簡單解析:首先解析類的所有屬性,判斷屬性上面是否存在這個注解,如果存在這個注解,再根據搜索規則來取得這個bean,然后通過反射注入。 **注解有如下規則:** 1)所有的注解類都隱式繼承于 java.lang.annotation.Annotation,注解不允許顯式繼承于其他的接口。 2)注解不能直接干擾程序代碼的運行,無論增加或刪除注解,代碼都能夠正常運行。Java語言解釋器會忽略這些注解,而由第三方工具負責對注解進行處理。 3)注解的成員以無入參、無拋出異常的方式聲明;可以通過default為成員指定一個默認值;成員類型是受限的,合法的類型包括primitive及其封裝類、String、Class、enums、注解類型,以及上述類型的數組類型;注解類可以沒有成員,沒有成員的注解稱為標識注解,解釋程序以標識注解存在與否進行相應的處理。 代碼示例1: ~~~ package com.cl.search.utils; import java.lang.annotation.*; import java.lang.reflect.*; public class MyAnnotationTest { public static void main(String[] args) { Test test = Container.getBean(); test.loginTest(); } } @Documented @Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @interface AnnotationTest { public String nation() default ""; } interface IUser { public void login(); } class ChineseUserImpl implements IUser { @Override public void login() { System.err.println("用戶登錄!"); } } class EnglishUserImpl implements IUser { @Override public void login() { System.err.println("User Login!"); } } @AnnotationTest class Test { private IUser userdao; public IUser getUserdao() { return userdao; } @AnnotationTest(nation = "EnglishUserImpl") public void setUserdao(IUser userdao) { this.userdao = userdao; } public void loginTest() { userdao.login(); } } class Container { public static Test getBean() { Test test = new Test(); if (Test.class.isAnnotationPresent(AnnotationTest.class)) { Method[] methods = Test.class.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); if (method.isAnnotationPresent(AnnotationTest.class)) { AnnotationTest annotest = method.getAnnotation(AnnotationTest.class); System.out.println("AnnotationTest(field=" + method.getName() + ",nation=" + annotest.nation() + ")"); IUser userdao; try { userdao = (IUser) Class.forName("com.cl.search.utils." + annotest.nation()).newInstance(); test.setUserdao(userdao); } catch (Exception ex) { ex.printStackTrace(); } } } } else { System.out.println("沒有注解標記!"); } return test; } } ~~~ # java.lang.ref包 java.lang.ref 是 Java 類庫中比較特殊的一個包,它提供了與 Java 垃圾回收器密切相關的引用類。這篇IBM工程師寫的文章很好:[深入探討 java.lang.ref 包](http://www.ibm.com/developerworks/cn/java/j-lo-langref/)。 # java.lang.AutoCloseable接口 在Java7中,引入了一個新特性try-with-resource,即在try中的代碼,其資源會自動釋放,不用手工執行資源釋放操作。 要求跟在try后面的資源必須實現AutoCloseable接口,否則會報變異錯誤,代碼示例如下: ~~~ class CustomResource implements AutoCloseable { @Override public void close() throws Exception { System.out.println("進行資源釋放操作!"); } public static void main(String[] args) throws Exception { try(CustomResource r = new CustomResource()) { System.out.println("使用資源!"); } } } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看