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

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

反射概念
  • 反射之后的“反”是针对与“正”来的。那什么是正?就是使用一个类构造一个对象的过程:类——>对象;因此,“反”即是:对象——>类。
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值