黑马程序员-----反射技术

Java反射技术详解
本文深入讲解Java反射技术,包括如何动态获取类信息及调用类中的构造方法、字段和方法等内容,有助于提升程序的扩展性和灵活性。

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

1.反射技术

反射技术:动态的获取指定的类以及动态的调用类中的内容。

                   以前呢?先有类,在new对象。

                   有了反射后:先new对象,也就是说把创建对象的动作先做完,至于new哪个类由用户通过配置文件传递。

        

                   好处:大大的提高了程序的扩展性。

                  

         反射的应用:当使用的类不确定的时候,可以通过配置文件告诉应用程序,只要应用程序中使用反射技术就哦了。

         需要哪些对象呢?

         Class

         Constructor

         Field

         Method

         动态创建对象的方法。newInstance();默认调用的是被反射类的空参数构造函数。

         如果要通过指定的构造函数来初始化对象,需要先通过getConstructor()方法获取构造器对象。

         然后,在通过构造器创建对象,并初始化。


         获取构造器。

         获取字段。

         获取方法。

         注意;几个异常。初始化异常 没有对应的构造函数,无效访问;权限不够。

1.1获取字节码文件对象的方式

import cn.itcast.domain.Person;

public class Reflect_GetClassDemo {

	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		
		/*
		 * 要想获取字节码文件中的成员,必须要先获取字节码文件对象。
		 * 获取字节码文件对象的方式:
		 * 1,通过Object类中的getClass方法。
		 * 虽然通用,但是前提必须有指定类,并对该类进行对象的创建,才可以调用getClass方法。
		 * 2,使用的任意数据类的一个静态成员class,所有的数据类型都具备的一个属性。
		 * 好处:不用new对象。但是,还需要使用具体的类。
		 * 3,使用Class类中的forName方法。通过给定类名来获取对应的字节码文件对象。
		 * 这种方式很爽,只要知道类的名字就可以了。获取对应的字节码文件直接由forName方法自动完成。
		 * 这就是反射技术使用的获取字节码文件对象的方式。
		 */
		
		getClass_3();
	}

	public static void getClass_3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		
		String className = "cn.itcast.domain.Person";
		
		/*
		 * 1,通过给定的类名称,加载对应的字节码文件,并封装成字节码文件对象Class.
		 */
		Class clazz = Class.forName(className);
//		System.out.println(clazz);
		
		//通过newInstance()就可以创建字节码对象所表示的类的实例。
		/*
		 * 2,通过new创建给定的类的实例。
		 * 3,调用该类的构造函数。
		 * 通常被反射的类都会有提供空参数的构造函数。
		 * 没有对应的构造函数,会报InstantiationException
		 * 如果有提供,但是权限不够,会报IllegalAccessException
		 * 
		 */
		Object obj = clazz.newInstance();
		
		
		/* Person p = new Person();
		 * 1,加载Person类,并将Person类封装成字节码文件对象。
		 * 2,通过new创建Person对象。
		 * 3,调用构造函数对对象初始化。
		 */
		System.out.println(obj);
		
	}

	public static void getClass_2() {
		
		Class clazz = Person.class;
	}

	public static void getClass_1() {
	
		Person p1 = new Person();
		Person p2 = new Person();
		Class clazz1 = p1.getClass();
		Class clazz2 = p2.getClass();
		System.out.println(clazz1 == clazz2);//true

//		System.out.println(clazz1.getName());//获取类的名字。
	}
}

1.2获取指定的构造方法初始化对象

import java.lang.reflect.Constructor;

public class Reflect_GetConstructor {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		/*
		 * 如果要通过指定的构造函数初始化对象怎么办呢?
		 * 思路:
		 * 1,获取字节码文件对象。
		 * 2,再获取给定的构造函数。
		 * 3,通过构造函数初始化对象。
		 * 
		 */
		
		getConstructorDemo();
	}

	public static void getConstructorDemo() throws Exception {
		
		String className = "cn.itcast.domain.Person";
		Class clazz = Class.forName(className);
		
		//获取指定的构造器。获取Person类中两个参数string,int的构造函数。
		Constructor cons = clazz.getConstructor(String.class,int.class);
		
		//有了构造器对象后,通过构造器对象来初始化给类对象。
		Object obj = cons.newInstance("wangwu",23);
		//Person p = new Person("lisi",21);
		
		
		System.out.println(obj);
		
	}

}

1.3获取字段Field

import java.lang.reflect.Field;

public class Reflect_GetField {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		/*
		 * 获取字段。
		 */
		getFieldDemo();
	}

	public static void getFieldDemo() throws Exception {
		
		String className = "cn.itcast.domain.Person";
		Class clazz = Class.forName(className);
		
		String fieldName = "age";
		
		//获取age字段对象。
//		Field field = clazz.getField(fieldName);//获取是公共的字段。
		Field field = clazz.getDeclaredField(fieldName);
		
//		getXXX:获取都是类中公共的成员。
//		getDeclaredXXX:获取本类中已有的成员。
//		System.out.println(field);
		
		//对其进行值的设置,必须先有对象。
		Object obj = clazz.newInstance();
		
		
		//通过查找父类AccessiableObject的方法。setAccessiable(true);
		field.setAccessible(true);//取消权限检查,暴力访问。一般不访问私有。
		field.set(obj, 30);//IllegalAccessException:age字段是私有的。
		
		System.out.println(field.get(obj));
	}

}

1.4获取方法Method

import java.lang.reflect.Method;

public class Reflect_GetMethod {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		

		/*
		 * 获取方法。
		 */
		
		getMethodDemo2();
	}

	public static void getMethodDemo2() throws Exception {
		
		String className = "cn.itcast.domain.Person";
		Class clazz = Class.forName(className);
		String methodName = "staticShow";
		
		Method method = clazz.getMethod(methodName, null);
		method.invoke(null, null);
	}

	public static void getMethodDemo() throws Exception {
		
		String className = "cn.itcast.domain.Person";
		Class clazz = Class.forName(className);
		
		String methodName = "show";
		
		Method method = clazz.getMethod(methodName, String.class,int.class);
		Object obj = clazz.newInstance();
		method.invoke(obj, "wangcai",20);
	}
	
	

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值