用一些简单的语言来说明反射机制(但是不一定对,说不定是对的)
反射机制
大概可以理解成所有的类都有一个镜像的Class类,我们可以同过这个class类来正常的访问原来的类我们来看一个例子
package peg;
//这是一个普普通通的类
public class TestClass {
private int id;
private String name;
public int age=18;
public TestClass(int id, String name) {
this.id = id;
this.name = name;
}
public TestClass() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
System.out.println(this.name+" "+this.id);
return null;
}
public void f1(int i){
System.out.println("f1"+i);
}
public void f1(){
System.out.println("f1");
}
}
public class main {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
//这是使用反射的方式来创建并调用testclass的f1方法
Class class1 = Class.forName("peg.TestClass"); //创建对应的class类
Object testclass1 = class1.newInstance();//使用class类来创建testclass对象
Method method = class1.getMethod("f1");//通过Class类来获取testclass类的方法
method.invoke(testClass1);//使用方法(无参数)
//这是我们原来用的方式
TestClass testClass3 = new TestClass();
testClass.f1();
}
我们发现同样的事情使用反射,代码量活生生增加了一倍,那我们为什么还用反射呢?
1.增加程序的灵活性,避免将程序写死到代码里。
2.代码简洁,提高代码的复用率,外部调用方便
3.对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
缺点
反射会让你的程序性能降低
既然优点比缺点多,看来我们非学不可了啊
使用class获取类
Class class1 = Class.forName("peg.TestClass");
Class class2 = new TestClass().getClass();
Class class3 = TestClass.class;
这三种都是对testclass类获取class类,值得注意的是一个类只能有一个Class东西,所以三个class对象实际上都是同一个对象,因为他们的HashCode print 出来是一样的
使用class创建类
既然我们已经获取并创建了一个class对象,那我们应该用这个Class对象来创建一个我们用来要用的class类了
//有参数构造方法
//使用class对象获取TestClass的有参数构造方法并创建了一个构造器对象constructor
Constructor constructor = class1.getConstructor(int.class,String.class);
//使用这个构造器来创建一个testclass对象
Object testClass2 = constructor.newInstance(99,"大宝");
//无参数构造方法
Object testclass3 = class1.newInstance();//还好,无参数构造方法简单很多
我们甚至还要建一个构造器对象,
使用class获取成员变量
历经险阻我们终于建好了一个testclass对象,那我们先来获取一个变量试一下吧
Field[] fields = class2.getFields();//获取所有public修饰的变量
Field field = class1.getField("age");//获取指定public变量
//这些变量直接print求可以使用了
//下面的方法可以获取指定方法
Field field1 = class1.getDeclaredField("age");
//下面的方法可以获取所有方法
Field[] fields1 = class2.getDeclaredFields();
//"但是如果我们想用private 修饰的变量的话还是报错"
//"废话!本来private变量就要不了"
//"这里就体现出了反射的其中一个优点,就算是private也能访问"
fields1[1].setAccessible(true);//忽略修饰符(暴力访问)
//使用了这个方法后我们发现fields能访问testclass所有的变量了,即使是private也不在话下
field.set(testClass1,20); //设置值
field.get(testClass)//获取值
使用class获取成员方法
现在我们再来用反射的方式来用用testclass的方法吧
Method[] methods = class1.getMethods();//基本同理
Method method = class1.getMethod("f1");//基本同理
//基本上和获取变量是一样的
//使用invoke来使用这些方法
method.invoke(testClass1);//使用方法(无参数)
method.getName();//获取方法名
method1.invoke(testClass1,10);//使用方法有参数
结尾
虽然讲的浅,但是应该还算是好理解吧我讲的,如果想要深入学习还是推荐去B战,CSDN看看,光看我这个肯定是不顶事的,这应该是我的第一篇文章,如果帮助到你了,可以给我点个赞,收个藏,关个注什么的嘛,又不要钱,
个人水平相当有限,如果发现了什么问题也欢迎学习交流