1. 程式人生 > >黑馬程式設計師------java中的反射,beanutils,註解的應用。

黑馬程式設計師------java中的反射,beanutils,註解的應用。

Class類:描述眾多java類的物件。代表記憶體裡的一份位元組碼。
  有三種方式可以獲取一個類的Class檔案。
  方法一:是通過該類物件.getClass()方法。
  方法二:通過Class類的靜態方法,Class.forName("name");
  方法三:是同過類名.class方法獲取。
  對於基本型別的封裝類,還可以通過封裝類型別.TYPE方式獲取其對應的基本資料型別的class檔案,例如:Integer.TYPE == int.class ;
   Class.forName()方法的作用,一是如果指定的位元組碼已經載入到記憶體中,則獲取指定的位元組碼,
   二是如果指定的位元組碼沒有載入進記憶體,則先將其載入進記憶體,然後獲取這份位元組碼。

   Class類的常用方法:
  Class.forName(String className);  //返回與帶有給定字串名的類或介面相關聯的 Class 物件。
  getAnnotation(Class<A> annotationClass);  //如果存在該元素的指定型別的註釋,則返回這些註釋,否則返回 null。
  getAnnotations(); //返回此元素上存在的所有註釋的陣列。
  getClassLoader(); //返回該類的類載入器。
  getConstructors(); //返回一個包含某些 Constructor 物件的陣列,這些物件反映此 Class 物件所表示的類的所有公共構造方法。
  getConstructor(Class... parameterTypes);//返回一個 Constructor 物件,它反映此 Class 物件所表示的類的指定公共構造方法。
  getDeclaredConstructor(Class... parameterTypes);//返回一個私有 Constructor 物件,
                                                    該物件反映此 Class 物件所表示的類或介面的指定構造方法。
  getField(String name); //返回一個欄位。
  getMethod(String name, Class... parameterTypes); //返回一個方法。
  getDeclaredField(String name);//返回一個生命為私有的欄位。
  getDeclaredMethod(String name, Class... parameterTypes);//返回一個私有方法,第一個引數方法名,第二個引數返回型別。
  isInterface(); //指定的Class是否是一個介面。
  isPrimitive(); //指定的Class是否是一個基本型別。
  isArray();   //判斷指定的Class檔案是否表示一個數組。
  

Reflect。反射:一個類有多個組成部分,例如,成員變數,方法,構造方法等。反射就是載入類,並解刨出類的各個組成部分。

