一. 什么是反射
在运行状态中,对于任意一个类,都能够知道其所有属性和方法,对于任意一个对象,都能够调用其任意方法和属性,这种动态获取信息、动态调用方法的能力称为Java语言的反射机制,大部分框架都有用到反射机制,了解反射的使用方法非常重要。
一个类通常包含了属性、方法、构造函数等,而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