java反射

java反射

什么是反射?

一种动态实例化对象,并且可以获取到实例对象的属性,方法,并对其进行一些操作

  • 常规调用对象

在 Java 中创建对象,获取属性,调用对象的方法通常都是通过 Object o = new Object(), 然后通过 o.getXXX(), o.setXXX() o.doSomething()来实现。

  • 反射调用对象
 Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
 Object objectBook = classBook.newInstance();
 Book book = (Book) objectBook;

反射的例子

  • 底层组件,调用上层业务对象
  • spring

反射的优缺点

优点

增加程序的灵活性,避免将固有逻辑写死

代码简洁,可读性强,可提高代码的复用率

缺点

相比较于直接调用,在访问量较大的情况下,反射会导致系统性能明显下降

打破了类的封装性,存在一定的安全隐患

为什么反射慢?

  • 反射调用会进行一系列的安全性校验

  • 反射需要调用一系列的native方法来实现

  • 寻找Class字节码的过程,比如通过ClassName找到对应的字节码Class,然后进行加载、解析,也会比较慢,而new的方式则无需寻找,因为在Linking的解析阶段已经将符号引用转为了直接引用

  • 入参校验

反射代码例子

被反射类Book.java

public class Book{
    private final static String TAG = "BookTag";

    private String name;
    private String author;

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    public Book() {
    }

    private Book(String name, String author) {
        this.name = name;
        this.author = author;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    private String declaredMethod(int index) {
        String string = null;
        switch (index) {
            case 0:
                string = "I am declaredMethod 1 !";
                break;
            case 1:
                string = "I am declaredMethod 2 !";
                break;
            default:
                string = "I am declaredMethod 1 !";
        }

        return string;
    }
}

创建对象

 try {
            Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
            Object objectBook = classBook.newInstance();
            Book book = (Book) objectBook;
            book.setName("Android进阶之光");
            book.setAuthor("刘望舒");
            Log.d(TAG,"reflectNewInstance book = " + book.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

反射私有的构造方法

 try {
     Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
     Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class,String.class);
     declaredConstructorBook.setAccessible(true);
     Object objectBook = declaredConstructorBook.newInstance("Android开发艺术探索","任玉刚");
     Book book = (Book) objectBook;
     Log.d(TAG,"reflectPrivateConstructor book = " + book.toString());
 } catch (Exception ex) {
     ex.printStackTrace();
 }

反射私有属性

try {
    Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
    Object objectBook = classBook.newInstance();
    Field fieldTag = classBook.getDeclaredField("TAG");
    fieldTag.setAccessible(true);
    String tag = (String) fieldTag.get(objectBook);
    Log.d(TAG,"reflectPrivateField tag = " + tag);
} catch (Exception ex) {
    ex.printStackTrace();
}

反射私有方法

try {
    Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
    Method methodBook = classBook.getDeclaredMethod("declaredMethod",int.class);
    methodBook.setAccessible(true);
    Object objectBook = classBook.newInstance();
    String string = (String) methodBook.invoke(objectBook,0);

    Log.d(TAG,"reflectPrivateMethod string = " + string);
} catch (Exception ex) {
    ex.printStackTrace();
}

参考: https://www.jianshu.com/p/9be58ee20dee

获取成员变量并调用

 1.批量的
  1).Field[] getFields():获取所有的"公有字段"
  2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
 2.获取单个的:
  1).public Field getField(String fieldName):获取某个"公有的"字段;
  2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

获取成员方法并调用

  1.批量的:
          public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
          public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
  2.获取单个的:
          public Method getMethod(String name,Class<?>... parameterTypes):
                      参数:
                          name : 方法名;
                          Class ... : 形参的Class类型对象
          public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
 
       调用方法:
          Method --> public Object invoke(Object obj,Object... args):
                      参数说明:
                     obj : 要调用方法的对象;
                      args:调用方式时所传递的实参;

参考: https://blog.csdn.net/qq_36226453/article/details/82790375

Spring IOC 和 DI

也是利用的反射

IOC(Inversion of Control)

控制反转是一种设计思想,并非实际的技术,最核心的思想就是将预先设计的对象实例创建的控制权交给程序(IOC容器)。

注:IOC容器大家可以简单认为是一个KV的Map集合

DI(Dependency Injection)

依赖注入,对象的构建过程中,IOC容器动态提供这个对象所需要的其他对象.

posted @ 2020-12-25 22:30  宁君  阅读(86)  评论(0编辑  收藏  举报