反射【二】

前言

|ू・ω・` )
哟,大家好啊,这一章节是对反射的一些补充和加深。
如果有兴趣可以去看看反射【一】

对了,本章节我采用了一些博客主的图片啊,之类的,
还有一个博主的我感觉挺不错的,可以看看
虽然是全文字
链接:https://blog.csdn.net/u010325193/article/details/80865672

反射的概念

JAVA反射机制是在运行状态中:
对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;

这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

啦啦,因为你在实列化的时候是在创建一个class文件,那么是咋样创建的呢?
为什么要反射呢?
在这里插入图片描述
大家可以参考一下,不懂也没事,下次我会做个章节的。

注意:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。


反射之获取Class对象

1、获取Class对象的三种方式

  1. Object ——> getClass();
  2. 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
  3. 通过Class类的静态方法:forName(String className)(常用)

第一种:

//Object ——> getClass();
	Student stu = new Student();
	Class clz =  stu.getClass();

在这里插入图片描述
第二种

	//任何数据类型(包括基本数据类型)都有一个“静态”的class属性
	Class clz =  Student.class

在这里插入图片描述

第三种:

	//通过Class类的静态方法:forName(String  className)(常用)
	Class clz =  Class.forName("com.reflect.demo.student");

在这里插入图片描述

ok,先了解了解,后再继续我们的反射之路


反射之动态main方法

反射也是可以调用main方法的哦,在上面一章里,反射是可以调用方法的,所以,那么不可以调用main方法吗?

首先,我们创建一个Student类

public class Student {

	public static void main(String[] args) {
		System.out.println("main方法执行了。。。");
	}
}

图片详解
在这里插入图片描述
测试类:


public class Main {
	
	public static void main(String[] args) {
		try {
			//1、获取Student对象的字节码
			Class clazz = Class.forName("fanshe.main.Student");
			
			//2、获取main方法
			 Method methodMain = clazz.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型,
			//3、调用main方法
			 //第一个参数,对象类型,因为方法是static静态的,
			 //这里拆的时候将  new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。
			 methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一
			 	
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}
}


图片详解
在这里插入图片描述

然后运行结果:“main方法执行了”


反射之运行配置文件

对于暂时还不太了解反射的伙计们,其实在一个地方,我们的反射就得到了很大的体现:
那就是util包的DBHelper类,连接eclipse数据库的类。
咱们只需在配置文件修改就不需要去改类.

所以我就拿现成的来讲:

public class DBAccess {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;

	static {// 静态块执行一次,加载 驱动一次
		try {
			InputStream is = DBAccess.class.getResourceAsStream("config.properties");//获取输入流(在config.properties中)

			Properties properties = new Properties();//获取配置文件的对象
			properties.load(is);//将流加载到配置文件对象中

			driver = properties.getProperty("driver");
			url = properties.getProperty("url");
			user = properties.getProperty("user");
			password = properties.getProperty("pwd");

			Class.forName(driver);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

在这里插入图片描述

在配置文件中,也就是config.properties这个静态资源文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db_0529?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
user=root
pwd=123

这样就可以了,那有人就说了不就是XML解析中的吗
其实也可以调用方法的
比如:
配置文件:

className = com.fanshe.Student
methodName = show

调用:

InputStream is = DBAccess.class.getResourceAsStream("config.properties");//获取输入流

Properties properties = new Properties();//获取配置文件的对象
properties.load(is);//将流加载到配置文件对象中

className = properties.getProperty("className");
methodName= properties.getProperty("methodName");

//通过反射获取Class对象
Class stuClass = Class.forName(className);//"cn.fanshe.Student"

//2获取show()方法
Method m = stuClass.getMethod(methodName);//show

//3.调用show()方法
m.invoke(stuClass.getConstructor().newInstance());


public class Student {
	public void show(){
		System.out.println("is show()");
	}
}

反射之越过泛型检查

我感觉这个挺好玩的哦,可以在泛型的编码过程,越过去。

泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的

public static void main(String[] args) throws Exception{
		ArrayList<String> strList = new ArrayList<>();
		strList.add("aaa");
		strList.add("bbb");
		
	
		//获取ArrayList的Class对象,反向的调用add()方法,添加数据
		Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
		//获取add()方法
		Method m = listClass.getMethod("add", Object.class);
		//调用add()方法
		m.invoke(strList, 100);  //可以加入int的类型了
		
		//遍历集合
		for(Object obj : strList){
			System.out.println(obj);
		}
	}


在这里插入图片描述

大家知道这个能干嘛吗,就算你定死了泛型类型,你还是可以去反调用add方法使得变为Object类型哦!!!


总结

理解并不难,难在怎么去灵活运用

Thanks♪(・ω・)ノ希望大家能用来参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值