2019独角兽企业重金招聘Python工程师标准>>>


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<m.length;i++){
System.out.println(m);
}
}
}


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("org.michael.Person");
}catch (Exception e){}
try{
p = (Person)c.newInstance();
}catch (Exception e){}
//上面两行代码也可以使用下面一行代码取代哈~
// p = (Person)Class.forName("org.michael.Person").newInstance();
p.setName("Michael");
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("org.michael.Person");
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("org.michael.Person");
Constructor[] cs = c.getConstructors();
Object obj[] = new Object[]{"Michael",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("Banana");
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("a","Apple");
p.setProperty("o","Orange");
p.setProperty("b","Banana");
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("a","Apple");
pro.setProperty("o","Orange");
//保存在文件之中
try{
pro.storeToXML(new FileOutputStream(new File("e:\\fruit.xml")),"FRUIT FACTORY");
}catch (Exception e){}
}
private void load(){
File f = new File("e:\\fruit.xml");
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()进行反射加载完成。

转载于:https://my.oschina.net/liu-xuewei/blog/66777

Java的反射机制 工厂模式综合讲解【转载自51CTO】相关推荐

  1. Java设计模式之简单工厂模式实验(软件工程综合实践课程第二周)

    实验目的 1 .理解软件设计的相关理论 : 2 .理解面向对象设计原则: 实验内容 1 .简单工厂模式实验: (1) 参考讲义上的代码,利用简单工厂模式完成计算器应用程序: (2) 画出计算器程序简单 ...

  2. Java的反射机制,内含超简单实例代码(搞懂反射,这一篇就够了)

    一 首先来说说反射机制的概念: 程序在运行时, 对于类来说,可以知道该类的任意属性和方法: 对于对象来说,可以调用该对象的任意方法和属性: 就以上这种动态获取信息的机制就称为Java的反射机制 彻底了 ...

  3. Java中的简单工厂模式(转)

    Java中的简单工厂模式 举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人 话说:"天地开辟,未有人民,女娲抟土为人."女娲需要用土造出一个个的人,但在女娲造出人之前, ...

  4. 搞懂Java的反射机制

    搞懂Java的反射机制 1.什么是反射? java的反射机制是指可以在运行状态下获取类和对象的所有属性和方法. 2.反射的作用? 1.在运行时获取一个类/对象的成员变量和方法 2.在运行时创建一个类的 ...

  5. 什么是Java的反射机制

    Java反射机制是Java的特点,是框架实现的基础,百度结果: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这 ...

  6. 反射与工厂模式:早餐店的发展之路

    实际开发中,接口的主要作用是为了不用层提供有一个操作的标准,如果直接实例化了类的操作[用new关键字来实例化],则一定存在耦合问题,可以用工厂模式解决此问题. 接下来用一个店主开早餐店的经历来阐述反射 ...

  7. java xml 反射_Java 读取XML文件以及Java 的反射机制实现

    Java 读取XML文件以及Java 的反射机制实现 代码部分 import java.io.File; import javax.xml.parsers.DocumentBuilder; impor ...

  8. java反射通俗解释,谁来帮用通俗易懂的语言解释下java的反射机制

    谁来帮用通俗易懂的语言解释下java的反射机制以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 谁来帮用通俗易懂的语言解释 ...

  9. Java的反射机制 —— 类的镜子

    Java的反射机制 -- 类的镜子 文章目录 Java的反射机制 -- 类的镜子 一.反射机制的原理 1.1.什么是反射? 1.2.反射机制的实现 1.3.获取类的Class对象的途径 1.4.运行时 ...

最新文章

  1. Android移动开发之【Android实战项目】在Service中弹出Dialog对话框,即全局性对话框
  2. windows下mongodb的安装与配置
  3. linux c 内存分配内存,Linuxc - 操作系统内存分配
  4. linux-权限案例-文件与目录权限
  5. mysql是怎样运行的书籍_《Mysql是怎样运行的》读书笔记三
  6. pta:6-1单链表逆转(20分)
  7. python web框架 多线程_Django基础一之web框架的本质
  8. krc2lrc(krc酷狗歌词转lrc)工具更新- 1.2 增加添加/拖放目录功能
  9. 记录因安装npcap带来的无线连接上不了网的问题
  10. centos host在哪 local_centos怎么查看hostid
  11. TV端影视APP开发搭建需要注意哪些问题?
  12. bzoj 4816 [Sdoi2017]数字表格——反演
  13. 百度AI市场热品试用 | 台面式双目活 体检测USB摄像头
  14. Spline(三次样条插值)
  15. mysql函数LOCATE、POSITION和INSTR
  16. JAVA——微博热搜爬虫
  17. 乐视腾讯深度合作 超级电视26日易迅网首发
  18. 学生信息管理系统(java+sqlserver)
  19. Google勇敢新世界:两个天才的相遇
  20. 手机蓝牙连不上jimu机器人_手机和蓝牙接收器配对不成功的常见问题和解决方案...

热门文章

  1. 一个电脑白痴与黑客的对话
  2. git2.29.2.2怎么安装_制作Win10安装U盘时install.wim大于4G怎么办?
  3. 神经网络与机器学习 笔记—支持向量机(SVM)(上)
  4. UVA11389巴士司机问题
  5. C语言-链表的创建头插法和尾插法(有无头节点)
  6. 【Groovy】编译时元编程 ( 方法拦截时用到的 AST 语法树节点 MethodNode 节点 | MethodNode 节点分析 | MethodNode 节点中的BlockStatement)
  7. 【C 语言】字符串模型 ( 字符串翻转模型 )
  8. 【JetPack】kotlin-android-extensions 插件 ( 视图绑定简单用法 )
  9. 【软件工程】CMMI 能力成熟度模型集成 ( CMMI 过程管理过程域 | CMMI 项目管理过程域 ) ★
  10. 【集合论】关系性质 ( 常见的关系的性质 | 关系性质示例 | 关系运算性质 )