概念:
java反射机制是在运行状态中,对任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法;
这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
一些人听着反射,可能有些懵。主要是工作中几乎不需要接触。就像玩王者荣耀或lol,没有接触过的英雄,总觉得自己玩不好。
不过,反射比学一个英雄还简单点。主要是理解。
反射要点:
1. 获取需要的类 (Class类)
2. 获取该类的构造函数、成员变量、方法
3. 这步不说也知道是什么了吧。使用该类,赋值、调用方法。
第一步: 获取需要的Class类,直接看方式三; 方式1、2都可以不用了解。
package com.demo;
/**
* @author: wangqinmin
* @date: 2019/1/7 10:11
* @description: 仰天大笑出门去,我辈岂是蓬蒿人
*/
public class DemoTestOne {
/**
* 反射,最基本的获取class(字节码文件对象)的3种方式
*
* @param args
*/
public static void main(String[] args) {
getClassObjectOne();
System.out.println("----------");
getClassObjectTwo();
System.out.println("----------");
try {
getClassObjectThree();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取字节码对象的第一种方式:不适合扩展
* 1. Object类中的getClass方法
* 要求:想用这种方法,必须要明确知道具体的类,并创建对象
*/
public static void getClassObjectOne() {
Person p = new Person();
Class<? extends Person> c1 = p.getClass();
Person p1 = new Person();
Class<? extends Person> c2 = p1.getClass();
System.out.println(c1 == c2);
}
/**
* 第二种方式:不适合扩展
* 任何数据类型都具备一个静态的属性.class,所以通过这个获取其对应的Class对象。
* 要求:这种方式,相对简单。但是还是要明确知道类中的静态成员
*/
public static void getClassObjectTwo() {
Class<Person> c1 = Person.class;
Class<Person> c2 = Person.class;
System.out.println(c1 == c2);
}
方式三:(上面的方式一,方式二,看看就好了)
要求:给定类的字符串名称
java.lang
类 Class<T>,该类的方法,有很多。用于反射正好
public static void getClassObjectThree() throws ClassNotFoundException {
// 传入参数:包名 + 类名
String className = "com.demo.Person";
Class<?> c1 = Class.forName(className);
System.out.println(c1);
}
}
我把反射要用的Person类,也贴出来:
package com.demo;
/**
* @author: wangqinmin
* @date: 2019/1/7 10:44
* @description: 仰天大笑出门去,我辈岂是蓬蒿人
*/
public class Person {
private Integer age;
private String name;
public Person(Integer age, String name) {
this.age = age;
this.name = name;
System.out.println("有参构造方法");
}
public Person() {
System.out.println("无参构造方法");
}
public void show() {
System.out.println(name + ",show方法," + age);
}
public void method() {
System.out.println("方法运行");
}
public void paramMethod(String str, int num) {
System.out.println("传入参数:" + str + "," + num);
}
public static void staticMethod() {
System.out.println("静态方法运行");
}
}
接下来就是第二步了:
使用反射的Class对象,获取构造函数、成员变量,成员方法,一个完整的例子。
先说要点:
1. 反射相当于new 对象,既然是new 对象。
注意问题: 该对象是否有无参构造,或者构造函数是否被私有
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* @author: wangqinmin
* @date: 2019/1/8 10:27
* @description: 仰天大笑出门去,我辈岂是蓬蒿人
*/
public class DemoTestTwo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
若该对象有public修饰的无参构造,反射new 对象
Class<?> personClass = Class.forName("com.demo.Person");
创建Class对象所表示的新对象,被创建对象必须提供无参构造
Person person = (Person) personClass.newInstance();
System.out.println("----------------");
1. 获取所有public、private等修饰的构造方法
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
1. 若被反射的对象,没有无参构造时。先获取构造函数
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor con : constructors) {
System.out.println(con);
// public com.demo.Person(java.lang.Integer,java.lang.String)
// public com.demo.Person()
}
System.out.println("----------------");
1.1 通过获取构造函数 创建对象
Constructor<?> constructor = personClass.getConstructor(Integer.class, String.class);
System.out.println(constructor);
通过构造器对象,初始化对象(实例化)
Object obj = constructor.newInstance(12, "蔡文姬");
System.out.println("----------------");
2. 获取public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("----------------");
2. 能够获取private修饰的成员变量
Field[] declaredFields = personClass.getDeclaredFields();
for (Field d : declaredFields) {
System.out.println(d);
}
System.out.println("----------------");
3. 获取public修饰的方法方法
Method[] methods = personClass.getMethods();
for (Method m : methods) {
System.out.println(m);
// public void com.demo.Person.method()
// public void com.demo.Person.paramMethod(java.lang.String,int)
// public void com.demo.Person.show()
// public static void com.demo.Person.staticMethod()
// public final void java.lang.Object.wait() throws java.lang.InterruptedException
// public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
// public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
// public boolean java.lang.Object.equals(java.lang.Object)
// public java.lang.String java.lang.Object.toString()
// public native int java.lang.Object.hashCode()
// public final native java.lang.Class java.lang.Object.getClass()
// public final native void java.lang.Object.notify()
// public final native void java.lang.Object.notifyAll()
}
System.out.println("----------------");
3. 获取所有本类中的所有方法
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method m : declaredMethods) {
System.out.println(m);
// public void com.demo.Person.method()
// public void com.demo.Person.show()
// public void com.demo.Person.paramMethod(java.lang.String,int)
// public static void com.demo.Person.staticMethod()
}
System.out.println("----------------");
}
}
接下来就是一个小练习,使用反射,这里面深度解析为什么使用反射,反射的应用场景:
https://blog.csdn.net/chuxin_mm/article/details/86507928