通過反射得到建構函式,方法,欄位例項。
   
   通過反射獲得一個類的空引數建構函式:
    Class clazz = Class.forName("cn.itcast.Person"); //通過反射提取該類位元組碼。
    Constructor c = clazz.getConstructor(null); //通過getConstructor方法獲取此類的空引數建構函式。
    Person p = (Person)c.newInstance(null);  //通過此建構函式建立該類物件,因為返回型別是Object,所以要進行提升。
     類的建構函式為私有時的做法:
    Class clazz = Class.forName("cn.itcast.Person"); 
    Constructor c = clazz.getDeclaredConstructor(List.class); //通過getDeclaredConstructor方法獲取此類的私有引數建構函式。
    c.setAccessible(true); //暴力反射。將此建構函式的Accessible方法設定為true,可以開啟私有的訪問許可權。
    Person p = (Person)c.newInstance(new ArrayList()); 
        通過反射獲得一個類的方法:
    Person p = new Person();
    Class clazz = Class.forName("cn.itcast.Person"); 
    Method method = clazz.getMethod("run",null);  //通過getMethod方法獲得此類的空引數run方法。
    method.invoke(p,null); //通過Class類的invoke方法執行此方法,需要傳入物件p,引數為null。
     通過反射獲取有兩個引數的方法:
    Person p = new Person();
    Class clazz = Class.forName("cn.itcast.Person"); 
    Method method = clazz.getMethod("eat",String.class,int.class);  //通過getMethod方法獲得此類兩個引數eat方法。
    method.invoke(p,"apple",5); //
     通過反射獲取一個有返回值得方法:
    Person p = new Person();
    Class clazz = Class.forName("cn.itcast.Person"); 
    Method method = clazz.getMethod("run",String.class,int[].class);  //通過getMethod方法獲得此類的空引數run方法。
    Class[] cs = method.invoke(p,"pao",new int[]{1,2,3}); //通過Class類的invoke方法執行此方法,需要傳入物件p,引數為null。
     通過反射獲取一個私有的方法:
    Person p = new Person();
    Class clazz = Class.forName("cn.itcast.Person"); 
    Method method = clazz.getDeclaredMethod("run",InputStream.class);  //通過getMethod方法獲得此類的InputStream引數run方法。
    method.setAccessible(true);  //暴力反射。
    method.invoke(p,new FileInputStream("c:\\1.txt")); 
     通過反射獲取一個靜態的方法:
    //Person p = new Person();
    Class clazz = Class.forName("cn.itcast.Person"); 
    Method method = clazz.getMethod("run",String.class); 
    method.invoke(null,"isrun"); 
     反射main函式
     //Person p = new Person();
    Class clazz = Class.forName("cn.itcast.Person"); 
    Method method = clazz.getMethod("main",String[].class);  
    method.invoke(null,(Object)String[]{"aaa","bbb","ccc"}); 
   通過反射獲得一個類的欄位:
     反射一個公有的欄位:
      Person p = new Person();
     Class clazz = Class.forName("cn.itcast.Person");
     Field f = clazz.getField("name");  //通過名稱獲取欄位。
     Class type = f.getType(); //獲取該欄位的型別。
     String str = (String)f.get(p);  //通過get方法獲取欄位的值。
     f.set(p,"abc");  //給p物件的f欄位賦值。
     f.get(p);  //獲取p物件f欄位的值。
     反射一個私有的欄位:
     Person p = new Person();
     Class clazz = Class.forName("cn.itcast.Person");
     Field f = clazz.getDeclaredField("name");  //通過名稱獲取欄位。
     f.setAccessible(true);
     Class type = f.getType(); //獲取該欄位的型別。
     String str = (String)f.get(p);  //通過get方法獲取欄位的值。
     f.set(p,"abc");  //給p物件的f欄位賦值。
     f.get(p);  //獲取p物件f欄位的值。
     反射一個靜態私有的欄位:
     Person p = new Person();
     Class clazz = Class.forName("cn.itcast.Person");
     Field f = clazz.getDeclaredField("name");  //通過名稱獲取欄位。
     f.setAccessible(true);
     Class type = f.getType(); //獲取該欄位的型別。
     String str = (String)f.get(p);  //通過get方法獲取欄位的值。
     f.set(p,"abc");  //給p物件的f欄位賦值。
     f.get(p);  //雖然是靜態方法,但是此處需要傳入一個物件才可獲取。
     用反射將一個物件中的所有字串欄位中的一個字母替換成另一個字母。
      private static void changeStringValue(Object obj){
        Field[] fields = obj.getClass.getFields();
        for(Field field : fields){
          if(field.getType()==String.class){
            String oldValue = (String)field.get(obj);
            String newValue = oldValue.replace('b','a');
            field.set(obj,newValue);
          }
        }
      }
       通過反射的到一個集合上的泛型。通過反射無法直接得到一個集合上到底用到了什麼泛型,
    但是可以將這個集合作為一個方法的引數,通過獲得此方法的引數列表間接的到引數上定義的泛型。
    public static void applyType(ArrayList<Integer> list){
    System.out.println("pao.....");
   }
   Method method = reflect1.class.getMethod("applyType", ArrayList.class);
    Type[] types =  method.getGenericParameterTypes();
    ParameterizedType pType = (ParameterizedType) types[0];
    System.out.println(pType.getRawType());
    System.out.println(pType.getActualTypeArguments()[0]);
     
內省:IntroSpector,主要用於對JavaBean進行操作,JavaBean是一種特殊的java類,如果一個類中有get set方法,那麼
    這個類就可以被當做一個JavaBean來操作。一個類的屬性是由其get set方法決定的。
