Java基础----反射Reflect---Field

原创
2016/03/08 21:35
阅读数 121

     Field  java.lang.reflect  表示一个字段

     在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();
		} 
	}
}

  运行结果: 

权限----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();
		} 
	}
}

   运行结果:

权限----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类的其他方法:

  

  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字段,重新进行赋值

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();
			} 
		}
}

  运行结果:

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类型变量的异常。 那么两者结果为什么不一样呢?

 这是因为这是两个类的main方法,

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的数据类型

 

展开阅读全文
打赏
1
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
1
分享
返回顶部
顶部