Class 類|類加載器|AOP|加密|JUnit

 
2006-8-25 學習總結
1、類 Class<T>
       Class 類的實例表示正在運行的 Java 應用程序中的類和接口。枚舉是一種類,註釋是一種接口。每個數組屬於被映射爲 Class 對象的一個類,所有具有相同元素類型和維數的數組都共享該 Class 對象。基本的 Java 類型(booleanbytecharshortintlongfloatdouble)和關鍵字 void 也表示爲 Class 對象。
Class 沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的 defineClass 方法自動構造的。
以下示例使用 Class 對象來顯示對象的類名:
    void printClassName(Object obj) 
    {
         System.out.println("The class of " + obj +" is " + obj.getClass().getName());
}
說明:類可以申明一個對象,即明一個具體的事物,平時申明對象的類也是一個事物,因此有一種類來申明這些類,這個類的名字就叫Class,他是所有類最高級別。
2、類加載器
Java編譯後的java字節碼class文件怎麼加載到內存中的呢,其實他們是通過一個繼承了ClassLoader類的java類加載到內存中的,然後這些加載類最後是通過一個本地c編寫的加載器(Bootstrap)加載入內存中的,Bootstrap加載rt.jar這個包,而由這個加載器加載的調用.getClassLoader返回NULL。常用到的類加載器有AppClassLoader它用於加在classpath下的類,ExtClassLoader裝<JAVA_HOME>/jre/lib/ext目錄下的jar包,而AppClassLoader是ExtClassLoader的子類,所以AppClassLoader不能裝載ExtClassLoader下的類。(注意:ClassLoader是委託父級類裝載器加載的,一個類加載器在加載字節碼時首先不是自己加載,而是找他的父加載器加載,如果父加載器可以加載那麼就由父加載器加載,這就是junit的爲什麼不能放到<JAVA_HOME>/jre/lib/ext下的原因)。
Important: don't install the junit.jar into the extension directory of your JDK installation. If you do so the test class on the files system will not be found.(引用)
       類 ClassLoader:
              類加載器是負責加載類的對象。ClassLoader 類是一個抽象類。
ClassLoader 類使用委託模型來搜索類和資源。每個 ClassLoader 實例都有一個相關的父類加載器。需要查找類或資源時,ClassLoader 實例會在試圖親自查找類或資源之前,將搜索類或資源的任務委託給其父類加載器。虛擬機的內置類加載器(稱爲 "bootstrap class loader")本身沒有父類加載器,但是可以將它用作 ClassLoader 實例的父類加載器。
findClass:      protected Class<?> findClass(String name)
                                 throws ClassNotFoundException
loadClass:      protected Class<?> loadClass(String name, boolean resolve)
                                         throws ClassNotFoundException
使用指定的二進制名稱來加載類。此方法的默認實現將按以下順序搜索類:
1.     調用 findLoadedClass(String) 來檢查是否已經加載類。
2.     在父類加載器上調用 loadClass 方法。如果父類加載器爲 null,則使用虛擬機的內置類加載器。
3.     調用 findClass(String) 方法查找類。
如果使用上述步驟找到類,並且 resolve 標誌爲真,則此方法將在得到的 Class 對象上調用 resolveClass(Class) 方法。
鼓勵用 ClassLoader 的子類重寫 findClass(String),而不是使用此方法loadClass中也是調用findClass
4、AOP:
AOPOOP的延續,是Aspect Oriented Programming的縮寫,意思是面向方面編程。面向對象將應用程序分解成各個層次的對象,而AOP將程序分解成各個方面 或者說 關注點這使得可以模塊化諸如事務管理等這些橫切多個對象的關注點。
5、Java單元測試——JUnit
JUnit就是一個測試Java程序的類,同時他提供了Java程序員一個寫測試代碼的規範。
JUnit是由 Erich Gamma Kent Beck 編寫的一個迴歸測試框架(regression testing framework)。用於Java開發人員編寫單元測試之用。
迴歸測試就是你不斷地對所編寫的代碼進行測試:編寫一些,測試一些,調試一些,然後循環這一過程。
所謂框架就是Erich Gamma Kent Beck 定下了一些條條框框,你編寫的測試代碼必須遵循這個條條框框:繼承某個類,實現某個接口。其實也就是我們前面所說的規範。
6、注意:在拋出異常時,子類拋出異常只能是父類拋出異常的子類。
7、加密,自定義類裝載器加載並運行
Tag:java 加密 (引用)         
以MyClassLoader.java爲例,先加密Test.class文件,再用自定義類裝載器加載並運行。
import java.io.*;
import java.lang.reflect.*;
public class MyClassLoader extends ClassLoader
{
       private String path = null;
       public MyClassLoader(String path) throws Exception//檢查文件是否存在
       {
              File f = new File(path);
              if(!f.isDirectory())
              {
                     throw new RuntimeException(path + " is not a directory");
              }
              this.path = path;
       }
      
       public Class findClass(String name) //throws Exception //爲什麼不能拋出
       {
              try
              {
                     byte[] datas = loadClassData(name);
                     return defineClass(name, datas, 0, datas.length);
              }
              catch(Exception e)
              {
                     return null;
              }
       }
 
       private byte[] loadClassData(String name) throws Exception
       {
              File f = new File(path, name + ".class");//不用檢查目錄最後是否有目錄分割符
              FileInputStream fis = new FileInputStream(f);
              ByteArrayOutputStream bas = new ByteArrayOutputStream();
              cypher(fis,bas);
              byte [] datas = bas.toByteArray();
              bas.close();
              fis.close();
              return datas;
       }
      
       public static void cypher(InputStream istream,OutputStream ostream) throws Exception
       {
              //下面這段代碼可能遇到255的字節,當成byte就成了-1
              /*byte b = 0;
              while((b = (byte)istream.read()) != -1)
              {
                     ostream.write(b ^ 0xff);
              }*/
             
              int b = 0;
              while((b = istream.read()) != -1)
              {
                     ostream.write(((byte)b) ^ 0xff);
              }
       }
 
       public static void main(String [] args) throws Exception
       {
 
              //下面省略了錯誤檢查
              if(!args[0].endsWith("class"))
              {
                     ClassLoader loader = new MyClassLoader(args[1]);
                     Class cls = loader.loadClass(args[0]);
                     //Method m = cls.getMethod("test",null);//在jdk1.5中報警告,爲什麼?
                     Method m = cls.getMethod("test");
                     //m.invoke(cls.newInstance(),null);
                     m.invoke(cls.newInstance());
                     //((Test)cls.newInstance()).test();
                     return;
              }
              else
              {           
                     FileInputStream fis = new FileInputStream(args[0]);         
                     File f = new File(args[1], new File(args[0]).getName());//不用檢查目錄最後是否有目錄分割符
                     FileOutputStream fos = new FileOutputStream(f);            
                     cypher(fis,fos);
                     fis.close();
                     fos.close();
              }
       }
}
測試類:
       package cn.itcast;
public class Test extends java.util.Date
{
              public String toString()
              {
                     return "xixihehe";
              }
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章