JAVA高级用法 —— 反射(一)

来源:互联网 发布:千月软件序列号 编辑:程序博客网 时间:2024/06/05 19:48

引言:这里结合工厂模式和接口来记录对于反射的理解。代码和文字部分源于网络。对其进行了重新整理。反射机制对于普通开发者而言,意义不大,一般都是作为一些系统的架构设计去使用的,包括以后学习的开源框架,几乎都使用了反射机制。

反射概念

  • 反射之后的“反”是针对与“正”来的。那什么是正?就是使用一个类构造一个对象的过程:类——>对象;因此,“反”即是:对象——>类。
package reflection;class Apple{}public class Demo{    public static void main(String[] args) throws Exception    {        Apple a = new Apple(); //正向操作        System.out.println(a.getClass().getName());//反向操作    }}
  • 反向操作即通过使用一个getClass()方法,得到对象所在的“package.Class”,返回一个Class类对象,这就是一切反射机制的根源。

获取Class类的三种方法

  • 通过Object类的getClass()方法,很少用此方法:
package reflection;class Apple{}public class Demo{    public static void main(String[] args) throws Exception    {        Apple a = new Apple(); //正向操作        System.out.println(a.getClass().getName());//反向操作    }}
  • 使用“类.class”获得Class对象:
package reflection;class Apple{}public class Demo{    public static void main(String[] args) throws Exception    {        Class c = Apple.class;        System.out.println(cls.getName());    }}
  • 使用Class类内部定义的static方法:
package reflection;class Apple{}public class Demo{    public static void main(String[] args) throws Exception    {        Class cls = Class.forName("reflection.Apple");        System.out.println(cls.getName());    }}
  • 通过反射实例化对象:
package reflection;class Apple{    @Override public String toString()    {        return "eating an apple...";    }}public class Demo{    public static void main(String[] args) throws Exception    {        Class cls = Class.forName("reflection.Apple");        Object obj = cls.newInstance(); //实例化对象,此处和关键字new是一样的        Apple a = (Apple) obj;//转换类型        System.out.println(obj);     }}

应用中的反射

  • 在“通过反射实例化对象”一部分中,对于对象的实例化操作,除了使用new关键字之外,又多了一个反射机制操作,增加了复杂性,然而有什么用?对于程序的开发模式,一直要求尽量减少耦合,而减少耦合的最好方法就是使用接口,但是就算使用了接口也避不开关键字new。所以new是造成耦合的关键。但是,通过反射机制和接口就可以避免new造成的耦合。
  • 原始版工厂设计模式
package reflection;interface Fruit{    public void eat();}class Apple implement Fruit{    public void eat()    {        System.out.println("eating an apple...");    }}class Factory{    public static Fruit getInstance(String className)    {        if("Apple".equals(className))        {            return new Apple();        }        return null;    }}public class FactoryDemo{    public static void main(String[] args)    {        Fruit f = Factory.getInstance("Apple");        f.eat();    }}/**  * 这是最简单的工厂设计模式,但是其中有一个最大的问题:如果现在实现接口的类增加  * 了,那么Factory类肯定需要修改,问题的原因就在与Factory类getInstance方法  * 中的new,如果使用反射机制,就可避免该类问题。  */
  • 使用反射机制的工厂类,此处使用第三种获得Class对象的方法。
package reflection;interface Fruit{    public void eat();}class Apple implement Fruit{    public void eat()    {        System.out.println("eating an apple...");    }}class Orange implement Fruit{    public void eat()    {        System.out.println("eating an orange...");    }}class Factory{    public static Fruit getInstance(String className)    {        Fruit temp = null;        try        {            temp = (Fruit)Class.forName(className).newInstance();        }        catch(Exception e)        {            e.printStackTrace();        }        return temp;    }}public class FactoryDemo{    public static void main(String[] args)    {        Fruit apple = Factory.getInstance("reflection.Apple");        apple.eat();        Fruit orange = Factory.getInstance("reflection.Orange");        orange.eat();    }}/**  * 这样不论实现接口的类有多少,都不需要改动Factory类,降低了耦合性  */
0 0