黑马程序员——反射Reflection

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


-反射的概念

        反射就是吧Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,比如汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示Java的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。

反射的主要应用:工具,架构,动态开发等开发工程。


-反射机制 

        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。简单说:反射技术可以对一个类进行解剖。 

反射的好处:大大的增强了程序的扩展性。


-反射的基本步骤 

1、获得Class对象,就是获取到指定的名称的字节码文件对象。 

2、获得类的成员变量对象、成员方法对象或构造方法对象。 

3、访问成员变量、调用方法、调用构造函数创建实例对象。


-反射的基础-Class类

Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class

获取各个类字节码的方法有以下3种方式:

1、类名.class  //直接使用类.class 获取

2、对象.getClass()  //通过对象调用其getClass()方法获取

3、Class.forName("java.util.Date")  //使用类加载器加载获取

public class Demo {

public static void main(String[] args) throws ClassNotFoundException {

//1:获取类 (字节码)的方法一

Class clazz1= Class.forName("reflect.Person");

//2:获取类 (字节码)的方法二

Class clazz2= new Person().getClass();

//3:获取类 (字节码)的方法三

Class clazz3= Person.class;

}

}

(小提示----Java原始基本类型有:boolean,byte, char, short, int, long, float, double, 另外关键词void同样有Class类,它们都可以通过( .class )获取它们的字节码)

-构造方法的反射应用

Constructor类:各种类构造方法的反射类

Constructor反射类对象的获取:

(例如) Constructor construtor = String.class.getConstrutor(StringBuffer.class);

从而可以通过构造方法创建实例对象:

String str = (String)construtor.newInstance(new StringBuffer("abc"));

Class 本身也有newInstance()方法,可以直接调用:

String obj = (String)String.class.newInstance(); //相当于调用无参的构造方法

package reflect;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

/**
 * 反射类的构造函数,创建类对象
 * 
 * @author Administrator
 *
 */
public class ReflectConstrustor {

	// 反射构造函数:public Person()
	@Test
	public void test1() throws Exception {
		Class clazz = Class.forName("reflect.Person");
		Constructor c = clazz.getConstructor(null);
		Person p = (Person) c.newInstance(null);
		System.out.println(p.name);
	}

	// 反射构造函数:public Person(String name)
	@Test
	public void test2() throws Exception {
		Class clazz = Class.forName("reflect.Person");
		Constructor c = clazz.getConstructor(String.class);
		Person p = (Person) c.newInstance("haha");
		System.out.println(p.name);
	}

	// 反射构造函数:public Person(String name,int password)
	@Test
	public void test3() throws Exception {
		Class clazz = Class.forName("reflect.Person");
		Constructor c = clazz.getConstructor(String.class, int.class);
		Person p = (Person) c.newInstance("kila", 888);
		System.out.println(p.name);
	}

	// 反射构造函数:public Person(List list)
	@Test
	public void test4() throws Exception {
		Class clazz = Class.forName("reflect.Person");
		Constructor c = clazz.getDeclaredConstructor(List.class);
		c.setAccessible(true);
		Person p = (Person) c.newInstance(new ArrayList());
		System.out.println(p.name);
	}

}

Person类:

package reflect;

import java.io.InputStream;
import java.util.List;

//关联学习反射的Person类
public class Person {

	// 字段
	public String name = "kolen.j";
	private int password= 123;
	private static int age= 27;

	// 构造方法
	public Person() {
		System.out.println("Person()");
	}

	public Person(String name) {
		System.out.println("Person(String name) ::" + name);
	}

	public Person(String name, int password) {
		System.out.println("Person(String name,int password) ::" + name + ":"
				+ password);
	}

	private Person(List list) {
		System.out.println("Person(List list)");
	}

	// 非构造方法
	public void person1() {
		System.out.println("person1()");
	}

	public void person1(String name, int password) {
		System.out.println(name + ":" + password);
	}

	public Class[] person1(String name, int[] phone) {
		return new Class[] { String.class };
	}

	private void person1(InputStream in) {
		System.out.println(in);
	}

	public static void person1(int num) {
		System.out.println(num);
	}
	
	public static void main(String[] args){
		System.out.println("main(String[] args)");
	}
}

-Method:代表某个类中的一个成员方法

调用方法:

System.out.println(str.charAt());

System.out.println(charAt.invoke(str,1));

提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

package reflect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * 反射类的的非构造方法
 * 
 * @author Administrator
 *
 */
public class ReflectMethod {
	Person p = null;