javabean:
    通過內省的方法得到一個類的get方法:
    例如:
          public static Object getProperty(Object obj,String propertyName) throws Exception{
     //通過儲存器操作propertyName屬性的set和get方法。
     PropertyDescriptor pd = new PropertyDescriptor(propertyName, obj.getClass());
     //獲取propertyName欄位的讀取方法。
     Method getMethod = pd.getReadMethod();
     //讀取obj物件propertyName欄位上的值。
     Object retValue = getMethod.invoke(obj);
     return retValue;
   }
   public static Object getProperty1(Object obj,String propertyName) throws Exception{
     BeanInfo bInfo= Introspector.getBeanInfo(obj.getClass());
     PropertyDescriptor[] propertyDescriptors = bInfo.getPropertyDescriptors();
     String reValue = null;
     for(PropertyDescriptor pd : propertyDescriptors){
       if(pd.getName().equals(propertyName)){
       Method getMethod = pd.getReadMethod();
       reValue = (String) getMethod.invoke(obj);
       break;
       }
     }
     return reValue;
   }
   
 
Beanutils工具包:是Apache公司提供的用於操作JavaBean的工具包,此工具包簡化了對JavaBean的操作。
   例如,使用BeanUtils設定和獲取某個物件的某個屬性。
     BeanUtils.setProperty(pt1,"x","9");  //設定pt1這個物件的x這個屬性,值為9。
     BeanUtils.getProperty(pt1,"x");  //獲取pt1這個物件x欄位的屬性值。
   jdk7的一個新特性:通過BeanUtils設定Map的屬性。
     Map map = {name:"zxx",age:"18"};
     BeanUtils.setProperty(map,"name","lhm"); 
   使用PropertyUtils設定和獲取一個物件的屬性。
     PropertyUtils.setProperty(pt1,"x",9);
     PropertyUtils.getProperty(pt1,"x");
     //通過PropertyUtils同樣也可以達到BeanUtils的設定和獲取效果,兩者的不同之處在於
     //PropertyUtils設定物件的屬性時,需要使用物件的本身型別,而BeanUtils不論物件本身是什麼型別
     //都需要使用字串。獲取物件屬性時PropertyUtils返回的物件本身的型別,而BeanUtils則都返回字串。 
     

BeanUtils只支援8種資料型別的轉換,其他型別須自定義型別轉換器。
例如:
ConvertUtils.register(new Converter(){
  public Object convert(Class Type,Object value){  //覆寫介面中的方法。
    if(value==null)   //判斷傳入的值是否為空。
      retrun null;
    if(!(value instanceof String)){
      throw new ConversionException("請傳入String型別的資料");
    }
    String str = (String)value;
    if(str.trim().equals(""))
      return null;
    SimpleDateFormat adf = new SimpleDateFormat("yyyy-MM-dd");  //定義一個格式化的格式。
    try{
      return df.parse(str);  //格式化時可能發生異常,不能丟擲比父類更多的異常。
    }
    catch(ParseException e){
      throw new RuntimeException(e);  
    }
  }
},Date.class);


也可以用已定義號的轉換器:例如:
ConvertUtils.reqister(new DateLocalConverter(),Date.class);

將Map集合中的資料填充到指定的Bean中:
Map map = new HashMap();
map.put("name","zhangsan");
map.put("password","123");
map.put("age","23");
map.put("birthday","1982-2-22");
ConvertUtils.register(new DateLocalConverter(),Date.class);
Person bean = new Person();
BeanUtils.populate(bean,map);  //將map集合中的資料填充到bean中。

     
    
 
 
註解的自定義方法:
@interface 註解名{}
例如:
  @Retention(RetentionPolicy.RUNTIME) //元註解。RUNTIME表示的是,讓註解保留到執行時。
                    //除此之外,還有兩個一個是:@Retention(RetentionPolicy.CLASS)儲存到位元組碼階段。
                    //另個一個是:@Retention(RetentionPolicy.SOURCE)儲存到原始檔階段。
  public @interface ItcastAnnotation{}
  
  在一個自定義註解上加上元註解:@Target((ElementType.METHOD),(ElementType.TYPE))  //表示此註解可以作用的範圍。檢測某一個類上是否有某個註解:
  類名.class.isAnnotationPresent(註解名.class);  //先得到該類的位元組碼,在呼叫位元組碼的isAnnotationPresent方法。
                得到某一個註解的方法:
  getAnnotation(註解名.class);
