反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Class 类 ,一个Class对象将表示一个类的属性;获取Class类一共有三种方式如下
package javase.first; /** * @author fqh * @Date 2017年4月12日:上午8:15:01 */ public class Employee { //属性,私有化属性,并提供方法让其能够通过方法访问 private String name; private int age; private double salary; private static final int NUMBER=217; //常量 private static void method1(){ System.out.println("静态方法"); } static{ System.out.println("静态块"); } public Employee(){ } //构造器 public Employee(String name,int age,double salary){ this.name=name; this.age=age; this.salary=salary; System.out.println("构造器"); } public void raiseSalary(double multiple){ this.salary *= multiple; } 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; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } }
@Test public void testReflect() { Employee e =new Employee("fqh", 23, 5000); Class class1 = null; Class class2 = null; Class class3 = null; try { //推荐这种 class1 = Class.forName("javase.first.Employee"); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } //第二种 class2=Employee.class; //第三种 class3=e.getClass(); System.out.println(class1.getName()+" "+e.getName());//通过Class。getName()可以获取类名 System.out.println(class2.getName()+" "+e.getName());//通过Class。getName()可以获取类名 System.out.println(class3.getName()+" "+e.getName());//通过Class。getName()可以获取类名 }
例如加载jdbc驱动的时候Class.forName("com.mysql.jdbc.Driver");
假如我需要获取类的属性方法等等,该怎么做呢?
@Test public void testReflect2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchFieldException { Class class1 = null; try { //推荐这种 class1 = Class.forName("javase.first.Employee"); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } System.out.println(class1.getName());//通过Class。getName()可以获取类名 System.out.println("===============本类属性==============="); //获取所有属性 ,getFields()是获取所有公有的方法 Field[] fields =class1.getDeclaredFields(); for(Field f:fields) { // 权限修饰符 int mo = f.getModifiers(); String priv = Modifier.toString(mo); // 属性类型 Class<?> type = f.getType(); System.out.println(priv + " " + type.getName() + " " + f.getName() + ";"); } System.out.println("===============本类方法==============="); Method[] methods =class1.getDeclaredMethods(); for(Method f:methods) { // 权限修饰符 int mo = f.getModifiers(); String priv = Modifier.toString(mo); // 属性类型 Class<?> type = f.getReturnType(); System.out.println(priv + " " + type.getName() + " " + f.getName() + ";"); } System.out.println("===============通过反射机制调用方法==============="); Object obj = class1.newInstance(); Method method = class1.getMethod("setName", String.class); method.invoke(obj,"fqh"); method = class1.getMethod("getName"); method.invoke(obj); Employee e = (Employee) obj ; System.out.println(e.getName()); System.out.println("===============通过反射机制修改属性==============="); Field field =class1.getDeclaredField("name"); // 可以直接对 private 的属性赋值 field.setAccessible(true);//将属性设为可修改 field.set(obj, "Java反射机制"); System.out.println(field.get(obj)); }
将反射应用在工厂方法
interface fruit { public abstract void eat(); } class Apple implements fruit { public void eat() { System.out.println("Apple"); } } class Orange implements fruit { public void eat() { System.out.println("Orange"); } } class Factory { public static fruit getInstance(String ClassName) { fruit f = null; try { f = (fruit) Class.forName(ClassName).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; } } /** * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。 * Java 工厂模式可以参考 * http://baike.xsoftlab.net/view/java-factory-pattern * * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。 * * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。 * * java 读取 properties 配置文件 的方法可以参考 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file * * @author xsoftlab.net */ public class TestReflect { public static void main(String[] args) throws Exception { fruit f = Factory.getInstance("net.xsoftlab.baike.Apple"); if (f != null) { f.eat(); } } }