JAVA泛型と反射

45623 ワード

一、パンチング
異なるデータ構造は同じ操作で汎型です.
1.類使用汎型
1)定義
/**
*                 ,        。         
*/
class Person<T> {
    //      ,  T  
	private T age;
    //        ,  T  
	public void setAge(T age) {
    	this.age = age;
	}
    //        ,  T  
	public T getAge() {
   		return this.age;
	}
}
2)呼び出し
public class Generics {
	public static void main(String args[]) {
    	//           ,      <>       
    	Person<String> p = new Person<String>();
    	p.setAge("3 years old");
    	//System.out.println(p.getAge());
    	printInfo(p);
        
        //<>     ,           int  Integer   
        Person<Integer> p2 = new Person<Integer>();
        p2.setAge(3);
    	//System.out.println(p2.getAge());
    	printInfo(p2);
        
    	Person<?> p3;
        //    p3  
    	p3 = p;
        //    (    )
    	//p3.setAge("4 years");
        //     
    	p3.getAge();
	}
    
    //Person>    ,        String     Integer 
	public static void printInfo(Person<?> p) {
   		System.out.println(p.getAge());
	}
}
2.方法は汎型を使う
1)定義
//         ,         
public static <T> void printInfo2(Person<T> p) {
	System.out.println(p.getAge());
}
2)呼び出し
//p      Person p = new Person();
printInfo2(p);
printInfo2(p2);
printInfo2(p3);
3.サブクラスは汎型(汎型の継承)を使用する
1)定義
//        
class Student<T> extends Person<T> {
	
}

//        
class Student2 extends Person<String> {
	//       String,          ,              
}
2)呼び出し
//      ,    
Student<Integer> s = new Student<Integer>();
//       
s.setAge(10);
//    
printInfo(s);

