Java的反射机制

在正常的情况下,肯定是需要先知道一个类的完整的“包.类”之后再产生对象,如果说现在想反着来,通过一个给定的对象知道对象所属的“包.类”,那么就必须依靠Object类中的getClass()方法完成了。

public class APIDemo{
    public static void main(String [] args){
        java.util.Date date = new java.util.Date();
        System.out.println(date.getClass().getName());
    }
}

现在可以通过对象反向回去了,而getClass()方法的定义如下:

     * Object 类定义方法:public final Class<?> getClass()

可以发现getClass()方法所返回的是一个Class类的实例化对

class Factory{
    public static Fruit getFruit(String className){
        Fruit instance = null;
        try{
            Class<?> cls = Class.forName(className);
            instance = cls.newInstance();

        }catch(Exception e){
            e.printStackTrace();
        }
         return instance;
    }
}
public class APIDemo{
    Fruit f = Factory.getFruit(""org.lxh.demo.Apple);
    f.eat();


}

象,而且还有泛型的定义,但是这种在反射上使用的泛型基本上没有任何的用处,都使用“?“表示。

取得Class类的实例化对象

对于Class类而言,其本身属于所有反射机制操作的源头,所以这个类的对象有三种实例化方式:

     *方式一:利用Object类中的getClass()方法完成;

public class APIDemo{
    public static void main(String [] args){
        java.util.Date date = new java.util.Date();
        System.out.println(date.getClass().getName());
    }
}

     *方式二:利用”类.class“取得Class类的实例对象;

public class APIDemo{
    public static void main(String [] args) throws Exception{
        Class<?> cls = java.util.Date.class;
        System.out.println(cls.getName);
    }
}

     *方式三:利用Class类的一个static 方法完成:

         方法:public static Class<?> forName(String className) throws ClassNotFoundException

               |-此方法将传入一个完整的”包.类“名称,而后取得Class类的实例化对象;

public class APIDemo{
    public static void main(String [] args){
        Class<?> cls = Class.forName("java.util.Date");
        System.out.println(cls.getName());    
    }
}

而这三种操作方法之中以forName()这种形式使用最多。

通过反射实例对象

当取得了一个实例化对象之后最大的好处是可以通过Class类的一个方法进行指定的对象实例化操作:

   方法:public  T  newInstance()  throws  InstantinationException,IllegalAccessException

范例:定义一个Person类

Class Person{
    public String toString(){
        return "Person类的一个对象";
    }
}

正常情况下可以利用构造方法及关键字new进行对象的实例化操作:

public class APIDemo{
    public static void main(String[] args) throws Exception{
        Person per = new Person();
        System.out.println(per);
    
    }
    
}

如果说现在有了反射机制,则此种操作就可以改变了:

public class APIDemo{
    public static void main(String [] args){
        Class<?> cls = Class.forName("org.lxh.demo.Person");
        Person per = (Person)cls.newInstance();
        System.out.prinltn(per);
    }
}

 通过以上的代码可以发现,使用反射操作可以替代掉关键字new实例化对象的过程。

对于现在对象的两种实例化方式,最常用的还是关键字new,但是反射机制的操作有其固定的应用范畴。

范例:工厂设计模式

 这种传统工厂设计模式有一个最大的问题在于:如果现在增加子类的话,一定要修改工厂类,那么如果说现在希望即使增加再多的子类,工厂类也可以不修改呢?那么就使用反射。

传统的工厂设计模式如下:

class Apple implements Fruit{
    public void eat(){
        System.out.println("***吃苹果");
}
class Factory{
    public static Fruit getFruit(String className){
        if("apple".equals(className)){
            return new Apple();
        }
    return null;
    }
}
public class APIDemo{
    public static void main(String[] args[]) throws Exception{
           Fruit f = Factory.getFruit("apple");        
            f.eat();
    }
}

使用反射机制的工厂模式如下:

interface Fruit{
    public void eat();
}
class Apple implements Fruit{
    System.out.println("***吃苹果");
}
class Orange implements Fruit{
    System.out.println("***吃橙子");
}
class Factory{
    public static Fruit getFruit(String className){
        Fruit instance = null;
        try{
            Class<?> cls = class.forName(className);
            instance = (Fruit)cls.newInstance();
        }catch(Exception e){
            e.printStackTrace();
        }
        return instance;
    }
}
public class APIDemo{
       public static void main(String [] args){
            Fruit f = Factory.getFruit("org.lxh.demo.Orange");
            f.eat();
    }
}

     通过反射机制可以让程序开发更加的灵活,因为使用反射方式实例化对象的时候只需要传入完整的”包.类“的字符串名称即可。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值