java反射学习(结合工厂方法)
来源:互联网 发布:stm8单片机 编辑:程序博客网 时间:2024/06/06 03:32
java反射的应用
- 什么是反射?
JAVA反射机制是就是运行的状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 - 反射的应用场景?
在讲反射的应用场景之前,先来讨论一个开发当中碰到的场景。一步步深入,最后就会发现反射对于代码的质量会有一个质的提升。 - 假设我们的数据库是mysql,那么我们的代码中会出现如下代码
Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection(url, user, password);
而如果我们的数据库是oracle,我们的代码会如下:
Class.forName("oracle.jdbc.driver.OracleDriver");conn = DriverManager.getConnection(url, user, password);
如果这时候数据库换成了sql server,我们也只需要修改一下Class.forName()的参数。这对于开发者来说是相当方便的,如果java没有提供jdbc。一切和数据库的交互我们都需要从底层实现,那么菜鸟的代码就可能会出现下面这种情况:
String dbName = "mysql"; if(dbName.equals("mysql")){ //实例化mysql相关的类 }else if(dbName.equals("oracle")){ //实例化oracle相关的类 }
可能会有更加硬编码的写法,如下:
//在客户端代码中Driver driver = newe OracleDriver(xxx);conn = driver.getConnection(url,username,password);
那么当有一天我们接到一个需求,只能使用mysql数据库,那么这是灾难性的。因为我们需要找出代码中所有实例化Oracle相关类的地方,将其替换成mysql的相关类。而由于mysql和oracle的差别,可能要修改的东西更加多。我们想要的显然的是只需要换一个数据库类型就不用改代码了。那么我们修改一下代码改成如下:
Driver driver = DriverFactory.getDriver();conn = driver.getConnection(url,username,password);
此时,我们只需要修改getDriver方法即可了。客户端全局的代码并不需要修改,这就是解耦。也体现了解耦的好处。所以客户端代码不要和一个具体的类相关联。但是这样也有缺陷,我们虽然修改方便了,但是违背了开闭原则,怎么样才能在切换数据库的时候不修改这个工厂类呢?
很简单,将代码改成如下:
String dbName = "mysql";Driver driver = DriverFactory.getDriver("mysql");conn = driver.getConnection(url,username,password);public Driver getDriver(String dbName){ if(dbName.equals("mysql")){ //实例化mysql相关的类 return ... }else if(dbName.equals("oracle")){ //实例化oracle相关的类 return ... }}
通过传参的方式来保证我们遵循开闭原则。但是这样也有问题,因为我们这样仅仅解决了切换的问题,并没有考虑增加数据库的情况。比如说我们这时候需要添加一种数据库类型,如sql server。那么我们又得修改getDriver(xxx)方法(添加一条if语句)。这又违背了开闭原则。那么我们怎么做到不用if,switch等语句就实现分支判断呢?
这里就要用到反射了。代码如下:
public Driver getDriver(String dbName){ //dbName是类的全路径名 Driver driver = (Driver)Class.forName("dbName").newInstance(); return driver;}
这样就可以根据需要动态切换和添加数据库类型,而不用修改原有的代码。这就是反射的最大的应用之一。
这里的代码并不是合理的java代码,我只是为了讲解反射的好处而假设代码这么写。这里并没有提供反射相关的细节,仅仅是提供了一种动态编程的思路。
一个反射的demo
package com.wsy.testReflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * 测试java反射 * @author shuyweng * */public class TestReflect { private String fieldOne; private String fieldTwo; public String getFieldOne() { return fieldOne; } public void setFieldOne(String fieldOne) { this.fieldOne = fieldOne; } public String getFieldTwo() { return fieldTwo; } public void setFieldTwo(String fieldTwo) { this.fieldTwo = fieldTwo; } public TestReflect(String test){ System.out.println("测试~"); } //反射的类必须要有无参的构造方法 public TestReflect(){ System.out.println("测试~"); } //测试invoke方法~ public void test(String param){ System.out.println("反射测试:" + param); } /** * @param args * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException */ public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // InstantiationException 使用反射的时候不存在带参数 Class<?> c1 = null; Object obj = null; // 利用反射获得一个类的类 c1 = Class.forName("com.wsy.testReflect.TestReflect"); // 获取类的全限定名儿 System.out.println(c1.getName()); //获得一个类的构造方法 Constructor<?> cons[] = c1.getConstructors(); //getDeclaredField是可以获取一个类的所有字段. //getField只能获取类的public 字段. Field[] fields = c1.getDeclaredFields(); Method[] method = c1.getMethods(); for(int i = 0; i < cons.length; i++){ System.out.println("构造方法:" + cons[i].getName()); System.out.println("属性:" + fields[i].getName()); //普通方法,包含wait System.out.println("普通方法:" + method[i].getName()); } try { obj = c1.newInstance(); Method testMethod = c1.getMethod("test", String.class); //java.lang.IllegalArgumentException 不合法参数 testMethod.invoke(obj, "String"); //Field field = c1.getDeclaredField("fieldOne"); Field field = obj.getClass().getDeclaredField("fieldOne"); System.out.println("获得属性成功"); //指定私有属性可以被外部访问~ field.setAccessible(true); field.set(obj, "test"); //在通过反射获得一个对象的属性的时候可以通过field.get方法来获得其属性的值,其中get的参数支持Object System.out.println("测试属性:" + field.get(obj)); } catch (Exception e) { e.printStackTrace(); } }}
- java反射学习(结合工厂方法)
- 工厂模式(与反射方法结合)
- java 反射和 工厂模式结合使用
- 工厂方法模式--结合具体例子学习工厂方法模式
- 结合属性文件的工厂模式(java反射的应用)
- 结合属性文件的工厂模式(java反射的应用)
- Java结合反射和单例的工厂模式
- Java反射结合属性文件实现工厂模式
- Java反射生成对象注入spring(结合工厂模式)
- Java反射 配置文件 工厂方法综合实例
- Java使用反射机制优化工厂方法
- Java中工厂、配置文件和反射学习
- Java学习笔记----工厂模式和反射
- Java中工厂、配置文件和反射学习
- 结合Java反射用简单工厂模式改进抽象工厂模式
- java学习之工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
- Java 反射学习(三)成员方法的反射
- Java 反射学习(五)反射的main方法
- Linux下链表的使用及探究
- CenterOS7-minimal
- SDN 技术指南(一):架构概览
- hdu3308(线段树区间合并)
- selenium webdriver 学习总结-JUnit4 入门_补充Annotation(三)
- java反射学习(结合工厂方法)
- c冒泡排序
- selenium webdriver 学习总结-JUnit4 入门_补充枚举 (三)
- C++ explicit关键字
- jdbc增删改查的工具类
- 小工具:火车票查询
- Java多线程--对thread.join的理解
- 今后的职业规划
- 自定义View自定义标题