//      ,    
Student2 s2 = new Student2();
//           ,          String
s2.setAge("11 years");
printInfo(s2);
4.インターフェースは汎型を使用する(インターフェース:特殊な父親類)
1)定義
interface Person<T> {
	public void setAge(T age);
	public T getAge();
}
  • 呼び出し
  • //        
    class Student<T> implements Person<T> {
        T age;
        public void setAge(T age){
            this.age = age;
        }
        public T getAge() {
            return this.age;
        }
    }
    
    //           
    class Student2 implements Person<String> {
        //       ,    
    	String age;
        public void setAge(String age){
            this.age = age;
        }
        public String getAge() {
            return this.age;
        }
    }
    
    public static void main(String args[]) {
        //      ,    
    	Student<Integer> s = new Student<Integer>();
    	s.setAge(10);
        //    ,        ,             ,             
    	printInfo(s);
        
        //      ,    
    	Student2 s2 = new Student2();
    	s2.setAge("11 years");
    	printInfo(s2);
    }
    
    public static void printInfo(Person<?> p) {
    	System.out.println(p.getAge());
    }
    
    5.制限付きパンチング
    汎型を宣言する時は汎型の上限と下限を指定できます.
    1)汎型の上限:TはNumber類またはそのサブクラスしかない.
    //T   Number     Integer, Float 
    class Student<T extends Number> implements Person<T> {
    	T age;
    	public void setAge(T age){
        	this.age = age;
    	}
    	public T getAge() {
    		return this.age;
    	}
    }
    
    2)泛型の下限:super String>TはString類またはその親類だけである.
    //super       ,          (                )
    class Student<T> implements Person<T> {
    	T age;
    	public void setAge(T age){
    		this.age = age;
    	}
    	public T getAge() {
    		return this.age;
    	}
    }
    
    //         (    ?    )。       String     
    public static void printInfo(Person<? super String> p) {   
        System.out.println(p.getAge());
    }
    
    //  
    Student<String> s = new Student<String>();
    s.setAge("10");
    printInfo(s);
    
    二、反射
    通常の手順はimport「包.類」です.そしてnewの実用化によって最後に実用化されたオブジェクトがあります.
    逆にできますか?
    答えは肯定的です.私達は実用化対象からget Class方法を得ることができます.最後に完全な「パケット・クラス」の名称を得ることができます.これは逆の操作です.
    注意:反射動作では、すべての操作はObjectで行われます.クラスと配列の参照はすべてObjectで受信できます.
    1.lassオブジェクトとクラスのインスタンス化オブジェクト
    Person p=new Person();
    //  " . "  
    System.out.println(p.getClass().getName());
    
    JVMは*.クラスファイル(Javaで書いたクラス)をメモリにロードします.つまり、このクラスを記述するために、クラスのパッケージ、クラス名、構造方法、方法、属性などを含みます.このclass objectを使って、オブジェクトを具体化することができます.(メモリの中で一つのクラスに対しては一つのクラスしかないです.このクラスはクラス自体を記述するために使われています.このクラスのObjectを使って実用化対象を作成してもいいです.)三つの方法で一つのクラスのクラスのクラスを獲得することができます.
    2.クラスを獲得する
    	//1).Class> c=Class.forName(" . ");
        Class<?> c1 = null;
        try {
            c1 = Class.forName("a.b.c.d.Person");
        } catch (ClassNotFoundException e) {
            System.out.println(e);
        }
        System.out.println(c1.getName());
    
    	//2).Class> c = new X().getClass();
        Person p = new Person();
        Class<?> c2 = p.getClass();
        System.out.println(c2.getName());
    
    	//3).Class> c=X.class;
        Class<?> c3 = Person.class;
        System.out.println(c3.getName());
    
    3.配列およびその他のタイプのクラス
    配列や他のデータタイプに対しても、対応するクラス、対応するクラスがあります.
    int arr[] = {1,2,3};
    int arr2[] = {1,2,3,4};
    int arr3[][] = {{1,2,3,4},{1}};
    
    Class<?> c4 = arr.getClass();
    Class<?> c5 = arr2.getClass();
    Class<?> c6 = arr3.getClass();
    System.out.println(c4.getName());
    System.out.println(c5.getName());
    System.out.println(c6.getName());
    //           class
    System.out.println((c4 == c5));
    //                  class
    System.out.println((c4 != c6));
    
    //            ,    class
    Class<?> c7 = int.class;
    System.out.println(c7.getName());
    
    4.反射を使ってクラスの例示的なオブジェクトを取得する
    反射を使用してクラスの例示的なオブジェクト(クラスの属性と方法)を取得し、import a.b.c.d.Personの代わりに.
    //Exception         ,        InstantiationException     
    public static void main(String args[]) throws Exception {
        Class<?> c = null;
        try {
            //         Person class object
        	c = Class.forName("a.b.c.d.Person");
        } catch (ClassNotFoundException e) {
        	System.out.println(e);
        }
        
        //           (Object       ,       )
    	Object p = null;
        try {
            //           (Object       ,       (      )),                
        	p = c.newInstance();
        } catch (InstantiationException e) {
        	System.out.println(e);
        }
        
        //            
        //     String      class
        Constructor<?> con = c.getConstructor(String.class);
        //           ,   
        Object p2 = con.newInstance("123");
    }
    
    5.クラスを取得して呼び出す方法
    //      (           public  )     
    Method set = c.getMethod("setName", String.class);
    
    //           ,         ,        
    set.invoke(p2, "123");
    set.invoke(p, "abc");
    
    //      , invoke  1       null
    Method get = c.getMethod("getName");//      
    
    System.out.println(get.invoke(p));
    System.out.println(get.invoke(p2));
    
    set.invoke(p2, "123");//           ,         ,        
    set.invoke(p, "abc");
    
    //      , invoke  1       null
    Method get = c.getMethod("getName");//      
    System.out.println(get.invoke(p));
    System.out.println(get.invoke(p2));
    
    6.クラスの属性の読み込みまたは設定
    1)上記の方法でクラスの属性にアクセスしたほうがいいです.
    2)属性を直接取得することもできます.
    //(1)      ,        ,         ,        
    Field f = c.getField(String name); 
    
    //(2)           (  private,public )   name   
    Field name = c.getDeclaredField("name");
    
    //      ,         public       ,                  ,              ,               ( set  )
    name.setAccessible(true);
    
    //           name  
    name.set(p, "www");
    name.set(p2, "123");
    
    //       name  
    System.out.println(name.get(p));
    System.out.println(name.get(p2));
    
    7.反射のメリット
    プログラムの柔軟性を増やす
    クラスの名前(ファイルに入れたり、パラメータを通して伝えたりすることで、コードに死を書かずに、何かを伝えてくれれば、実用化できます.)を使って、異なるオブジェクトを具体化することができます.