Class.forName(String className) 实例化对象问题
2017-10-09 20:13
387 查看
在实验课上用xml配置文件实现工厂模式,其中用配置文件返回类实例时出现了一点小问题,故记之。
问题的描述:工厂方法模式日志记录器。某系统日志记录器要求支持多种日志记录方式,如文件日志记录(FileLog)、数据库日志记录(DatabaseLog)等,且用户可以根据要求动态选择日志记录方式,现使用工厂模式设计该系统。
该工厂的类图如下:
实现代码:
现需要从xml配置文件中读取具体工厂名,并返回工厂对象,这里使用java中的反射机制中的Class接口,其Class.forName(String className)方法可以返回与带有给定字符串名的类或接口相关联的Class对象,再通过Class对象的newInstance()方法创建此对象表示的类的一个新实例,即通过一个类名字符串得到类的实例。
如创建一个字符串类型的对象,其代码如下:
值得注意的是这里的String类是包java.lang的类,每个java文件都会默认引入这个包。
再看配置文件:
通过获取配置文件中预先设置的类名,再利用反射机制获取类对象。通过引入DOM和反射机制后,可以在XMLUtil中实现读取XML文件并根据存储在XML文件中的类名获取对应的对象,XMLUtil类的详细代码如下:
在实验时,结果出现了错误:
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.forName()主要功能
Class.forName(xxx.xx.xx)返回的是一个类
Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,
也就是说JVM会执行该类的静态代码段。
我们再来看api文档中提供的关于Class.forName的详细解释:
Returns the
where
For example, the following code fragment returns the runtime
A call to
Parameters:
注意黑色加粗的部分,这里的className要使用类的路径,如上述的java.lang.Thread,即包名.类名
修改后的XMLUtil.java文件,
try{
...
Class c = Class.forName("com.log."+cName); //使用类的全路径
Object obj = c.newInstance();
return obj;
}catch(
Exception e)
{
e.printStackTrace();
return null;
}
问题解决,运行结果如下:
通过解决这个问题,得出以下结论:要仔细阅读API文档提供的帮助和样例
。
问题的描述:工厂方法模式日志记录器。某系统日志记录器要求支持多种日志记录方式,如文件日志记录(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 block e.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 the
Classobject associated with the class or interface with the given string name. Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
where
currentLoaderdenotes the defining class loader of the current class.
For example, the following code fragment returns the runtime
Classdescriptor for the class named
java.lang.Thread:
Class t = Class.forName("java.lang.Thread")
A call to
forName("X")causes the class named
Xto be initialized.
Parameters:
className- the fully qualified name of the desired class.Returns: the
Classobject for the class with the specified name. Throws:
LinkageError- if the linkage fails
ExceptionInInitializerError- if the initialization provoked by this method fails
ClassNotFoundException- if the class cannot be located
注意黑色加粗的部分,这里的className要使用类的路径,如上述的java.lang.Thread,即包名.类名
修改后的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)使用哪个类加载器? 2015-01-08 20:56 2196人阅读 评论(0) 收藏 举报 分类: Java虚拟机(13) 版权
- Class.forName(String className)使用哪个类加载器?
- Class.forName(String className)解析
- Class和 forName(String className)的作用
- There is no getter for property named 'fieldName' in 'class java.lang.String'
- java解惑:Class.forName(String driverClassName)载入JDBC驱动程序的幕后。
- java中Class对象详解、类名.class, class.forName(), getClass()区别
- Class.forName问题
- 关于Class.forName(className).newInstance()介绍
- 关于myBatis的问题There is no getter for property named 'USER_NAME' in 'class com.bky.model.实例类'
- java.io.InvalidClassException: <className>; incompatible types for field <fieldName> 异常追踪
- 关于Mybatis "There is no getter for property named 'XXX' in class java.lang.String"的问题
- 关于There is no getter for property named 'mohuname' in 'class java.lang.String'] with root cause问题
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- java中Class对象详解和类名.class, class.forName(), getClass()区别
- Java中Class对象详解、类名.class、class.forName()、 getClass()区别
- Class.forName().newInstance()和通过new得到对象的区别
- Could not resolve placeholder 'driverClassName' in string value "${driverClassName}"
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
- Class.forName(String driverClassName)加载JDBC驱动程序时,底层都做了些什么???