反射

反射是面向对象语言,主要的一个实现。
反射主要将面向对象的一些主要特性提取出来形成对应的类
比如:
Class 对应到类
Object 对应到对象
Field 对应到变量
Method 对应到方法

反射具体的东西要想清楚就必须要上代码了。首先规定一个“门”类:

package mythread;
/** 

* @author Hercules

* @version 创建时间:2020年5月25日 下午8:23:02 

* 类说明 

*/
public class Door {

	private double width; //门的宽度
	
	private double height; //门的高度
	
	private String Material; //门的材质
	
	private double price;//门的价格
	
	//无参构造方法
	public Door() {
		super();
		// TODO Auto-generated constructor stub
	}

    //带参构造方法
	public Door(double width, double height, String material, double price) {
		super();
		this.width = width;
		this.height = height;
		Material = material;
		this.price = price;
	}

	//get和set方法
	public double getWidth() {
		return width;
	}

	public void setWidth(double width) {
		this.width = width;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	public String getMaterial() {
		return Material;
	}

	public void setMaterial(String material) {
		Material = material;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	//toString方法
	@Override
	public String toString() {
		return "Door [width=" + width + ", height=" + height + ", Material=" + Material + ", price=" + price + "]";
	}
	
	public void open() {
		System.out.println("门打开");
	}
	
	
	
}

这个门类包含了这些变量和方法,但是还要清楚它所属的包是mythread包。接下来在其他的包中再写一个测试类。

package oop;

import mythread.Door;

/** 

* @author Hercules

* @version 创建时间:2020年5月25日 下午8:30:19 

* 类说明 

*/
public class Test {
	
	public static void main(String[] args) {
		//通过反射获取到类对象 字符串的内容是包名.类名
		String className = "mythread.Door";
		
		//这里要捕获异常是因为mythread.Door这个包名.类名万一这个类不存在,就要报这个异常了。
		try {
			Class clazz = Class.forName(className);
			//通过类对象去创建实例对象
//			Object obj = clazz.newInstance();//默认调用了无参构造方法,其实这时这个obj就是Door对象,可以直接强转
			Door obj = (Door) clazz.newInstance();
			//下面直接调用obj的open方法,如果没有问题就说明Door对象成功创建
			obj.open();
		} catch (ClassNotFoundException e) {//类没有发现异常
			e.printStackTrace();
		} catch (InstantiationException e) {//初始化异常就是在访问无参构造方法时候的异常
			e.printStackTrace();
		} catch (IllegalAccessException e) {//非法访问异常,就是说这个构造方法可能是私有的不能访问
			e.printStackTrace();
		}
	}
	
}

运行如下:
在这里插入图片描述
这时候就说明运行成功了,这个对象也创建出来了。

也可以通过反射得到这个类中所有的方法。代码如下:
Class clazz = Class.forName(className);
			//通过类对象去创建实例对象
//			Object obj = clazz.newInstance();//默认调用了无参构造方法,其实这时这个obj就是Door对象,可以直接强转
//			Door obj = (Door) clazz.newInstance();
			Object obj = clazz.newInstance();
			Method [] methods = clazz.getMethods();			
			//下面直接调用obj的open方法,如果没有问题就说明Door对象成功创建
//			obj.open();
			for(Method m:methods) {
				System.out.println(m.getName());
			}

得到结果如下图:
在这里插入图片描述
这里就是类中所有的方法。可以发现多了很多新方法,其实没什么奇怪的。我前面的博客中提到过,其实java所有的类都继承自Object这个类。所以那些新方法都是Object这个类中的方法。

现在将open方法执行,for循环中代码修改如下:

for(Method m:methods) {
				System.out.println(m.getName());
				if(m.getName().equals("open")) {
					m.invoke(obj);
				}
			}

运行结果如下:
在这里插入图片描述
可以看到门打开这个方法顺利执行了。
其实invoke方法原型是这样的

m.invoke(obj, args);

第一个参数是对象,也就是执行的是哪个对象中的这个方法,第二个参数可以理解成一个参数数组,比如我们这里调用的是“open”方法,但是这个方法并没有参数,所以这里就不写。

对于反射初步有一个了解以后,再来了解一下反射对于类的操作,接下来全部都是记忆的东西了:接下来我只会写伪代码。

获取类 三种方式
Class clazz = Class.forName(className);
clazz = ArmDoor.class;
ArmDoor armDoor = new ArmDoor();
clazz = armDoor.getClass();

Class是类的类型  
Class.forName(“类的全路径”) 通过全路径获取到类的类型的对象
clazz.getAnnotations();//获取类的注解
clazz.cast(obj)//强转
clazz.getClassLoader()//获取类的类加载器
clazz.getConstructors();//获取所有的构造方法
clazz.getConstructor(参数类型);//获取指定的构造方法
int a = clazz.getModifiers();//获取类的修饰符
System.out.println(Modifier.toString(a));//将修饰符的值转换为字符串
clazz.getMethods();//获取所有方法
Method [] methods = clazz.getDeclaredMethods();//获取当前类的方法
Field [] fieds = clazz.getFields();//获取所有可视的成员变量
Field [] fieds = clazz.getDeclaredFields();//获取当前类声明的变量
clazz.getPackage();//获取包
clazz.getInterfaces();//获取接口
clazz.getName();//全路径类名
clazz.getSimpleName();//单独的类名

这就是关于类的反射的方法内容了,如果有名词不理解的自行百度。

接下来是关于反射的变量的方法:

Field 
field.get(obj);//获取指定对象的变量的值
field.getModifiers();//获取变量的修饰符
field.getName();//变量名
field.setAccessible(true);//设置变量可以访问
field.set(obj, value);//设置指定对象的指定变量的值

最后是关于方法的东西:

Method
System.out.println(m.getName());//获取方法名
Modifier.toString(m.getModifiers());//获取修饰符
m.getReturnType();//获取返回类型
m.getParameterCount();//获取参数个数
m.getParameterTypes();//获取参数类型
//m.setAccessible(flag);//设置可以访问
Parameter [] parameters = m.getParameters();//获取所有的参数对象
parameters[0].getName();//获取参数的名字
Object oo = m.invoke(obj, args);//执行方法  返回方法执行后的返回值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值