Class.forName(String className) 实例化对象问题
来源:互联网 发布:js跳转微信打开链接 编辑:程序博客网 时间:2024/06/03 17:06
在实验课上用xml配置文件实现工厂模式,其中用配置文件返回类实例时出现了一点小问题,故记之。
问题的描述:工厂方法模式日志记录器。某系统日志记录器要求支持多种日志记录方式,如文件日志记录(FileLog)、数据库日志记录(DatabaseLog)等,且用户可以根据要求动态选择日志记录方式,现使用工厂模式设计该系统。
该工厂的类图如下:
实现代码:
package com.log;//产品interface Log {public void writeLog();}class DataBaseLog implements Log {public void writeLog() {System.out.println("写入数据库");}}class FileLog implements Log {public void writeLog() {System.out.println("写入文件");}}//工厂interface LogFactory {public Log createLog();}class FileLogFactory implements LogFactory {public Log createLog(){return new FileLog();}}class DataBaseLogFactory implements LogFactory {public Log createLog(){return new DataBaseLog();}}public class Client{public static void main(String[] args) {//创建工厂LogFactory lgfactory = new DataBaseLogFactory();//创建日志产品Log lg = lgfactory.createLog();//调用写日志方法lg.writeLog();}}
现需要从xml配置文件中读取具体工厂名,并返回工厂对象,这里使用java中的反射机制中的Class接口,其Class.forName(String className)方法可以返回与带有给定字符串名的类或接口相关联的Class对象,再通过Class对象的newInstance()方法创建此对象表示的类的一个新实例,即通过一个类名字符串得到类的实例。
如创建一个字符串类型的对象,其代码如下:
Class c = Class.forName("String");Object obj = c.newInstance();return obj;
值得注意的是这里的String类是包java.lang的类,每个java文件都会默认引入这个包。
再看配置文件:
<?xml version="1.0" encoding="UTF-8"?><config><className>DataBaseLogFactory</className></config>很简单,就是放置一个具体工厂类名。
通过获取配置文件中预先设置的类名,再利用反射机制获取类对象。通过引入DOM和反射机制后,可以在XMLUtil中实现读取XML文件并根据存储在XML文件中的类名获取对应的对象,XMLUtil类的详细代码如下:
package com.log;import javax.xml.parsers.*;import org.w3c.dom.*;import org.xml.sax.*;import java.io.*;public class XMLUtil {@SuppressWarnings("unchecked")public static Object getBean(){try{//创建DOM文档对象DocumentBuilderFactory dFactory= DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc = builder.parse(new File("D:\\Junior\\DesignPartern\\Log\\src\\com\\log\\config.xml"));//注意这里使用配置文件的绝对路径 //获取包含结点类名的文本结点NodeList nl = doc.getElementsByTagName("className");Node classNode = nl.item(0).getFirstChild();String cName = classNode.getNodeValue();//System.out.println(cName);//通过类名生成实例对象并将其返回Class c = Class.forName(cName);Object obj = c.newInstance();return obj;} catch(Exception e){e.printStackTrace();return null;}}}将主测试类代码改为:
public class Client{public static void main(String[] args) {try {//创建工厂LogFactory lgfactory = (LogFactory)XMLUtil.getBean();//创建日志产品Log lg = lgfactory.createLog();//调用写日志方法lg.writeLog();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
在实验时,结果出现了错误:
java.io.FileNotFoundException: D:\Junior\DesignPartern\Log\config.xml (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
at sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source)
后来经逐步测试发现错误出现在XMLUtil.java文件中的
Class c = Class.forName(cName);
这里从配置文件获取的类名只是一个类名字符串,
Class.forName()主要功能
Class.forName(xxx.xx.xx)返回的是一个类
Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,
也就是说JVM会执行该类的静态代码段。
我们再来看api文档中提供的关于Class.forName的详细解释:
forName
public static Class<?> forName(String className) throws ClassNotFoundException
Returns theClass
object associated with the class or interface with the given string name. Invoking this method is equivalent to:
whereClass.forName(className, true, currentLoader)
currentLoader
denotes the defining class loader of the current class.For example, the following code fragment returns the runtime
Class
descriptor for the class namedjava.lang.Thread
:Class t = Class.forName("java.lang.Thread")
A call to
forName("X")
causes the class namedX
to be initialized.- Parameters:
className
- the fully qualified name of the desired class.- Returns:
- the
Class
object for the class with the specified name. - Throws:
LinkageError
- if the linkage failsExceptionInInitializerError
- if the initialization provoked by this method failsClassNotFoundException
- if the class cannot be located
修改后的XMLUtil.java文件,
try{...Class c = Class.forName("com.log."+cName);//使用类的全路径Object obj = c.newInstance();return obj;}catch(Exception e){e.printStackTrace();return null;}
通过解决这个问题,得出以下结论:要仔细阅读API文档提供的帮助和样例。
- Class.forName(String className) 实例化对象问题
- Class.forName(String className)使用哪个类加载器?
- 关于Class.forName(className).newInstance()的理解
- 关于Class.forName(className).newInstance()介绍
- 关于Class.forName(className).newInstance()介绍
- 关于Class.forName(className).newInstance()介绍
- 关于Class.forName(className).newInstance()介绍
- Class.forName与new创建对象实例的区别
- JAVA反射机制,get.method()/ Class.forName(className)
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- 十图详解tensorflow数据读取机制(附代码)
- C++一本通题库1024
- POJ-3461-Oulipo
- 什么是进程?什么是线程?进程与线程有何区别?
- C++一本通题库1025
- Class.forName(String className) 实例化对象问题
- 045 中值定理总结(罗尔定理,拉格朗日定理,柯西定理,泰勒公式)及型一二三四五
- 霍夫曼编码
- 数据结构之顺序队列(循环队列)
- POJ1724 ROADS 解题报告【最短路/SPFA】
- bzoj 3033: 太鼓达人 欧拉图+dfs
- 3秒显示下一条及json数组解析
- Currency Exchange POJ
- 网页自动刷新