反射的概念
-
Java反射机制是在运行状态时,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。
-
通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
-
要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
获取class对象方式(3种方式)
-
Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
多用于配制文件,将类名定义在配置文件中。读取文件,加载类。
-
类名.class: 通过类名的属性class获取
多用于参数的传递
-
对象.getClass():getClass()方法在Object类中定义着。
多用于对象的获取字节码的方式
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。
定义一个Person类,利用三种反射方式获取class对象
//定义Person类
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
/*利用三种反射方式获取class对象
1、Class.forName("全类名")
2、类名.class
3、对象.getClass()
*/
public class reflect {
public static void main(String[] args) throws ClassNotFoundException {
//Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
Class cls1 = Class.forName("Person");
System.out.println(cls1);//class Person
//类名.class: 通过类名的属性class获取
Class cls2 = Person.class;
System.out.println(cls2);//class Person
//对象.getClass():getClass()方法在Object类中定义着。
Person person = new Person();
Class cls3 = person.getClass();
System.out.println(cls3);//class Person
// == 比较3个对象
System.out.println(cls1==cls2);//true
System.out.println(cls2==cls3);//true
}
}
反射对象的使用
获取成员变量们
Field [] getFields() // 获取所有public修饰的成员变量
Field [] getField(String name) // 获取指定名称的public修饰的成员变量
Field [] getDeclaredFields() //获取所有的成员变量,不考虑修饰符
Field [] getDeclaredFields(String name) //获取指定的成员变量,不考虑修饰符
//Demo 获取成员变量们,定义Person类,利用反射获取成员变量们
public class Person {
public int a;
public String b;
protected String c;
private String name;
private int age;
private String d;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a=" + a +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
public void eat() {
System.out.println("eat....");
}
public void eat(String food) {
System.out.println("eat..." + food);
}
}
//利用反射获取成员变量们
import java.lang.reflect.Field;
public class reflect {
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class<Person> personClass = Person.class;
//1.Field[] getFields()获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field); //public int Person.a
//public java.lang.String Person.b
}
System.out.println("=====================");
//2.Field getField(String name)
Field b = personClass.getField("b");
//获取成员变量a的值
Person p = new Person();
Object value = b.get(p);
System.out.println(value); // null
//设置a的值
b.set(p,"张三");
System.out.println(p);//Person{name='null', age=0, a=0, b='张三', c='null', d='null'}
System.out.println("================");
//Field [] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
/*
private java.lang.String Person.name
private int Person.age
public int Person.a
public java.lang.String Person.b
protected java.lang.String Person.c
private java.lang.String Person.d
*/
//Field getDeclaredField(String name)
Field d = personClass.getDeclaredField("d");
//忽略访问权限修饰符的安全检测
d.setAccessible(true); //暴力反射
Object value2 = d.get(p);
System.out.println(value2); //null
//Field [] getDeclaredFields(String name)
}
}
获取构造方法们
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors()
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class reflect2 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//0.获取Person的Class对象
Class<Person> personClass = Person.class;
//Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
//创建对象
Person p = constructor.newInstance("张三", 28);
System.out.println(p);//Person{name='张三', age=28, a=0, b='null', c='null', d='null'}
Constructor<Person> constructor2 = personClass.getConstructor();
Person p2 = constructor2.newInstance();
System.out.println(p2);//Person{name='null', age=0, a=0, b='null', c='null', d='null'}
Person p3 = personClass.newInstance();
System.out.println(p3);
}
}
获取成员方法们
Method[] getMethods()
Method getMethod(String name,类<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name,类<?>... parameterTypes)
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflect3 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//0.获取Person的Class对象
Class<Person> personClass = Person.class;
//获取指定名称的方法
Method eat_method = personClass.getMethod("eat");
//执行方法
Person p = new Person();
eat_method.invoke(p);//eat....
Method eat_method2 = personClass.getMethod("eat",String.class);
eat_method2.invoke(p,"饭");//eat...饭
Method[] methods = personClass.getMethods();
for (Method method : methods) {
//System.out.println(method);
String name = method.getName();
System.out.println(name);
}
//获取类名
String className = personClass.getName();
System.out.println(className);
}
}
获取类名
String getName()
成员变量&构造方法&方法对象的应用
Field:成员变量
*操作:
1.设置值
* void set(Object obj,Object value)
2.获取值
* get(Object obj)
3.忽略访问权限修饰符的安全检查
* setAccessible(true) 暴力反射
Constructor:构造方法
创建对象:
* T newInstance(Object... initargs)
* 如果使用空参数构造方法创建对象,操作可简化:Class对象的newInstance方法
Method:方法对象:
执行方法:
* 执行方法:
* Object invoke(Object obj,Object... args)
* 获取方法名称:
* String getName:获取方法名