為註解新增屬性:
//1,定義一個註解類。
public @interface ItcastAnnotation{
  //給註解定義一個String屬性,並設定預設值。
  String color defult "bule";
  String value();
  //定義一個數組屬性,並設定預設值。
  int[] arrayAttr() defult {3,4,5};
}

註解的應用例項:
   @Retention(RetentionPolicy.RUNTIME)
   public @interface ItcastAnnotation{
     //為color屬性設定預設屬性為blue。
     String coloer() default "blue"; 
     String value(); 
     int[] arrayA default {3,4,5};
     //定義一個列舉型別的屬性。
     EnumTest.TrafficLamp lamp() default TrafficLamp.RED;
     //定義一個註解屬性,併為其指定預設值。
     MetaAnnotation annotationAttr(); default @MetaAnnotation("arrs");
   }
   public @interface MetaAnnotation{
     String value();
   } 
   @ItcastAnnotation(color="red",value="abc",arrayA={1,2,3})
   public class AnnotationTest{
     //因為color有預設屬性,所以可以不用設定。當只有一個屬性需要設定時,可以不寫屬性名和等號。
     @ItcastAnnotation("xyz")
     public static void main(String[] args){
       //判斷某一個類上是否有某個註解。
       if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){
         //通過反射獲取指定的註解。
         ItcastAnnotation annotation = (ItcastAnotation)AnnotationTest.class.getAnnotatio(ItcastAnnotation.class);
         //呼叫註解的屬性。
         System.out.println(annotation.color());
       }
     }
   }   
   */

類載入器:ClassLoader
自定義類載入器需要繼承ClassLoader並覆寫finedClass()方法。
自定義一個類載入器的例項:
public class MyClassLoader extends ClassLoader {

 /**
  * @param args
  */
 public static void main(String[] args)throws Exception {
  // TODO Auto-generated method stub
  
 }
 //自定義一個加密方法,使用自定義類載入器可以解密被此加密方法加密過的類。
 private static void cypher(InputStream ips,OutputStream ops)throws Exception{
  int b = -1;
  while((b=ips.read())!=-1){
   ops.write(b^0xff);
  }
 }
 private String classDir;
 
 @Override
 protected Class<?> findClass(String name) throws ClassNotFoundException {
  String classFileName = classDir+"\\"+name+".class";
  try {
   //讀取此檔案,並解密。
   FileInputStream fis = new FileInputStream(classFileName);
   ByteArrayOutputStream bos = new ByteArrayOutputStream();
   cypher(fis,bos);
   fis.close();
   byte[] bytes = bos.toByteArray();
   System.out.println("aabbb");
   return defineClass(bytes,0,bytes.length);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return super.findClass(name);
 }
 
 public MyClassLoader(){
  
 }
 //傳入需要載入的類檔案的相對路徑
 public MyClassLoader(String classDir){
  this.classDir = classDir;
 }
}

 

相關推薦

黑馬程式設計師------java反射beanutils註解應用

Class類:描述眾多java類的物件。代表記憶體裡的一份位元組碼。 有三種方式可以獲取一個類的Class檔案。 方法一:是通過該類物件.getClass()方法。 方法二:通過Class類的靜態方法,Class.forName("name"); 方法三:

黑馬程式設計師----javastatic,final,abstract的用法和區別

