首页 > 代码库 > 从零开始学java (四)反射

从零开始学java (四)反射

  反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为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;
    }
    

    
}
View Code
技术分享
    @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()可以获取类名
    }
    
View Code

  例如加载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));
    }    
View Code

  将反射应用在工厂方法

技术分享
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();
        }
    }
}
View Code

 

从零开始学java (四)反射