一. 什么是反射
在运行状态中,对于任意一个类,都能够知道其所有属性和方法,对于任意一个对象,都能够调用其任意方法和属性,这种动态获取信息、动态调用方法的能力称为Java语言的反射机制,大部分框架都有用到反射机制,了解反射的使用方法非常重要。
ASP站长网一个类通常包含了属性、方法、构造函数等,而Java一般情况下是现有类再有对象,通过对象调用各种属性和方法,而Java反射则是通过已有的对象,反过来得到其所属类的相关信息,调用所属类的相关方法。
二. 反射的基础Class
2.1 Class类概述
我们知道在Java的世界中,万事万物皆对象。其实类本身也是对象,任何一个类都是Class类的实例对象。
//定义了一个SuperHero的类
public class SuperHero {}
如上面定义的SuperHero类,是类也是对象,
对象:SuperHero类是Class类的实例,Class类是SuperHero的类类型,故而为对象;
类:以类的方式创建,SuperHero本身可以调用SuperHero ironMan = new SuperHero ()被实例化,ironMan 就是创建的实体,故而也是类。
Class类很特殊,它表示了某个类的类类型,被不可被继承,每个类的Class对象仅有一个,Class类没有公共构造函数。 相反, Class对象由Java虚拟机自动构建,因为加载了类,并且通过调用类加载器中的defineClass方法,原始Java类型( boolean , byte , char , short , int , long , float和double ),和关键字void也表示为Class对象
//Class源码,final修饰不可被继承,构造函数是private的,不可手动实例化
public final class Class<T> {
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
}
public static void main(String[] args) {
try {
Class clazz1 = Class.forName("java.lang.Integer");
Class clazz2 = Class.forName("java.lang.Integer");
System.out.println(clazz1 == clazz2);
System.out.println(int.class);
System.out.println(void.class);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
运行结果为:
true
int
void
2.2 Class类对象获取的三种方式
先定义一个类
package reflectdemo;
import java.io.Serializable;
/**
* 超级英雄类
*/
public class SuperHero implements Serializable {
public static final String ADDRESS = "earth";
private String id;
private String name;
private Integer age;
private String skill;
public SuperHero() {
}
public SuperHero(String id, String name, Integer age, String skill) {
this.id = id;
this.name = name;
this.age = age;
this.skill = skill;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
public void print(){
System.out.println("超级英雄:" + this.name);
}
}
2.2.1 通过对象获取Class
public static void main(String[] args) {
SuperHero ironMan = new SuperHero("1","钢铁侠",35, "战甲");
Class clazz = ironMan.getClass();
System.out.println(clazz.getName());
}
输出结果:
reflectdemo.SuperHero
2.2.2 通过类获取Class
public static void main(String[] args) {
Class clazz = SuperHero.getClass();
System.out.println(clazz.getName());
}
输出结果:
reflectdemo.SuperHero
2.2.3 传入类路径获取Class
public static void main(String[] args) {
try {
Class clazz = Class.forName("reflectdemo.SuperHero");
System.out.println(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
输出结果:
reflectdemo.SuperHero
三种创建方式:
第一种方式对象已经有了,所有的操作直接通过该对象进行即可,
第二种方式需要import将类引入,也不是常用的方式,
第三种仅需传入类的路径,即可得到类的相关信息,是最常用的方式。
2.2.4 获取类信息的常用方法
public static void main(String[] args) {
try {
Class clazz = Class.forName("reflectdemo.SuperHero");
//获取类名称(含路径)
System.out.println(clazz.getName());
//获取类名称(不含路径)
System.out.println(clazz.getSimpleName());
//获取所在包
System.out.println(clazz.getPackage());
//通过Class创建对象
SuperHero hero = (SuperHero)clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
输出结果:
reflectdemo.SuperHero
SuperHero
package reflectdemo
这里提前说明一下:Class中两个功能相同的方法,若其中一个带有Declared字样,表示针对类中所有声明的变量、方法、构造函数等,而对应不带Declared字样的方法,则表示仅对公有(public)成员变量、方法起作用,下面不再重复描述,下面仅对带有Declared字样的方法进行讲解。