	// 反射类的非构造方法:public void person1()
	@Test
	public void test1() throws Exception {
		p = new Person();
		Class clazz = Class.forName("reflect.Person");
		Method method = clazz.getMethod("person1", null);
		method.invoke(p, null);
	}

	// 反射类的非构造方法:public void Person1(String name, int password)
	@Test
	public void test2() throws Exception {
		p = new Person();
		Class clazz = Class.forName("reflect.Person");
		Method method = clazz.getMethod("person1", String.class, int.class);
		method.invoke(p, "kolen.j", 1111);
	}

	// 反射类的非构造方法:public Class[] Person1(String name, int[] phone)
	@Test
	public void test3() throws Exception {
		p = new Person();
		Class clazz = Class.forName("reflect.Person");
		Method method = clazz.getMethod("person1", String.class, int[].class);
		Class cl[] = (Class[]) method.invoke(p, "kolen.j", new int[] { 1, 2 });
		System.out.println(cl[0]);

	}

	// 反射类的非构造方法:public void Person1(InputStream in)
	@Test
	public void test4() throws Exception {
		p = new Person();
		Class clazz = Class.forName("reflect.Person");
		Method method = clazz.getDeclaredMethod("person1", InputStream.class);
		method.setAccessible(true);
		method.invoke(
				p,
				new FileInputStream(
						"D:\\AppDev\\WorkSpace\\JavaSpace\\java\\src\\reflect\\reflectStudy.txt"));
	}

	// 反射类的非构造方法:public static void Person1(int num)
	@Test
	public void test5() throws Exception {
		Class clazz = Class.forName("reflect.Person");
		Method method = clazz.getMethod("person1", int.class);
		method.invoke(null, 27);
	}

	// 反射类的Main()方法:public static void main(String[] args) 
	@Test
	public void testMain() throws Exception {
		//产生这个问题的原因是新版本要兼容以前的版本,分析如下
		//jdk1.5 Method.invoke(String methodName,Object...args);
		//jdk1.4 Method.invoke(String methodName,Object obj[]);  a(String name,String password)
		//jdk1.4 Method.invoke(String methodName,new Object[]{"aaa","123123"});
		Class clazz = Class.forName("reflect.Person");
		Method method= clazz.getMethod("main", String[].class);
		//method.invoke(null, new String[]{"aa","bb"});//出错 ----main(String s1,String s2);
		//method.invoke(null, new Object[]{new String[]{"aa","bb"}});//也可以像下面的写法
		method.invoke(null, (Object)new String[]{"aa","bb"});

	}

}

-字段的反射

Field:代表某个类中的一个成员变量

提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 

Array 允许在执行 get 或 set 访问操作期间进行扩展转换,但如果将发生收缩转换,则抛出一个 IllegalArgumentException。

package reflect;

import java.lang.reflect.Field;

import org.junit.Test;

/**
 * 反射类的字段
 * 
 * @author Administrator
 *
 */
public class ReflectField {

	Person p = null;

	// 反射字段:public String name="kelon.j"
	@Test
	public void test1() throws Exception {
		/*
		 * p= new Person(); Class clazz= Class.forName("reflect.Person"); Field
		 * f= clazz.getField("name"); String name= (String) f.get(p);
		 * System.out.println(name);
		 * 
		 * //获取字段的类型 Class type= f.getType(); System.out.println(type);
		 */

		p = new Person();
		Class clazz = Class.forName("reflect.Person");
		Field f = clazz.getField("name");
		// 获取字段的值
		Object value = f.get(p);
		// 获取字段的类型
		Class type = f.getType();
		// 判断字段的类似是否为某种期望的类型
		if (type.equals(String.class)) {
			String v = (String) value;
			System.out.println(v);
		}

		// 设置字段的值
		f.set(p, "xxx");
		System.out.println(p.name);
	}

	// 反射字段:private int password;
	@Test
	public void test2() throws Exception {
		p = new Person();
		Class clazz = Class.forName("reflect.Person");
		Field f = clazz.getDeclaredField("password");
		f.setAccessible(true);
		System.out.println(f.get(p));
	}

	// 反射字段:private static int age= 27;
	@Test
	public void test3() throws Exception {
		// 字段的静态成员变量与静态方法 有点不一样,静态方法不用对象
		// p= new Person();
		Class clazz = Class.forName("reflect.Person");
		Field f = clazz.getDeclaredField("age");
		f.setAccessible(true);
		System.out.println(f.get(p));
	}

}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值