黑马程序员_12_高新技术之反射

                                    黑马程序员——反射

                                          ------- android培训java培训、期待与您交流! ----------

反射的概念:一个类是由多个部分组成,例如:成员变量,方法,构造函数等,反射就是加载类<把硬盘中的class文件加载到内存中>,并解剖类的各个组成部分,包括私有的。

应用场景:主要是用于制作框架的时候使用,通过配置文件进行反射。

那么该如何加载类,如何反射呢?

Java是面向对象语言,万物皆对象,所以sun公司把所有类用一个Class类来描述。

通过字节码对象获取构造方法,创建对象,使用了Constructor类描述一个类的构造方法。创建对象用newInstance
通过一个字节码对象获取到成员函数,sun使用了一个Method类描述函数。执行指定方法用invoke
通过字节码对象获取成员变量 , sun使用了Field描述了一个类的成员变量。

首先我们先描述一个Person类,以Person类为列进行反射:
package cn.chen.reflect;

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

public class Person {
	//成员变量
	public String name="aaa";
	private int age = 22;
	//构造函数
	public Person(){
		System.out.println("person");
	}
	public Person(String name){
		System.out.println(name);
	}
	public Person(String name,int pass){
		System.out.println(name+":"+pass);
	}
	//集合作为形参传递
	private Person(List list){
		System.out.println("list");
	}
	public void aa1(){
		System.out.println("aa1...");
	}
	public void aa1(String name,int pass){
		System.out.println(name+":"+pass);
	}
	//返回类型是数组
	public Class[] aa1(String name,int[] pass){
		return new Class[]{String.class};
	}
	private void aa1(InputStream io){
		System.out.println(io);
	}
	//静态方法
	public static void aa1(String name){
		System.out.println(name);
	}
	public static void main(String[] args) {
		System.out.println("main...");
	}
}

步骤如下:
1:首先把硬盘中的class文件加载进内存中;

加载类进内存有三种方法:
a:通过Class类中forName方法:forName(String  className)
b:通过上帝Object类中getClass方法:对象.getClass()
c:通过类名.class

代码实现如下:
</pre><pre name="code" class="java">package cn.chen.reflect;

public class Demo1 {
	public static void main(String[] args) throws ClassNotFoundException {
		//第一种方法
		Class clazz1 = Class.forName("cn.chen.reflect.Person");
		//第二种方法
		Class clazz2 = new Person().getClass();
		//第三种方法
		Class clazz3 = Person.class;
	}
}


2:通过上个步骤获得该类字节码;通过该类的字节码获得该类的所以构造函数描述的类,该类有一个方法,根据构造函数指定的参数创建对象。

反射构造函数代码如下:

package cn.chen.reflect;

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

import org.junit.Test;

public class Demo2 {
	@Test
	public void test1() throws Exception{
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Constructor c = clazz.getConstructor(null);
		Person p = (Person) c.newInstance(null);
		System.out.println(p.name);
	}
	@Test
	public void test2() throws Exception{
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Constructor c = clazz.getConstructor(String.class);
		Person p = (Person) c.newInstance("chenlong");
		System.out.println(p.name);
	}
	@Test
	public void test3() throws Exception{
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Constructor c = clazz.getConstructor(String.class,int.class);
		Person p = (Person) c.newInstance("xieli",20);
		System.out.println(p.name);
	}
	@Test
	public void test4() throws Exception{
		//获得字节码文件对象
		Class clazz = Class.forName("cn.chen.reflect.Person");
		//反射私有成员时用的方法
		Constructor c = clazz.getDeclaredConstructor(List.class);
		//暴力反射
		c.setAccessible(true);
		//返回类型是Object,所以需要强制转换
		Person p = (Person) c.newInstance(new ArrayList());
		System.out.println(p.name);
	}
	@Test
	public void test5() throws Exception{
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Person p = (Person) clazz.newInstance();
		System.out.println(p.name);
	}
}

举一反三反射成员函数:

package cn.chen.reflect;

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

import org.junit.Test;

public class Demo3 {
	@Test
	public void test1() throws Exception{
		Person p = new Person();
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Method method = clazz.getMethod("aa1", null);
		method.invoke(p,null);
		
	}
	@Test
	public void test2() throws Exception{
		Person p = new Person();
		//获得字节码文件对象
		Class clazz = Class.forName("cn.chen.reflect.Person");
		//获得该类方法对象
		Method method = clazz.getMethod("aa1", String.class,int.class);
		//根据指定的参数,执行指定的方法。第一个参数是指定那个类的对象,后面参数是该类方法的形参
		method.invoke(p, "chen",25);
	}
	@Test
	public void test3() throws Exception{
		Person p = new Person();
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Method method = clazz.getMethod("aa1", String.class , int[].class);
		Class cs[] = (Class[]) method.invoke(p, "xieli",new int[]{12,2});
		System.out.println(cs[0]);
		
	}
	@Test
	public void test4() throws Exception{
		Person p = new Person();
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Method method = clazz.getDeclaredMethod("aa1", InputStream.class);
		method.setAccessible(true);
		method.invoke(p,new FileInputStream("H:\\1.jpg"));
	}
	@Test
	public void test5() throws Exception{
		
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Method method = clazz.getMethod("aa1", String.class);
		//反射静态方法,不需要对象、
		method.invoke(null,"chen");
	}
	@Test
	public void test6() throws Exception{
		Person p = new Person();
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Method method = clazz.getMethod("main", String[].class);
		//第一种解决方案,由于传入数组jvm会拆开,所以进行包装
//		method.invoke(null,(Object)new String[]{"s"});
		//第二种解决方案。
		method.invoke(null,new Object[]{new String[]{"bb","aa"}});
	}
}

反射字段即成员变量

package cn.chen.reflect;

import java.lang.reflect.Field;

import org.junit.Test;

public class Demo4 {
	@Test
	public void test1() throws Exception{
		Person p = new Person();
		Class clazz = Class.forName("cn.chen.reflect.Person");
		//根据参数获取对应的字段
		Field f = clazz.getField("name");
		System.out.println(f.get(p));
	}
	@Test
	public void test2() throws Exception{
		Person p = new Person();
		Class clazz = Class.forName("cn.chen.reflect.Person");
		Field f = clazz.getDeclaredField("age");
		f.setAccessible(true);
		System.out.println(f.get(p));
	}
}


注意部分:反射时如果是私有成员,必须使用带有Declared字母的方法,如果需要使用时,需要调用setAccessible(true) 方法告诉Jvm需要暴力访问。




------- android培训java培训、期待与您交流! ----------





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值