下面來介紹一下Java的高級應用有哪些。java
Java高級應用數組
第一講 類加載緩存
(一).類加載函數
類加載器是一個特殊的類,負責在運行時尋找和加載類文件。Java容許使用不一樣的類加載器,甚至是自定義類加載器。Java程序包含不少類文件,每個都與單個Java類相對應,這些類文件隨時須要隨時加載。類加載器從源文件(一般是.class或.jar文件)得到不依賴平臺的字節碼,而後將它們加載到JVM內存空間,因此它們能被解釋和執行。默認狀態下,應用程序多的每一個類由java.lang.ClassLoader加載。由於它能夠被繼承,因此能夠自由地增強其功能。測試
1.1 認識Classthis
Java程序在運行時,運行時系統一直對全部的對象進行運行時類型標識,這項信息記錄了每一個對象所屬的類。JVM一般使用運行時類型信息定位正確方法去執行,用來保存這些類型信息的類是Class類。Class類封裝一個對象和接口運行時的狀態,當裝載類時,Class類型的對象自動建立。spa
JVM爲每種類型管理一個獨一無二的Class對像,即每一個類(型)都有一個Class對象。運行程序時,JVM首先檢查所要加載的類對應的Class對象是否已經加載,若是沒有加載,JVM就會根據類名查找.class文件,並將其Class對象載入。code
Class無公共構造方法,其對象是在加載類時由JVM以及經過調用類加載器中的defineClass方法自動構造的,所以不能顯示地聲明一個Class對象。每一個類都有一個class屬性,能夠直接以類.class方式訪問,也能夠經過實例訪問,但實例得到class對象必需要調用getClass()方法才能夠。對象
1.2 Class類的方法blog
static Class forName(String name)————返回指定類名的Class對象(注意靜態的)
Object newInstance()————調用缺省構造方法,返回該Class對象的一個實例
getName()————返回此Class對象所表示的實體(類、接口、數組、基本類型或void)名稱
Class []getInstance————獲取當前Class對象的接口
ClassLoader getClassLoader()————返回該類的加載器
Class getSuperclass()————返回表示此Class所表示的實體的超類的Class
1.3 實踐
下面經過繼承關係演示Class類的使用,首先定義Person類及其子類Student類。
1 package com.itsuper.p1.classdemo; 2 public class Person { 3 String name; 4 //若是使用Class的newInstance()構造對象,則須要提供缺省的構造方法 5 public Person() { 6 7 } 8 public Person(String name) { 9 this.name = name; 10 } 11 }
1 package com.itsuper.p1.classdemo; 2 public class Student extends Person { 3 int age; 4 public Student() { 5 6 } 7 public Student(String name, int age) { 8 super(name); 9 this.age = age; 10 } 11 }
編寫測試代碼,使用Class類實現Student對象的建立
1 package com.itsuper.p1.classdemo; 2 3 public class ClassDemo { 4 5 /** 6 * 演示Class類 7 * @param args 8 */ 9 public static void main(String[] args) { 10 String className = "com.itsuper.p1.classdemo.Student"; 11 //由於調用forName()方法可能拋出異常,須要放到try中 12 try { 13 //調用靜態方法forName()獲取字符串對應的Class對象 14 Class c1 = Class.forName(className); 15 //構造一個對象,可是相應的構造類中必須提供缺省的構造函數,才能使用Class類的缺省構造方法 16 Object obj = c1.newInstance(); 17 //經過類.class,獲取Class實例 18 System.out.println(Student.class); 19 //經過具體對象,獲取Class實例,但具體對象獲取Class實例必須調用getClass()方法 20 System.out.println(obj.getClass().getName()); 21 //判斷類.class 與 具體對象獲取Class實例是不是統一引用地址 22 if(obj.getClass()==Student.class){ 23 System.out.println("The Class is Student class!"); 24 } 25 System.out.println("----------------"); 26 27 //獲取當前Class對象的父類Class對象 28 Class superClass = c1.getSuperclass(); 29 Object obj2 = superClass.newInstance(); 30 System.out.println(obj2.getClass().getName()); 31 32 //繼續獲取父類的Class對象 33 Class furtherClass = superClass.getSuperclass(); 34 Object obj3 = furtherClass.newInstance(); 35 System.out.println(obj3.getClass().getName()); 36 37 } catch (Exception e) { 38 // TODO Auto-generated catch block 39 e.printStackTrace(); 40 } 41 } 42 }
運行結果:
class com.itsuper.p1.classdemo.Student com.itsuper.p1.classdemo.Student The Class is Student class! ---------------- com.itsuper.p1.classdemo.Person java.lang.Object
注意: 調用Class.froName(name)方法時,因爲指定的類名可能不存在,須要將其放到try...catch語句塊中
JVM爲每種類型管理一個獨一無二的Class對象。所以可使用==操做符來比較類對象。經過運行結果分析,能夠肯定obj.getClass()和Student.class事實上是JVM管理的同一個Class對象。
第二講 ClassLoader
(二). 認識ClassLoader
類裝載器是用來把類(class)裝載進JVM的。JVM規範定義了兩種類型的類裝載器:啓動內裝載器(bootstap)和用戶自定義裝載器(user-defined class loader).
自底向上檢查類是否已裝載 |
Bootstap Classloader | 自頂向下嘗試加載類 |
Extension Classloader | ||
System Classloader |
Bootstap(啓動類加載器)是JVM自帶的類裝載器,負責裝載Java平臺核心類庫,如java.lang.*等,在Java中看不到他,是null
Extension(擴展類加載器) 主要負責jdk_home/lib/ext目錄下的jar包或—Djava.ext.dirs指定目錄下的jar包裝入工做
System(系統類加載器) 主要負責java-classpath/-Djava.class.path所指定的目錄下的類與jar包裝入工做
java提供了抽象類ClassLoader,全部用戶自定義類裝載器都實例化自ClassLoader的子類。ClassLoader是一個特殊的用戶自定義類裝載器,有JVM的實現者提供,如不特殊指定,其將做爲系統缺省的裝載器。
實踐:
代碼演示類加載機制的層次關係
1 public class ClassLoaderDemo { 2 public static void main(String[] args){ 3 ClassLoader classloader; 4 classloader = ClassLoader.getSystemClassLoader(); 5 System.out.println(classloader);//sun.misc.Launcher$AppClassLoader@1016632 6 7 while(classloader!=null){ 8 classloader = classloader.getParent(); 9 System.out.println(classloader);//sun.misc.Launcher$ExtClassLoader@dc6a77 10 // null 11 }//此過程在自底向上判斷類加載器 12 13 try{ 14 Class c1 = Class.forName("java.lang.Object");//返回Object的對象 15 classloader = c1.getClassLoader();//得到該對象的類加載器 16 System.out.println("java.lang.Object`s loader is " + classloader); 17 c1 = Class.forName("com.itsuper.p1.classdemo.ClassLoaderDemo"); 18 classloader = c1.getClassLoader(); 19 System.out.println("ClassLoaderDemo`s loader is " + classloader); 20 }catch (Exception e) { 21 System.out.println("Check name of the class"); 22 } 23 } 24 }
運行結果:
sun.misc.Launcher$AppClassLoader@1016632 //表示系統類加載器實例化自sun.misc.Launcher$AppClassLoader sun.misc.Launcher$ExtClassLoader@dc6a77 //表示系統類裝載器的parent實例化自類sun.misc.Launcher$ExtClassLoader null //表示系統類加載器的parent的parent爲bootstap,沒法直接獲取 java.lang.Object`s loader is null //表示類Object是由bootstap裝載的 ClassLoaderDemo`s loader is sun.misc.Launcher$AppClassLoader@1016632 //表示用戶本身寫的類是由系統類裝載器裝載的
2.1 加載過程
ClassLoader加載類時,首先檢查緩存中是否有該類
(1) 如有直接返回
(2) 若無,請求父類加載
(3) 若是父類沒法加載,則從bootstap classLoader加載
而後加載指定類,搜索的順序是:
(1) 尋找class文件(從與此classloader相關的類路徑中尋找)
(2) 從文件載入class
(3) 找不到則拋出ClassNotFoundException
第三講 instanceof
(三). 認識instanceof運算符
Java的多態性機制致使了引用變量的聲明類型和其實際引用的類型可能不一致,在結合動態方法調度機制能夠得出結論:聲明爲同種類型的兩個引用變量調用同一個方法時也可能會有不一樣的行爲。爲更準確的鑑別一個對象的真正類型,Java語言引入了instanceof操做符。
3.1 定義
instanceof關鍵字是用於判斷一個引用類型變量所指向的對象是不是一個類(或接口、抽象類、父類)的實例。
3.2 使用格式
<引用類型變量> instanceof <引用類型>
注意:該表達式爲Boolean類型的表達式,當instanceof左側的引用類型變量所引入對象的實際類型是其右側給出的類型或是其子類類型時,整個表達式的結果爲true,不然爲false。例如mi instanceof MyClass。
3.3 補充
3.4 實踐1
下面經過繼承關係來演示instanceof關鍵字的使用
1 public class InstanceofDemo { 2 3 public static void typeof(Object obj) { 4 if(obj instanceof Student){ 5 System.out.println("Student!"); 6 } 7 if(obj instanceof Person){ 8 System.out.println("Person!"); 9 } 10 } 11 public static void main(String[] args) { 12 Person pobj1 = new Person("tom"); 13 Student sobj1 = new Student("Daming",5); 14 typeof(pobj1); 15 System.out.println("-------------------"); 16 typeof(sobj1); 17 System.out.println("-------------------"); 18 Person pobj2 = new Person("rose"); 19 Student sobj2 = new Student("xiaoli",10); 20 typeof(pobj2); 21 System.out.println("-------------------"); 22 typeof(sobj2); 23 System.out.println("-------------------"); 24 String[] str = new String[2]; 25 if(str instanceof String[]){ 26 System.out.println("true! "); 27 } 28 } 29 }
運行結果:
Person! ------------------- Student! Person! ------------------- Person! Student! Person! ------------------- true!
經過對比結果,有什麼發現呢?再仔細的品味一下 這句話吧! 「instanceof左側的引用類型變量所引入對象的實際類型是其右側給出的類型或是其子類類型時,整個表達式的結果爲true」
實踐2
定義一個接口IBase和兩個類Derive,Derive1來演示instanceof用法
1 //定義Interface接口IBase 2 interface IBase{ 3 public void print(); 4 } 5 6 //定義Derive類實現IBase接口 7 class Derive implements IBase{ 8 int b; 9 public Derive(int b) { 10 super(); 11 this.b = b; 12 } 13 //實現接口的抽象方法 14 public void print(){ 15 System.out.println("In Derive!"); 16 } 17 } 18 19 //定義Derive的子類Derive1 20 class Derive1 extends Derive{ 21 int c; 22 public Derive1(int b, int c) { 23 super(b); 24 this.c = c; 25 } 26 public void print(){ 27 System.out.println("In Derive1!"); 28 } 29 } 30 31 public class InstanceDemo2 { 32 //判斷對象類型 33 public static void typeof(Object obj){ 34 if(obj instanceof Derive){ 35 Derive der = (Derive)obj; 36 der.print(); 37 }else if(obj instanceof Derive1){ 38 Derive1 der1 = (Derive1)obj; 39 der1.print(); 40 } 41 } 42 43 public static void main(String[] args) { 44 IBase b1 = new Derive(4);//父類引用指向子類對象 45 IBase b2 = new Derive1(4,5); 46 System.out.print("b1 is "); 47 //調用typeof()判斷b1對象類型 48 typeof(b1); 49 System.out.print("b2 is "); 50 //調用typeof()判斷b2對象類型 51 typeof(b2); 52 } 53 }
運行結果:
b1 is In Derive! b2 is In Derive1!