(黑马程序员)学习笔记,反射

学习了反射后,对其作用有个大致的理解:

1. 如果知道一个类的名称或者是它的实例对象,那么通过反射就可以把这个类中的方法和变量都获取到

2. 如果还知道这个类中的某个变量名,那么就可以把这个变量的当前值获取到

3. 如果明确知道这个类中的某个方法,那么也可以通过反射来调用这个方法

package demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/*
 * java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性
 * 至于属性是什么值,则由这个类的实例对象来确定,不同的实例对象有不同的属性值。
 * 
 * 而反射就是把java类中的各种成分映射成相应的Java类,
 * 一个类中的每一成员都可以用相应的反射API类的实例对象来表示,通过调用Class类的方法可以得到这些实例对象
 */
public class ReflectDemo {

	public static void main(String[] args) {
		try {
//			reflect();
//			refConstructor();
//			refField();
			refMethod();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//简单的反射类
	private static  void reflect() throws Exception{
		String s = "abc";
		//<? extends String>是泛型,表示该反射类的类型是String的子类,不写编译会有警告
		Class<? extends String> clazz = s.getClass();
		Class<String> clazz2 = String.class;//这个指定类型String
		Class clazz3 = Class.forName("java.lang.String");//这个就没有用泛型,会有警告,但不报错
		//通过比较可以看出,反射的对象其实是一个
		System.out.println(clazz==clazz2);
		System.out.println(clazz==clazz3);
		//判断反射的类是否为基本类型
		System.out.println("s 的反射类是否为基本类型"+clazz.isPrimitive());//String不是基本类型,所以它的实例对象反射类也不是基本类型
		System.out.println("int 的反射类是否为基本类型"+int.class.isPrimitive());//int是基本类型
		System.out.println("Integer 的反射类是否为基本类型"+Integer.class.isPrimitive());//Integer是int的封装对象,不是基本类型
		//判断反射类是否为数组
		System.out.println("int[] 的反射类是否为基本类型"+int[].class.isPrimitive());//int[]不是基本类型
		System.out.println("int[] 的反射类是否为数组"+int[].class.isArray());//int[]是基本类型的数组
	} 
	//构造函数的反射
	private static void refConstructor() throws Exception{
		//使用反射获得String中带有StringBuffer参数的构造方法
		Constructor<String> cons = String.class.getConstructor(StringBuffer.class);
		String s = cons.newInstance(new StringBuffer("abc"));
		System.out.println(s+"中第二个字符是"+s.charAt(1));
	}
	//类中属性的反射
	private static void refField() throws Exception{
		ReflectPoint rp = new ReflectPoint(3, 5);
		//通过反射获取ReflectPoint中的属性"a"
		Field f_a = ReflectPoint.class.getDeclaredField("a");
		Field f_b = ReflectPoint.class.getDeclaredField("b");
		//因为"a"在ReflectPoint类中是私有的,所以这里需要"暴力反射"一下,强行获取私有属性的值
		f_a.setAccessible(true);
		//Field的get()方法,参数是某类的实例对象,返回值就是那个实例中该属性的值(注意:因为是用反射获取的值,所以返回类型是Object)
		String a = f_a.get(rp).toString();
		String b = f_b.get(rp).toString();
		System.out.println("ReflectPoint中属性a的值是"+a);
		System.out.println("ReflectPoint中属性b的值是"+b);
		//Field的set()方法,参数一个是某类的实例对象,一个是修改的值
		f_b.set(rp,0);
		b = f_b.get(rp).toString();
		System.out.println("ReflectPoint中属性b修改后的值是"+b);
	}
	
	//类中方法的反射
	private static void refMethod() throws Exception{
		String s = "abc"; 
		//使用反射获得String中CharAt()方法,参数第一个是方法名,第二个是反射方法参数类型的class(如下也可以是int.class)
		Method m_charAt = String.class.getMethod("charAt", Integer.TYPE);
		//使用通过反射获得的方法,通过invoke()方法调用,第一个参数是带有反射方法的实例,第二个对象是方法
		char c = (Character) m_charAt.invoke(s, 1);
		System.out.println(s+"中第二个字符是"+c);
		
		//反射调用main()方法
		Method m_main = ReflectPoint.class.getMethod("main",String[].class);
		//因为main()方法是静态的,所以第一个参数为空
		m_main.invoke(null, (Object)new String[]{});
	}
}

//为演示反射提供的简单测试类
class ReflectPoint{
	private static int a;
	public static int b;
	public ReflectPoint(int a,int b){
		this.a = a;
		this.b = b;
	}
	public static void main(String[] args) {
		System.out.println("ReflectPoint");
	}
}

下面应用反射技术,来感受一下框架是怎样运行的

package demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;

/*
 * 反射的应用:这里利用反射模拟框架的效果
 * 框架就是根据配置文件中获取的类的信息,然后通过反射来使用配置进来的类
 */


public class ReflectDemo2 {

	public static void main(String[] args) {
		InputStream in = null;
		try {
//			获取配置文件的流有多种途径,问题主要集中在配置文件路径的选择上(假设配置文件和类在一个目录下)
//			第一种就是获取类的加载器的位置,然后再写上相对路径,获取配置文件
//			in = ReflectDemo2.class.getClassLoader().getResourceAsStream("demo/config.properties");
//			第二种就是获取类所在目录,然后写入相对路径,获取配置文件
//			in = ReflectDemo2.class.getResourceAsStream("config.properties");
			
			//加载配置文件,这就相当于框架的配置文件
			//这种获取类的方式使用的相对于工程的相对路径
			in = new FileInputStream(new File("src/demo/config.properties"));
			Properties prop = new Properties();
			prop.load(in);
			//根据配置的类名加载类
			String conllectionClass = prop.getProperty("conllectionClass");
			Collection<String> coll = (Collection<String>)Class.forName(conllectionClass).newInstance();
			//使用生成的类
			coll.add("A");
			coll.add("B");
			coll.add("A");
			coll.add("C");
			
			System.out.println(coll.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

配置文件内容:config.properties(和类放在一个文件夹下)

conllectionClass=java.util.HashSet


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值