J2EE框架(三)Reflect

反射在Java中允许运行时动态地获取类的信息并进行操作,如字段、方法和构造器。它可以访问私有成员,但无法获取方法的执行代码。使用反射时,需注意通过Class对象创建实例,并通过AccessibleObject的setAccessible(true)方法来访问私有成员。关键方法如getFields()获取公共字段,getDeclaredFields()获取所有声明的字段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射能做什么?


反射可以根据Class对象获取和设置它的所有,字段、方法、构造方法、类的注解,可以操作任何修饰字段、方法的能力当然包括私有修饰符


反射的边界是什么?


反射只能获取方法的返回类型、返回值、参数、并不能获得方法中的执行代码,当然我们可以通过代理动态注入新的执行代码但原代码永远存在且不变。


运用反射注意什么?


1、反射本质是获得Class对象的属性、方法,而我们所有对象都公用一个Class类型,所以用反射调用方法时需要给它一个具体的对象,这个对象就是Class对象转换后的对象(往往我们是用newInstance()方法把Class对象转换为具体的某个对象)


2、反射中类型是用的整数常量如下:

public static final int ABSTRACT 1024

                       public static final int FINAL 16

                       public static final int INTERFACE 512

                       public static final int NATIVE 256

                       public static final int PRIVATE 2

                        public static final int PROTECTED 4

                       public static final int PUBLIC 1

                       public static final int STATIC 8

                       public static final int STRICT 2048

                       public static final int SYNCHRONIZED 32

                       public static final int TRANSIENT 128

                       public static final int VOLATILE 64

3、方法、字段、构造方法都继承与AccessibleObject对象

这个对象可以操作访问权限和字段方法注解,最常用的setAccessible(boolean flag),设置为true就可以访问私有变量

4、Class 对象的以下方法需要注意:

getFields()

         返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。

getDeclaredFields()

         返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

   getMethods()

          返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

getDeclaredFields()

         返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。


反射代码实例:

public class Cat {
	// 静态模块
	static {
		System.out.println("我是静态内容");
	}


	// 无参构造方法
	public Cat() {
		System.out.println("我是构造方法");
	}
	// 有参构造方法
		public Cat(String str,int num) {
			System.out.println("有参构造方法"+str+num);
		}


	 List<Cat> catList=new ArrayList<Cat>();
   //静态变量
	public static int AGE=10;
   
	private String catName;
	
    public String  catPlay="玩溜溜球";
    
    public void setCatName(String catName) {
		this.catName = catName;
	}
	/**
		 * @return 获取猫的名字
	 */
	public String getCatName() {
		return catName;
	}

}
具体反射代码:
//构造方法
	@Test
	public void testReflectConstuctor() throws Exception{
		//1、获得Class对象
		Class<?> cl=Class.forName("com.lovo.Cat");
		//2、获取所有构造方法
		Constructor cs[]=cl.getConstructors();
		//3、获取构造方法名字、参数,构造方法并无返回值
		for(Constructor c:cs){
			int i=c.getModifiers();
			/**
			 *   public static final int ABSTRACT 1024 
				 public static final int FINAL 16 
				 public static final int INTERFACE 512 
				 public static final int NATIVE 256 
				 public static final int PRIVATE 2 
				 public static final int PROTECTED 4 
				 public static final int PUBLIC 1 
				 public static final int STATIC 8 
				 public static final int STRICT 2048 
				 public static final int SYNCHRONIZED 32 
				 public static final int TRANSIENT 128 
				 public static final int VOLATILE 64 
			 */
			//获得修饰符
			System.out.println("修饰符常量="+i);
			//获取方法名
			String methodeName=c.getName();
			System.out.println(methodeName);
			//获取参数类型素组
			 Class[] typeClasss=c.getParameterTypes();
			 for(Class tcl:typeClasss){
				 System.out.println("构造方法参数类型按照顺序"+tcl.getName());
			 }
			 //  使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
			 if(typeClasss.length>0){
				 //有参构造方法
			 c.newInstance("小花猫",5);				
			 }else{
				 //无参构造方法
				 c.newInstance();
			 }
		}
		
		
	}
	
	@Test
	public void testReflectFiled() throws Exception{
		//1、获得Class对象
		Class<?> cl=Class.forName("com.lovo.Cat");
		//获取非私有字段数组
		//Field fs[]=  cl.getFields();
		//获取所有字段数组
		Field fs[]=  cl.getDeclaredFields();
		//循环获取所有字段
		for(Field f:fs){
			//AccessibleObject类是 Field、Method 和 Constructor 对象的基类。
			//此方法为AccessibleObject类的方法,让反射是无忌惮的访问所有修饰类型
			f.setAccessible(true);
			System.out.println("字段修饰="+f.getModifiers());
			System.out.println("字段类型="+f.toGenericString());
			System.out.println("字段名称="+f.getName());
			System.out.println("获得值="+f.get(cl.newInstance()));
			//给catName字段设置新的值
			if(f.getName().equals("catName")){
			Object obj= cl.newInstance();
			f.set(obj,"小白猫");
			//获取新值
			Cat c=(Cat)obj;
			System.out.println("新值="+c.getCatName());
			}
		}
	}
	
	@Test
	public void testRefletMethod() throws Exception{
		//1、获得Class对象
		Class<?> cl=Class.forName("com.lovo.Cat");
		//获取所有非私有方法
		//Method []ms=cl.getMethods();
		//获取所有方法
		Method []ms=cl.getDeclaredMethods();
		//转换为具体的对象
		Object obj=cl.newInstance();
		for(Method m:ms){
			System.out.println("返回方法修饰="+m.getModifiers());
			System.out.println("返回方法返回类型="+m.getGenericReturnType().toString());
			System.out.println("返回方法名="+m.getName());
			System.out.println("获取方法参数类型"+m.getGenericParameterTypes());
		
			if(m.getName().equals("setCatName")){
				//设置		
				m.invoke(obj, "新猫咪");				
			}
		}
		
		for(Method m:ms){
			if(m.getName().equals("getCatName")){
				System.out.println("返回值="+m.invoke(obj));
			}
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值