Java基礎----反射Reflect---Field

     Field  java.lang.reflect  表示一個字段html

     在Java反射中,能夠經過Class對象用如下幾種方法獲取Field:
    a、public Field[] getDeclaredFields()  只獲取本類全部的字段  private、protected、default、public
public class ParentClass {
    
	private   String s_pri_p = "parent_private";
	protected String s_pro_p = "parent_protected";
	          String s_def_p = "parent_default";
	public    String s_pub_p = "parent_public";
	
	private   String sc_pri_p = "parent_static_private";
	protected String sc_pro_p = "parent_static__protected";
	          String sc_def_p = "parent_static__default";
	public    String sc_pub_p = "parent_static__public";
}

  

public class SubClass extends ParentClass {

	private   String s_pri = "private";
	protected String s_pro = "protected";
	          String s_def = "default";
	public    String s_pub = "public";

	private   static String sc_pri = "private";
	protected static String sc_pro = "protected";
	          static String sc_def = "default";
	public    static String sc_pub = "public";
	
	public    List<String> actual  = null;
	public static void main(String[] args) {
		try {
		    Class<?> clz = SubClass.class;
		    SubClass sub = new SubClass();
		   Field[] fields = clz.getDeclaredFields();//獲取全部訪問權限爲public的成員變量
		    for (Field field : fields) {
		         System.out.println("權限----"+field.getModifiers()+"--");//訪問權限
		         System.out.println("變量描述----"+field.toGenericString());//變量名稱
		         System.out.println("變量類型----"+field.getType().toString());//變量類型
			 System.out.println("變量真實類型----"+field.getGenericType());//變量真實類型  若是參數不是泛型的,與getType()結果相同
		         System.out.println("變量值----"+field.get(sub));//類SubClass實例sub的變量的值
			 System.out.println();
		    }
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

  運行結果: java

權限----2--
變量描述----private java.lang.String cn.trip.core.servlet.SubClass.s_pri
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----private

權限----4--
變量描述----protected java.lang.String cn.trip.core.servlet.SubClass.s_pro
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----protected

權限----0--
變量描述----java.lang.String cn.trip.core.servlet.SubClass.s_def
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----default

權限----1--
變量描述----public java.lang.String cn.trip.core.servlet.SubClass.s_pub
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----public

權限----10--
變量描述----private static java.lang.String cn.trip.core.servlet.SubClass.sc_pri
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----private

權限----12--
變量描述----protected static java.lang.String cn.trip.core.servlet.SubClass.sc_pro
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----protected

權限----8--
變量描述----static java.lang.String cn.trip.core.servlet.SubClass.sc_def
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----default

權限----9--
變量描述----public static java.lang.String cn.trip.core.servlet.SubClass.sc_pub
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----public

權限----1--
變量描述----public java.util.List<java.lang.String> cn.trip.core.servlet.SubClass.actual
變量類型----interface java.util.List
變量真實類型----java.util.List<java.lang.String>
變量值----null
   b、public Field[] getFields()   獲取訪問權限爲public類型的字段 包括父類的public字段   
public class ParentClass {
    
	private   String s_pri_p = "parent_private";
	protected String s_pro_p = "parent_protected";
	          String s_def_p = "parent_default";
	public    String s_pub_p = "parent_public";
	
	private   String sc_pri_p = "parent_static_private";
	protected String sc_pro_p = "parent_static__protected";
	          String sc_def_p = "parent_static__default";
	public    String sc_pub_p = "parent_static__public";
}

  

public class SubClass extends ParentClass {

	private   String s_pri = "private";
	protected String s_pro = "protected";
	          String s_def = "default";
	public    String s_pub = "public";

	private   static String sc_pri = "private";
	protected static String sc_pro = "protected";
	          static String sc_def = "default";
	public    static String sc_pub = "public";
	
	public    List<String> actual  = null;
	public static void main(String[] args) {
		try {
		    Class<?> clz = SubClass.class;
		    SubClass sub = new SubClass();
		    Field[] fields = clz.getFields();//獲取全部訪問權限爲public的成員變量
		    for (Field field : fields) {
			System.out.println("權限----"+field.getModifiers()+"--");//訪問權限
			System.out.println("變量描述----"+field.toGenericString());//變量名稱
			System.out.println("變量類型----"+field.getType().toString());//變量類型
			System.out.println("變量真實類型----"+field.getGenericType());//變量真實類型  若是參數不是泛型的,與getType()結果相同
			System.out.println("變量值----"+field.get(sub));//類SubClass實例sub的變量的值
			System.out.println();
		    }
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

   運行結果:spa

權限----1--
變量描述----public java.lang.String cn.trip.core.servlet.SubClass.s_pub
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----public

權限----9--
變量描述----public static java.lang.String cn.trip.core.servlet.SubClass.sc_pub
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----public

權限----1--
變量描述----public java.util.List<java.lang.String> cn.trip.core.servlet.SubClass.actual
變量類型----interface java.util.List
變量真實類型----java.util.List<java.lang.String>
變量值----null

權限----1--
變量描述----public java.lang.String cn.trip.core.servlet.ParentClass.s_pub_p
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----parent_public

權限----1--
變量描述----public java.lang.String cn.trip.core.servlet.ParentClass.sc_pub_p
變量類型----class java.lang.String
變量真實類型----class java.lang.String
變量值----parent_static__public
   c、public Field getDeclaredField(String name)  獲取本類中指定參數名稱的變量 不受訪問權限約束
   d、public Field getField(String name)   獲取指定參數名稱的變量,該變量訪問權限爲public,包括父類

  Field類的其餘方法:code

  

  public String getName()
 返回該字段定義的名稱
  public Object get(Object obj);
  public boolean getBoolean(Object obj)
  public byte getByte(Object obj)
  public char getChar(Object obj)
  public short getShort(Object obj)
  public int getInt(Object obj)
  public long getLong(Object obj)
  public float getFloat(Object obj)
  
   以上方法都是用來根據Field的類型獲取其的實際值,方法的參數obj   是類的實例。
public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
獲取該字段上指定類型爲annotationClass的註解
public Annotation[] getDeclaredAnnotations()
獲取該字段上全部聲明的註解
public Class<?> getDeclaringClass()
獲取該字段是由哪個類或接口聲明定義的,返回該類或者接口
public void set(Object obj,Object value)
public void setBoolean(Object obj,boolean z)
public void setByte(Object obj, byte b)
public void setChar(Object obj, char c)
public void setShort(Object obj, short s)
public void setInt(Object obj,int i)
public void setLong(Object obj,long l)
public void setFloat(Object obj,float f)
public void setDouble(Object obj,double d)

以上方法用於改變一個對象實例obj的Field字段的實際值,

    關於訪問private字段,從新進行賦值htm

public class SubClass extends ParentClass {
	private   String s_pri = "private";
	protected String s_pro = "protected";
	          String s_def = "default";
	public    String s_pub = "public";

	private   static String sc_pri = "private";
	protected static String sc_pro = "protected";
	          static String sc_def = "default";
	public    static String sc_pub = "public";
	
	//public    List<String> actual  = null;
	public static void main(String[] args) {
		try {
		    Class<?> clz = SubClass.class;
		    SubClass sub = new SubClass();
		    Field[] fields = clz.getDeclaredFields();//獲取全部訪問權限爲public的成員變量
		    for (Field field : fields) {
		    	  System.out.print("原來值---"+field.get(sub)+"---");
		          field.set(sub, "11");
		          System.out.println("修改後的值---"+field.get(sub));
		    }
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

  運行結果:對象

原來值---private---修改後的值---11
原來值---protected---修改後的值---11
原來值---default---修改後的值---11
原來值---public---修改後的值---11
原來值---private---修改後的值---11
原來值---protected---修改後的值---11
原來值---default---修改後的值---11
原來值---public---修改後的值---11

  能夠看到能夠訪問private類型而且進行修改,再看下面代碼:接口

public class ClassTest {
	public static void main(String[] args) {
		try {
			 Class<?> clz = SubClass.class;
			 SubClass sub = new SubClass();
			 Field[] fields = clz.getDeclaredFields();//獲取全部訪問權限爲public的成員變量
			 for (Field field : fields) {
			    	 System.out.print("原來值---"+field.get(sub)+"---");
		                 field.set(sub, "11");
		                 System.out.println("修改後的值---"+field.get(sub));
			 }
		} catch (Exception e) {
				e.printStackTrace();
			} 
		}
}

  運行結果:ip

java.lang.IllegalAccessException: Class cn.trip.core.servlet.ClassTest
 can not access a member of class cn.trip.core.servlet.SubClass with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:109)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253)
	at java.lang.reflect.Field.get(Field.java:376)
	at cn.trip.core.servlet.ClassTest.main(ClassTest.java:15)

  拋出訪問private類型變量的異常。 那麼二者結果爲何不同呢?get

 這是由於這是兩個類的main方法,servlet

SubClass 本類中的main方法能訪問本類中private變量,所以沒有拋出異常;
ClassTest 外部的類main方法沒有權限方法其餘類private變量,一次拋出訪問異常。
出現這種狀況應到調用Filed的setAccessible(boolean flag) 設置爲true,表示取消訪問檢查。

  

public class ClassTest {
	
    		public static void main(String[] args) {
    			try {
    			    Class<?> clz = SubClass.class;
    			    SubClass sub = new SubClass();
    		          Field[] fields = clz.getDeclaredFields();//獲取全部訪問權限爲public的成員變量
    			    for (Field field : fields) {
    			    	  field.setAccessible(true);
    			    	  System.out.print("原來值---"+field.get(sub)+"---");
    			    	  field.set(sub, "11");
    			          System.out.println("修改後的值---"+field.get(sub));
    			          field.setAccessible(false);
    			    }
    			} catch (Exception e) {
    				e.printStackTrace();
    			} 
    		}
}

  運行結果:

原來值---private---修改後的值---11
原來值---protected---修改後的值---11
原來值---default---修改後的值---11
原來值---public---修改後的值---11
原來值---private---修改後的值---11
原來值---protected---修改後的值---11
原來值---default---修改後的值---11
原來值---public---修改後的值---11
 public boolean equals(Object obj) {
        if (obj != null && obj instanceof Field) {
            Field other = (Field)obj;
            return (getDeclaringClass() == other.getDeclaringClass())
                && (getName() == other.getName())
                && (getType() == other.getType());
        }
        return false;
    }
 Field類的equals方法
 比較是不是同一個類聲明的Field,而後比較Field名稱、而後再比較Field的數據類型
相關文章
相關標籤/搜索