Java的反射机制

基础知识

概念

  • 反射是框架设计的灵魂。
  • 反射机制就是将类的各个组成部分封装为其他对象。

优势

  • 可以在程序运行过程中,操作这些对象。
  • 可以解耦,提高程序的可扩展性。

Java代码的阶段

  • Java代码在计算机中经历的三个阶段
    • Source(源代码阶段)
      • Java文件被Javac编译为class文件,class文件会将成员变量、成员方法和构造方法等编译成不同的模块。
      • class文件通过 Classload类加载器 来进入和下一阶段。
    • Class(类对象阶段)
      • 通过 Classload类加载器,将class文件加载进内存,成员变量、成员方法和构造方法会被封装为Class类中的对象。
    • Runtime(运行阶段)
      • 当我们需要访问Java文件的成员时,我们就可以逆向访问,通过Class类的Classload类加载器来获取该成员的对象。

获取Class对象

  • Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象。
    • 处于Source(源代码阶段),并未加载进内存。
      • 用于配置文件,将类名定义在配置文件中。读取文件,从而加载类。
  • 类名.class:通过类名的属性class获取。
    • 处于Class(类对象阶段),已经加载进内存。
      • 多用于参数的传递。
  • 对象.getClass():Object类中定义的方法。
    • Runtime(运行阶段),处于运行时。
      • 用于获取对象的字节码文件对象。
  • Class类对象
    • 同一个字节码文件( .class)在一次程序运行过程中,只会被加载一次。
    • 不论通过哪一种方式获取的Class类对象都是同一个。
// Class类.静态方法forName("全类名")
Class class1 = Class.forName("com.test.Person");
// 类名.成员class
Class class2 = Person.class;
// 对象名.成员方法getClass()
Person person = new Person();
Class class3 = person.getClass();

获取成员变量

  • Field[] getFields()
    • 返回包含一个 Field对象数组,反射 所有可访问的 public字段类对象。
  • Field getField(String name)
    • 返回一个 Field对象,反射 指定的 public成员字段类对象。
  • Field[] getDeclaredFields()
    • 返回一个 Field对象,反射 所有可访问的 已声明字段类对象。(不考虑修饰符)
  • Field getDeclaredField(String name)
    • 返回一个 Field对象数组,反射 指定已声明字段类对象。(不考虑修饰符)

Person类中的成员变量

//    public修饰符
    public String publicName;
    public int publicAge;
//    private修饰符
    private String privateName;
//    protected修饰符
    protected String protectedName;
//    无修饰符
    String name;

获取Person类中的成员变量

 Class pc = Person.class;

/* getField("") */
Field fie = pc.getField("publicName");
	// public java.lang.String  test.Person.publicName

/* getFields() */
Field[] fies = pc.getFields();
    // public java.lang.String  test.Person.publicName
	// public int  test.Person.publicAge

/* getDeclaredField("") */
Field fie = pc.getDeclaredField("privateName");
privateName.setAccessible(true);
	// private java.lang.String test.Person.privateName


/* getDeclaradFields() */
Field[] fies = pc.getDeclaredFields();
for (Field fie : fies) {
	fie.setAccessible(true);
}
    // public java.lang.String test.Person.publicName
    // private java.lang.String test.Person.privateName
    // protected java.lang.String test.Person.protectedName
    // java.lang.String test.Person.name

获取构造方法

  • Constructor<?>[] getConstructors()
    • 返回一个 Constructor对象,反射 指定的 public构造类对象。
  • Constructor<T> getDeclaredConstructor(类<?>… parameterTypes)
    • 返回一个 Constructor对象,反射 指定的 构造类对象。
  • Constructor<T> getConstructor(类<?>… parameterTypes)
    • 返回一个 Constructor对象数组,反射 所有的 public构造类对象。
  • Constructor<?>[] getDeclaredConstructors()
    • 返回一个 Constructor对象数组,反射 所有定的 构造类对象。

Person类中的构造方法

//    无参构造
public Person() {}

// public 带参构造(String)
public Person(String publicName) {}

// private 带参构造(String,String)
private Person(String publicName,String privateName) {}


获取Person类中的构造方法

/* getConstructor */
 Constructor con = pc.getConstructor();
 Object object = constructor.newInstance();
	// {publicName='null', privateName='null'}
 Constructor con =  pc.getConstructor(String.class);
 Object object = constructor2.newInstance("Cat");
	// {publicName='Cat', privateName='null'}


/* getDeclaredConstructor */
 Constructor con = pc.getDeclaredConstructor(String.class,String.class,);
 declaredConstructor.setAccessible(true);
 Object object = declaredConstructor1.newInstance("Pig","Pug");
	// {publicName='Pig', privateName='Pug'}


