反射简单介绍

1.反射是什么

反射就是java的一种机制,在程序运行的时候,可以动态的获取类中的方法和类中的属性,在此我们对其进行动态的修改添加或者删除功能,而不影响其他功能。

2.通过反射获取类中私有方法和属性

1.先创建一个对象

public class Demo {

private String name;
public void getPublicMethod(String name){
  System.out.println(this.name +"调用共用方法" + name);
}
private void getPrivateMethod(String name){
  System.out.println(this.name +"调用私有方法" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
  this.name = name;
}
}

2.编写一个简单java运行类

public class TestMain {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//      1.获取demo的类
        Class cl = Class.forName("com.zhaott.classloader.Demo");
//      2.创建demo的对象
        Demo demo = (Demo)cl.newInstance();
//      3. 获取demo类中的getPrivateMethod方法
        Method method = cl.getDeclaredMethod("getPrivateMethod",String.class);
//      4. 设置getPrivateMethod方法能够访问
        method.setAccessible(true);
//      5. 执行刚刚获取getPrivateMethod的方法
        method.invoke(demo,"小明");
//      6.获取demo类中的"name"属性
        Field field = cl.getDeclaredField("name");
//     7.设置name属性可用
        field.setAccessible(true);
//     8.为demo对象中的name属性赋值
        field.set(demo,"小红");
//      9.再次执行获取的getPrivateMethod的方法
        method.invoke(demo,"小明");
    }
}

3.查看执行结果

图1.png

3.通过反射获取类中公有方法和属性

1.先创建一个对象

public class Demo {

public String name;
public void getPublicMethod(String name){
  System.out.println(this.name +"调用共用方法" + name);
}
private void getPrivateMethod(String name){
  System.out.println(this.name +"调用私有方法" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
  this.name = name;
}
}

2.编写一个简单java运行类

public class TestMain {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//      1.获取demo的类
        Class cl = Class.forName("com.zhaott.classloader.Demo");
//      2.创建demo的对象
        Demo demo = (Demo)cl.newInstance();
//      3. 获取demo类中的getPublicMethod方法
        Method method = cl.getMethod("getPublicMethod",String.class);
//      4. 执行刚刚获取getPublicMethod的方法
        method.invoke(demo,"小明");
//      6.获取demo类中的"name"属性
        Field field = cl.getField("name");
//      7.为demo对象中的name属性赋值
        field.set(demo,"小红");
//      8.再次执行获取的getPublicMethod的方法
        method.invoke(demo,"小明");
    }
}

3.查看执行结果

图2.png

4.分析两次执行的结果

相信到了这里大家也已经把案例敲出来了,但是仔细的同学就会发现两次执行的结果不同,同时代码也有所不同了,而且相信还有一部分人把代码进行修改,出现了各种各样的错误,这里我就一一给大家解惑。

  1. 通过Class cl = Class.forName("com.zhaott.classloader.Demo");获取了cl的类,(这里方法不止一种,此处就先使用该种方法)
  2. 第一次使用的cl.getDeclaredMethod("getPrivateMethod",String.class);
    第二次使用的是cl.getMethod("getPublicMethod",String.class)

在这里对getDeclaredMethod(String str,Object...)和getMethod(String str,Object...)做一下区分

getDeclaredMethod是可用获取当前类中的所有方法,其中不包括继承的方法和实现的方法,也就是说不包含父类中的方法和父接口中的方法,包括包含public、protected和private方法

getMethod是可用获取当前类中的公共方法,包括继承的方法和实现的方法,
也就是包含父类中的方法和父接口中的方法,但是只能包含public修饰的公共方法

getDeclaredMethod(String str,Object...)参数值,第一个参数值是要初始化的参数名,第二个参数是要初始化方法的参数类型例如:cl.getDeclaredMethod("getPrivateMethod",String.class)
getMethod(String str,Object...)使用方法和getDeclaredMethod一样

  1. method.invoke(对象,"方法的参数值")
  2. cl.getDeclaredField("name")和cl.getField("name")的区别和上面介绍的获取方法的用法一样
  3. field.set(对象,"属性值");

此处还会有一个错误,如果在对象中该属性为私有属性,但是没有get/set方法,就会抛出异常,异常如下:
图3.png
  1. 介绍一下method.setAccessible(true)的使用

当我们获取的方法为私有方法,我们获取的属性为私有属性的时候,需要在获取到后调用method.setAccessible(true)/field.setAccessible(true)设置方法/属性可用性,如果不设置可用性此时会抛出异常,异常如下:
图4.png

相信经过两个简单案例可以让大家对反射有一定了解,还有反射使用的一些注意事项,反射在我们开发中随处可见,也许我们没用到,但是我们使用的框架中取经常使用,还有动态代理中就可以使用反射机制,写有不对之处,希望大家随时给出自己的意见。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容