反射是面向对象语言,主要的一个实现。
反射主要将面向对象的一些主要特性提取出来形成对应的类
比如:
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);//执行方法 返回方法执行后的返回值