    ---------------------- android培訓、java培訓、期待與您交流! ----------------------         一, 首先,static    

黑馬程式設計師——java反射機制

------- android培訓、java培訓、期待與您交流! ---------- 前言:通過觀看畢向東老師的java基礎視訊,查漏補缺,將一些自己掌握的還不牢固的知識寫出來,希望和大家交流分享。 一、反射技術是java在執行的時候獲取類的基本資訊。 反射技術大大提高了

黑馬程式設計師-Java面向抽象和麵向介面設計

一、“開閉原則” 在討論面向抽象和麵向介面之前,先來粗略瞭解下“開閉原則”。 最近在搜尋問題的時候總是會看到有人提到“開閉原則”的設計思想。今天就稍微總結下JavaSE中最能體現”開閉”思想的兩部分。我覺得在學習早期或多或少的滲透理解一些思想,這種潛

黑馬程式設計師 Java高新技術--反射和內省

1.框架與框架要解決的核心問題:比如:我做房子賣給使用者住,由使用者自己安裝門窗和空調,我做的房子就是框架,使用者需要使用我的框架,把門窗插入進我提供的框架中。框架和工具類有區別,工具類被使用者的類呼叫,而框架則是呼叫使用者提供的類。2.框架要解決的核心問題:我在寫框架(房子)時,你這個使用者可能還在上小學,

黑馬程式設計師 java高新技術 反射

---------- android培訓、java培訓、期待與您交流! ---------- 一、Class類     Class是Java程式中各個Java類的總稱;它是反射的基石,通過Class類來使用反射。    物件的建立和使用:       建立例項物件:

黑馬程式設計師--java高新技術----反射

---------------------- ASP.Net+Android+IOS開發、.Net培訓、期待與您交流! ---------------------- 什麼是反射?         反射就是把一個類中的各種元素對映成一個類。 得到一個類中的元素都是從這個

黑馬程式設計師--Java基礎--awt詳解以及簡單應用

GUI 圖形使用者介面 CLI 命令列使用者介面 Java為GUI提供的物件存在java.Awt和Javax.Swing兩個包中. Java當中如何完成圖形化介面的製作呢? AWT:abstract Window ToolKit.需要呼叫本地

黑馬程式設計師--java高新技術 25--列舉反射

---------------------- ASP.Net+Android+IO開發S、.Net培訓、期待與您交流! ---------------------- /*1.5 新特性總結: 靜態匯入 可變引數 增強for(foreach) 基本資料的自動拆裝箱 列舉 泛

黑馬程式設計師----Java基礎之反射

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師----Java基礎之IO包其它類

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師——Java 反射技術

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 一、概述  1.理解反射:   反射就是把java類中的各種成分對映成相應的java類。  2.反射中常用的類:   Class類:是反射的基石,由它可

黑馬程式設計師——java-幾個常用的類(ObjectScannerStringStringBuffer/StringBuilder)

1 Object類 Object類層次結構的根類,所有的類都直接或間接的繼承自該類 Object類中常用的方法 public String toString()---//返回該物件的字串表示 public final Class getCla

黑馬程式設計師——java的IO之字元流位元組流,轉換流

------- android培訓、java培訓、期待與您交流! ---------- 前言:通過觀看畢向東老師的java基礎視訊,查漏補缺,將一些自己掌握的還不牢固的知識寫出來,希望和大家交流分享。 1.IO概述 1、相關概念:IO:即Input和Output的縮寫。

黑馬程式設計師-java高新技術(反射

一、反射 1、定義: Java程式中的各個Java類屬於統一類事物,描述這類事物的Java類名就是Class。反射機制指的是程式在執行時能夠獲取自身的資訊。在java中,只要給定類的名字,那麼就可以通過反射機制來獲得類的所有資訊。 2、優點和缺

黑馬程式設計師-java基礎加強-反射的深入講解

-------------------------ASP.Net+Unity開發、.Net培訓、期待與您交流!-------------------------- 透徹分析反射的基礎_Class類 Class類1、定義java程式中的各個java類也屬於同一類事物,而描述這

黑馬程式設計師---java基礎加強 反射的深入理解

=================第5單元:反射的深入講解=============== 17.透徹分析反射的基礎_Class類 反射的基礎: Class也就是每個java源程式通過編譯後生成的檔案載入進入記憶體的那個位元組碼檔案, 獲取到該位元組碼,就可以獲取

黑馬程式設計師--java基礎--String,StringBufferStringBuilde

------- android培訓、java培訓、期待與您交流! --------- String的兩種例項化方式: 方式1: String s1 = "abc"; //s1是一個類型別變數,"abc"是一個物件 //字串最大的特點:String一旦初始化

黑馬程式設計師》 使用反射獲取位元組碼檔案的方法

public class ReflectMethod { /** * 方法的反射 * @param args */ public static void main(String[] args) throws Exception { String str

黑馬程式設計師--java高新技術 26--javaBean,泛型類載入器代理spring小框架

---------------------- ASP.Net+Android+IO開發S、.Net培訓、期待與您交流! ---------------------- /*設計模式: Singleton: 單例模式 Factorty: 工廠模式 Iterator: 迭代器模