/* getConstructors */
 Constructor[] cons = pc.getConstructors();
    // public test.Person()
	// public test.Person(java.lang.String,)


/* getDeclaredConstructors */
 Constructor[] cons = pc.getDeclaredConstructors();
	// public test.Person()
	// public test.Person(java.lang.String)
	// private test.Person(java.lang.String,java.lang.String)

获取成员方法

  • Method getMethod(String name, 类<?>… parameterTypes)
    • 返回一个 Method对象,反射 指定的 public成员方法类对象。
  • Method getDeclaredMethod(String name, 类<?>… parameterTypes)
    • 返回一个 Method对象,反射 指定的 成员方法类对象。
  • Method[] getMethods()
    • 返回一个 Method对象数组,反射 所有的 public成员方法类对象。
  • Method[] getDeclaredMethods()
    • 返回一个 Method对象数组,反射 所有的 成员方法类对象。

Person类中的成员方法

//    public修饰符
  public void publicMethod111(){System.out.println("publicMethod()...");}
  public void publicMethod222(String s){System.out.println("publicMethod("+ s +")...");}

//    private修饰符
  private void privateMethod(){System.out.println("privateMethod()...");}

//    protected修饰符
  protected void protectedMethod(){System.out.println("publicMethod()...");}

获取Person类中的成员方法

 Class pc = Person.class;
 Person p = new Person();

/* getMethod */
 Method method = personClass.getMethod("publicMethod111");
	// public void test.Person.publicMethod111()
 method.invoke(p);
	// publicMethod()...
 Method method = personClass.getMethod("publicMethod222", String.class);
	// public void test.Person.publicMethod222(java.lang.String)
 method.invoke(p,"带参");
	// publicMethod(带参)...

/* getDeclaredMethod */
Method method = pc.getDeclaredMethod("privateMethod");
	//private void test.Person.privateMethod()
method.setAccessible(true);
method.invoke(p);
	// privateMethod()...

/* getMethods */
 Method[] methods = personClass.getMethods();
 //public java.lang.String test.Person.toString()
 //public java.lang.String test.Person.getName()
 //public void test.Person.setName(java.lang.String)
 //public void test.Person.publicMethod111()
 //public void test.Person.publicMethod222(java.lang.String)
 //public void test.Person.setPublicAge(int)
 //public void test.Person.setProtectedName(java.lang.String)
 //public int test.Person.getPublicAge()
 // ................................

/* getDeclaredMethods */
Method[] methods = personClass.getDeclaredMethods();
 // public java.lang.String test.Person.toString()
 // public java.lang.String test.Person.getName()
 // public void test.Person.setName(java.lang.String)
 // public void test.Person.publicMethod111()
 // protected void test.Person.protectedMethod()
 // private void test.Person.privateMethod()
 // public void test.Person.publicMethod222(java.lang.String)
 // public void test.Person.setPublicAge(int)
 // public void test.Person.setProtectedName(java.lang.String)
 // ...............................


获取全类名

  • String getName()

其他操作

操作Field

  • 设置值
    • void set(Object obj, Object value)
  • 获取值
    • get(Object obj)
  • 暴力反射:忽略访问权限修饰符的安全检查
    • setAccessible(true):暴力反射
Class pc = Person.class;
Person p = new Person();

 /*public修饰符*/
Field fie = pc.getField("publicName");
	// public java.lang.String test.Person.publicName
fie.set(p,"cat");
System.out.print( fie.get(p) );
	// cat

 /*private修饰符*/
Field fie = pc.getDeclaredField("privateName");
	// private java.lang.String test.Person.privateName
pc.setAccessible(true);
pc.set(p,"dog");
System.out.print( fie.get(p) );
	// dog

操作Constructor

  • 创建对象
    • T newInstance(Object… initargs)
  • 如果使用空参数构造方法创建对象,操作可以简化
    • Class对象的newInstance方法
 
 /* Class */
 Class pc = Person.class;
 Object object = pc.newInstance();
	// {publicName='null', privateName='null'}


/* Constructor */
 Class pc = Person.class;
 Constructor con = pc.getConstructor();
 Object object = constructor.newInstance();
	// {publicName='null', privateName='null'}

操作Method

  • 执行方法
    • Object invoke(Object obj, Object… args)
  • 获取方法名
    • String getName
 Class pc = Person.class;
 Person p = new Person();
 Method method = personClass.getMethod("publicMethod111");
 method.invoke(p);
	// publicMethod()...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值