我所知的反射

一、反射的概述

1.反射的介绍:
Java的反射机制是在运行的状态中,对于任意的一个类,能够知道这个类的所有属性和方法;对于任意一个对象,能够调用它的任意一个属性和方法,这种动态获取的信息以及动态调用对象的方法的功能成为java语言的反射机制

一句话,反射技术可以对类进行解剖

 

2. 反射中涉及的概念:
Java中的.class文件是java的可运行文件,叫字节码文件,java的.class文件也有共性,可以单独抽取出来,用“类”来描述。这个“类”就是Class(注意这是类的名字)。

要想获取一个类的内容,必须先要获取这个类所在的字节码文件对象,该对象是Class类型

字节码文件对象的作用:New一个Person对象,首先加载Person.class文件进内存,进内存时就被封装成了对象

 

例:Person类

public class Person {

  //成员变量

  public String sex;
  private String name;
  private int age;

  //构造方法
  public Person(){
    System.out.println("Person 构造方法运行");
  }

  //重载的方法
  public Person(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  }

  //静态方法
  public static void show(){
    System.out.println("show静态方法执行");
  }

  //带参数的方法
  public String eate(String a,int b){
    String res = a + b;
    System.out.println("function param:"+ a + "." + b);
    return res;
  }

  //私有方法
  private void joke(){
    System.out.println("joke私有方法执行");
  }

  //不带参数的方法 
  public void run(){
    System.out.println("run普通方法执行");
  }

}

 

 

 

二、字节码文件对象的获取的三种方法


1、通过对象获取 getclass();

Person p = new Person();
Class class1 = p.getClass();

2、通过类型获取 .class()
Class class2 = Person.class;

3、通过字符串获取 forName();
Class class3 = Class.forName("fanshe.Person");//全限定类名

 

 

 

三、获取自解码文件对象中的字段

 

getDeclaredField是可以获取一个类本身的所有字段,包括private 

getField只能获取类及其父类的public 字段

 

//字符串获取自解码文件对象(以字符串获取为例)
Class class1 = Class.forName("fanshe.Person");

//获取字节码文件中的字段
Field[] declaredFields = class1.getDeclaredFields();  //获取到该类所有字段,不包括继承的需要遍历
Field declaredField = class1.getDeclaredField("name");  //获取到该类单个字段

Field[] fields = class1.getFields();  //获取到该类及其父类所有公共字段
Field field = class1.getField("name");  //获取到该类公共单个字段

//给字段赋值

Field field = class1.getDeclaredField("name");
Object obj = class1.newInstance();

field.setAccessible(true);  //私有字段要写这句,跳过权限检查
field.set(obj, "小红");  //字段赋值
Object value = field.get(obj);  //获取字段值并接收

 

 

 

四、获取自解码文件对象中的方法

public Method[] getMethods():返回某个类的所有公用(public)方法和其父类的公用方法,也包括它所实现接口的方法。
public Method[] getDeclaredMethods():返回某个类的所有方法,包括私有方法,也包括它所实现接口的方法,但不包括继承的方法。

 

Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数。 要求被调用的构造函数是可见的,也即必须是public类型的;
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。在特定的情况下,可以调用私有的构造函数。

 

//字符串获取自解码文件对象(字符串获取)
Class class1 = Class.forName("fanshe.Person");


1、//获取所有方法
Method[] methods = class1.getMethods();

Method[] declaremethods = class1.getDeclaredMethods();

 

2、//获取构造方法

Object object = class1.newInstance();

 

3、//给带参数的构造方法赋值

赋值要用到Constructor了,预先遍历出构造方法的参数是什么类型,括号里写类型.class

Constructor constructor = class1.getConstructor(String.class,int.class);

Object object = constructor.newInstance("小明",18);

 

4、//获取不带参数的普通方法(run方法没有参数所以写null)

Method method = class1.getDeclaredMethod("run", null);

//将该方法反射到对象上,该方法的返回值是什么就用什么接
Object obj= class1.newInstance();
method.invoke(obj, null);

 

5、//获取带参数的普通方法
Method method = class1.getMethod("eate", String.class,int.class);

Object obj = class1.newInstance();
Object reValue = method.invoke(obj, "小刚",30);

 

6、//获取静态方法
Method method = class1.getMethod("show", null);
method.invoke(null, null);

 

7、//获取私有方法

Method method = class1.getDeclaredMethod("privateShow", null);
method.setAccessible(true);  //跳过权限检查
Object obj= class1.newInstance();
method.invoke(obj, null);

 

五、 反射的应用案例

 

接口USB:

 

实现类USBMouse:

 

实现类USBKeyBoard:

 

配置文件UsbTool(新建file文件):

 

业务逻辑Computer类:

 

主方法,测试方法:

运行输出的是“键盘启动”,改变配置文件usb = fanshe.UsbMouse,输出的就是“鼠标启动”,这样就可以在不改变代码的情况下变更需求,实现耦合。

posted @ 2018-04-20 10:37  输入贩卖元  阅读(130)  评论(0)    收藏  举报