引言:这里结合工厂模式和接口来记录对于反射的理解。代码和文字部分源于网络。对其进行了重新整理。反射机制对于普通开发者而言,意义不大,一般都是作为一些系统的架构设计去使用的,包括以后学习的开源框架,几乎都使用了反射机制。
反射概念
- 反射之后的“反”是针对与“正”来的。那什么是正?就是使用一个类构造一个对象的过程:类——>对象;因此,“反”即是:对象——>类。
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类,降低了耦合性
*/