一、JAVA的反射
在学习反射的时候就没太弄明白,现在看了一些资料认真学习一下,暂时记录此刻的笔记。
1、java反射的概念:
就是java程序运行时才确定哪个类被加载了,编译器不知道该加载哪个类。这种特点就是反射。反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
其实我们的本地IDE就是使用了这种机制,当我们敲入某个类名然后按下.点号的时候,自动会提示你有哪些类的属性方法可以使用。
2、java反射的作用:
反编译:.class -> java
访问一个类的所有信息:
—获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息.
—检获属于一个接口的常量和方法声明.
—创建一个直到程序运行期间才知道名字的类的实例.
—获取并设置一个对象的成员,甚至这个成员的名字是
其实主要的作用两种:
一、扩展未知的应用,如在程序中定义了一些接口,只要实现了这些接口的dll都可以作为插件插入到这个程序中,那么要怎么实现,就可以通过反射,将dll加载进内存然后用反射的方式调用dll里面的方法。
二、加载配置文件,在编译器都无法知道类名,怎么使用死方法调用 new Classname();必须用到反射才能创建对象获取实例和方法。
3、常用的获取方法API
Class Demo1 . . . Class<?> class1 = null; Class<?> class2 = null; Class<?> class3 = null; // 一般采用这种形式,实现类对象创建 class1 = Class.forName("reflect.Demo1"); //使用包名加类名就可以 class2 = new Demo1().getClass(); class3 = Demo1.class;
public static void method_04() throws ClassNotFoundException { Class<?> c = Class.forName("java.lang.Integer"); Method[] methods = c.getDeclaredMethods(); //获取类中所有声明的方法 for (Method method : methods) { System.out.println(method.toString()); } }
二、工厂模式+反射的例子
1、介绍一下工厂模式:
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式不只由一个工厂类决定哪一个产品应该实例化,这个决定交给抽象工厂的子类去实现。
组成:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的!
2、实例介绍
抽象产品接口
package factory.unit; //定义一个抽象产品接口 public interface Animal { public void eatFood(); }
实现两个具体产品角色
//新建一个Dog类实现Animal的接口,并且实现其方法 public class Dog implements Animal{ @Override public void eatFood() { System.out.println("狗吃肉————————————————————"); } }
//新建一个Cat类实现Animal的接口,并且实现其方法 public class Cat implements Animal{ @Override public void eatFood() { // TODO Auto-generated method stub System.out.println("猫吃鱼*****************"); } }
实现工厂类
顺便插入一个单例模式的讲解:别人的博文:http://blog.csdn.net/jason0539/article/details/23297037/
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Properties; public class Factory { //创建私有的静态的properties对象 private static Properties pro = new Properties(); //加载配置文件 static{ try { pro.load(new FileInputStream("file.txt")); } catch (IOException e) { e.printStackTrace(); } } //单例模式,保证该类只能创建一个对象 private static Factory fc = new Factory(); private Factory(){} //static 可以直接类名.调用 public static Factory getFactory() { return fc; } //本方法为公有方法,用于生产接口对象 public Animal getInterface() { //定义接口对象 Animal am = null; try{ //根据键,获取文件中的值,这里的值是类的全路径 String classInfo = pro.getProperty("classpath"); //利用发射,生成Class对象 Class<?> c = Class.forName(classInfo); //获取该Class对象的实例 Object obj = c.newInstance(); //将实例对象转换成接口对象 am= (Animal)obj; }catch(Exception e) { e.printStackTrace(); } //返回接口对象 return am; } }
配置文件内容
classpath=factory.unit.Cat
测试类
import factory.unit.Animal; import factory.unit.Factory; public class FactoryModeTest { //测试函数,调用方 public static void main(String[] args) { // TODO Auto-generated method stub //获取工厂的实例 Factory fc = Factory.getFactory(); //调用获得接口对象的方法,获得接口对象 Animal testAnimal = fc.getInterface(); //调用接口的方法 testAnimal.eatFood(); } }
结果:
当配置文件输入的是classpath=factory.unit.Cat 结果就是猫吃鱼
当配置文件输入的是classpath=factory.unit.Dog结果就是狗吃肉
这样当我们更换产品的时候,只需要更改配置文件就可以,不需要重新修改代码,将new cat() 改成 new Dog();这就便于后期的修改和维护。