反射机制与工厂设计模式
更新时间:2023-11-19 14:04:01 阅读量: 教育文库 文档下载
[零基础学JAVA]Java SE应用部分-36.反射机制与工厂设计模式
Java的反射机制 工厂模式综合讲解 1、什么叫反射
Java.lang.reflect包下
正常情况下我们可以通过类实例化一个对象,那么通过反射实际上就可以通过一个对象得到此类完整的包.类名称。
package org.michael; class Person{
private String name; private int age;
public void setName(String name){ this.name = name; }
public void setAge(int age){ this.age = age; }
public String getName(){ return this.name; }
public int getAge(){ return this.age; } }
public class Demo01{
public static void main(String args[]){ Person p = new Person();
//假设现在不知道p是那个类的对象,则可以通过反射机制找到 Class c = null; c = p.getClass();
System.out.println(c.getName()); } }
看下效果:
除了可以找到对象所在的包.类名称,实际上也可以把所有的方法名称列出来。
package org.michael; import java.lang.reflect.*; class Person{
private String name; private int age;
public void setName(String name){ this.name = name; }
public void setAge(int age){ this.age = age; }
public String getName(){ return this.name; }
public int getAge(){ return this.age; } }
public class Demo02{
public static void main(String args[]){ Person p = new Person();
//假设现在不知道p是那个类的对象,则可以通过反射机制找到 Class c = null; c = p.getClass();
Method m[] = c.getMethods(); for(int i=0;i 2、研究Class类 Class类的构造方法被私有化了,外部无法直接看见,所以其内部必然有一个方法可以取得Class 实例。 public static Class> forName(String className) throws ClassNotFoundException 此方法可以返回Class类的实例,此方法接收一个完整的包.类名称。 通过newInstance方法,可以将传入的完整的字符串(包.类名称)实例化。 package org.michael; import java.lang.reflect.*; class Person{ private String name; private int age; public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } public String getName(){ return this.name; } public int getAge(){ return this.age; } } public class Demo03{ public static void main(String args[]){ Person p = null; Class c = null; try{ c = Class.forName(\); }catch (Exception e){} try{ p = (Person)c.newInstance(); }catch (Exception e){} //上面两行代码也可以使用下面一行代码取代哈~ // p = (Person)Class.forName(\ p.setName(\); p.setAge(30); System.out.println(p.getName()+\+p.getAge()); } } 如果要使用以上的代码去实例化一个对象,则必须有一个前途条件:在对象所在的类中必须有一个无参构造方法,如果没有此无参构造,则肯定会出现错误。 package org.michael; import java.lang.reflect.*; class Person{ private String name; private int age; public Person(String name,int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } public String getName(){ return this.name; } public int getAge(){ return this.age; } } public class Demo04{ public static void main(String args[]){ Person p = null; Class c = null; try{ c = Class.forName(\); p = (Person)c.newInstance(); }catch (Exception e){ System.out.println(e); } System.out.println(p.getName()+\+p.getAge()); } } 在此时如果想继续通过此操作为对象进行实例化,则可以通过构造方法类(Constructor)完成。 package org.michael; import java.lang.reflect.*; class Person{ private String name; private int age; public Person(String name,int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } public String getName(){ return this.name; } public int getAge(){ return this.age; } } public class Demo05{ public static void main(String args[]){ Person p = null; Class c = null; try{ c = Class.forName(\); Constructor[] cs = c.getConstructors(); Object obj[] = new Object[]{\,30}; //一个类中会有多个构造方法,所以此时返回一个数组 p = (Person)cs[0].newInstance(obj); }catch (Exception e){ System.out.println(e); } System.out.println(p.getName()+\+p.getAge()); } } 反射机制实际上是我们所有框架的一个基础,那么现在就利用反射机制完成一个高可扩展性的工厂设计。 回顾:工厂设计 interface Fruit{ public void grow(); public void eat(); } class Apple implements Fruit{ public void grow(){ System.out.println(\苹果在生长...\); } public void eat(){ System.out.println(\吃苹果...\); } } class Orange implements Fruit{ public void grow(){ System.out.println(\橘子在生长...\); } public void eat(){ System.out.println(\吃橘子...\); } } class Factory{ public static Fruit getFruit(int i){ Fruit f = null; if (i==1){ f = new Apple(); } if (i==2){ f = new Orange(); } return f; } } public class Demo06{ public static void main(String args[]){ Fruit f = Factory.getFruit(1); f.grow(); } } 客户端只与工厂和直接的接口有关了,而与其他的无关,但是有个问题,如果现在要扩展了子类,则工厂也必须同时进行修改。那么有没有一种方法,可以让子类扩充之后不去修改工厂呢?肯定是有的,通过Class.forName 完成。 interface Fruit{ public void grow(); public void eat(); } class Apple implements Fruit{ public void grow(){ System.out.println(\苹果在生长...\); } public void eat(){ System.out.println(\吃苹果...\); } } class Orange implements Fruit{ public void grow(){ System.out.println(\橘子在生长...\); } public void eat(){ System.out.println(\吃橘子...\); } } class Banana implements Fruit{ public void grow(){ System.out.println(\香蕉在生长...\); } public void eat(){ System.out.println(\吃香蕉...\); } } class Factory{ public static Fruit getFruit(String className){ Fruit f = null; try{ f = (Fruit)Class.forName(className).newInstance(); }catch (Exception e){} return f; } } public class Demo07{ public static void main(String args[]){ Fruit f = Factory.getFruit(\); f.grow(); } } 但是此程序依然有一个缺点,现在的输入的包.类名称实际上长度非常的短,如果包.类名称的长度过长了,则在使用的时候就比较麻烦了。所以最好可以找个代号进行替代。 使用Hashtable的子类 —— Properties完成。 import java.util.*; import java.io.*; interface Fruit{ public void grow(); public void eat(); } class Apple implements Fruit{ public void grow(){ System.out.println(\苹果在生长...\); } public void eat(){ System.out.println(\吃苹果...\); } } class Orange implements Fruit{ public void grow(){ System.out.println(\橘子在生长...\); } public void eat(){ System.out.println(\吃橘子...\); } } class Banana implements Fruit{ public void grow(){ System.out.println(\香蕉在生长...\); } public void eat(){ System.out.println(\吃香蕉...\); } } class Factory{ public static Fruit getFruit(String className){ Fruit f = null; try{ f = (Fruit)Class.forName(className).newInstance(); }catch (Exception e){} return f; } } class InputData{ private BufferedReader buf = null; public InputData(){ this.buf = new BufferedReader(new InputStreamReader(System.in)); } public String getString(){ String str = null; try{ str = this.buf.readLine(); }catch (Exception e){} return str; } } public class Demo08{ public static void main(String args[]){ Properties p = new Properties(); p.setProperty(\,\); p.setProperty(\,\); p.setProperty(\,\); System.out.println(p); System.out.print(\请选择所需要的类型:\); String str = new InputData().getString(); //进一步扩展,现在可以由用户自己输入要使用的类型 Fruit f = Factory.getFruit(p.getProperty(str)); f.grow(); } } 如果现在再增加子类呢? 属性文件肯定不够了。 所以此时为了达到好的效果,则最好可以将属性保存起来,之后通过修改保存的文件达到属性的扩充。 import java.util.*; import java.io.*; interface Fruit{ public void grow(); public void eat(); } class Apple implements Fruit{ public void grow(){ System.out.println(\苹果在生长...\); } public void eat(){ System.out.println(\吃苹果...\); } } class Orange implements Fruit{ public void grow(){ System.out.println(\橘子在生长...\); } public void eat(){ System.out.println(\吃橘子...\); } } class Banana implements Fruit{ public void grow(){ System.out.println(\香蕉在生长...\); } public void eat(){ System.out.println(\吃香蕉...\); } } class Factory{ public static Fruit getFruit(String className){ Fruit f = null; try{ f = (Fruit)Class.forName(className).newInstance(); }catch (Exception e){} return f; } } class PropertyOperate{ private Properties pro = null; public PropertyOperate(){ this.pro = new Properties(); this.load(); } //设置一个返回方法 public Properties getPro(){ return this.pro; } //从文件中读出属性,如果文件不存在,则创建一个默认的 private void save(){ pro.setProperty(\,\); pro.setProperty(\,\); //保存在文件之中 try{ pro.storeToXML(new FileOutputStream(new File(\)),\); }catch (Exception e){} } private void load(){ File f = new File(\); if(f.exists()){ //文件存在则可以读取 try{ pro.loadFromXML(new FileInputStream(f)); }catch (Exception e){} }else{ //进行创建 this.save(); } } } class InputData{ private BufferedReader buf = null; public InputData(){ this.buf = new BufferedReader(new InputStreamReader(System.in)); } public String getString(){ String str = null; try{ str = this.buf.readLine(); }catch(Exception e){} return str; } } public class Demo09{ public static void main(String args[]){ Properties p = new PropertyOperate().getPro(); System.out.println(p); System.out.print(\请选择所需要的类型:\); String str = new InputData().getString(); //进一步扩展,现在可以由用户自己输入要使用的类型 Fruit f = Factory.getFruit(p.getProperty(str)); f.grow(); } } 如果此时要想新增加可以操作的子类,则就需要配置fruit.xml文件即可。 此种代码是典型的配置与程序相分离,程序直接有配置文件有关。某一个部分的修改不影响其他程序。—— 思想必须建立起来。 总结 对象的产生到底有多少种方法了: · 直接用new关键字产生:直接,但是代码间会产生严重的耦合性 · 可以通过工厂传递引用:直接,但是必须考虑到代码以后的可维护性 · 通过对象克隆可以完成 · 通过Class.forName()进行反射加载完成 //进行创建 this.save(); } } } class InputData{ private BufferedReader buf = null; public InputData(){ this.buf = new BufferedReader(new InputStreamReader(System.in)); } public String getString(){ String str = null; try{ str = this.buf.readLine(); }catch(Exception e){} return str; } } public class Demo09{ public static void main(String args[]){ Properties p = new PropertyOperate().getPro(); System.out.println(p); System.out.print(\请选择所需要的类型:\); String str = new InputData().getString(); //进一步扩展,现在可以由用户自己输入要使用的类型 Fruit f = Factory.getFruit(p.getProperty(str)); f.grow(); } } 如果此时要想新增加可以操作的子类,则就需要配置fruit.xml文件即可。 此种代码是典型的配置与程序相分离,程序直接有配置文件有关。某一个部分的修改不影响其他程序。—— 思想必须建立起来。 总结 对象的产生到底有多少种方法了: · 直接用new关键字产生:直接,但是代码间会产生严重的耦合性 · 可以通过工厂传递引用:直接,但是必须考虑到代码以后的可维护性 · 通过对象克隆可以完成 · 通过Class.forName()进行反射加载完成
正在阅读:
反射机制与工厂设计模式11-19
2018媒体与设计学院第5届文化产业-上海交通大学媒体与传播学院12-24
各省军区独立师历史沿革04-25
高考数学模拟试题文新人教A版04-27
海南工业竞争力研究07-22
文中考命题思路例举03-08
机械基础练习题11-21
古代汉语现代汉语笔记03-17
交通运输局上半年工作总结及下半年工作思路08-04
奥数讲座 - 五年级组合图形的面积04-16
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 设计模式
- 反射
- 机制
- 工厂
- 外贸函电课程重点 - 外贸函电 Unit 7
- 破茧成蝶的蜕变 - 群文阅读
- 太阳镜材质对比手册
- 打孔机生产效能的提高优秀作品 - 图文
- 机动车驾驶人社会化考试场监督管理办法实施细则
- 高校物理自主招生试题
- 北京工业大学2008高数工-2期末考试-A卷工 -
- 2011学年四年级测试题
- FCD11040
- Matlab(8)-数据拟合
- 计算机网络复习题 - 图文
- 大坪明德小学校园文化核心理念
- 5 古诗两首《宿新市徐公店》
- 第二章信用与利息练习题
- XX县发展和改革委员会2011年上半年社会治安综合治理工作总结
- 理论力学练习册题及解答
- 华农2011年信息学院计算机网络A卷(含答案) - 图文
- 中职体育教师专业化发展策略研究
- 复旦大学校长许宁生
- 半结构化面试经典题目及解答思路