本来是想放在上一篇博文一起写的,后来某些原因,单独写了。
刚学反射,或者说刚学某些东西的时候总觉得挺难的。其实当你学完回头一看,就那么回事,你越把它当回事,越南!
贴一下项目结构,还是用了上篇博文的项目
先来两行代码,先来个接口,然后有个类实现了这个接口!
MyService.java
package com.yl.web.service;
/**
* @author YL
* @date 2019年2月28日
* @version
* @message Service接口
*/
public interface MyService {
public void init();
public void run();
public void end();
}
MyServiceImpl.java
package com.yl.web.serviceImpl;
import com.yl.web.service.MyService;
/**
* @author YL
* @date 2019年2月28日
* @version
* @message Service的实现类
*/
public class MyServiceImpl implements MyService {
/* (non-Javadoc)
* @see com.yl.web.service.MyService#init()
*/
@Override
public void init() {
// TODO Auto-generated method stub
System.out.println("服务器进行初始化啦!");
}
/* (non-Javadoc)
* @see com.yl.web.service.MyService#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("服务器进入运行啦!");
}
/* (non-Javadoc)
* @see com.yl.web.service.MyService#end()
*/
@Override
public void end() {
// TODO Auto-generated method stub
System.out.println("服务器进行结束啦!");
}
}
现在介绍一下反射是干啥的!就是在运行期,不用创建对象,能拿到某个类里的构造方法,方法,属性等。在配合着配置文件,我们可以在一个软件已经出厂,不能在用我们的eclipse等开发工具来修改代码时,来动态控制软件由运行一个类中的某个方法到循行另一个类的某个方法的手段。
简单来说,我们软件出厂了!我本来在软件中设置的是运行上边代码的run方法,我想改成运行end方法,怎么办呢?我们可以这样干,我弄一个专门运行代码的方法,给我一个类和方法,好,我运行,我通过配置文件修改了这个类和方法,现在我运行另一个方法了,好,我还能运行!我们学的通过配置文件拿到值,反射,这些东西都是为了将来能实现软件出场还能完成对软件的一些控制和修改而学的。
废话有点多了,反正学就完事了!
回到正题,先贴出Java代码,代码可以不先看,不先理解,看代码下边的解释!
/**
*
*/
package com.yl.xml.test;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import com.yl.web.serviceImpl.MyServiceImpl;
/**
* @author WangYalun
* @date 2019年2月28日
* @version
* @message 反射测试
*/
public class ReflectTest {
/**
* 测试1
*/
@Test
public void testReflect() {
// TODO Auto-generated method stub
try {
//反射需要的类至运行时
Class<?> clazz = Class.forName(getClassName());
//获取类实例
Object ms = clazz.newInstance();
//获取定义的方法
Method[] methods = clazz.getDeclaredMethods();
//遍历方法依次运行
for (Method method : methods) {
try {
//运行
method.invoke(ms, null);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public String getClassName() {
String className = null;
// 核心
SAXReader sr = new SAXReader();
try {
// 获得文档
Document read = sr.read(new File(
"src/com/yl/xml/schema/SchemaXml.xml"));
// 获得根元素
Element rootElement = read.getRootElement();
// 获得所有子元素
List<Element> elements = rootElement.elements();
// 遍历
for (Element e : elements) {
if ("servlet".equals(e.getName())) {
Element element = e.element("servlet-class");
className = element.getText();
}
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return className;
}
}
我们的Java中有一个Class的类,它有一个方法forName(String className),干啥用的?就是说你给它完整包名的字符串,它就能给转化成这个类,就是说它能变成这个类(应该可以这样理解...汗),什么叫完整包名?看我开头贴的那个图,就是包名+类名,比如:com.yl.web.serviceImpl.MyServiceImpl。
然后介绍另一个方法,newInstance()就是new 对象,然后我们就不用知道是那个类,反正不用new就得到了一个实例
后边的什么获得构造方法,获得方法,获得属性,自己去查JDK吧,上边代码的getDeclaredMethods()就是获得不包括继承的其他方法(大概就这样子....)也许你注意到了,我的forName()里是一个方法,其实就是用了我上篇博文的XML的知识。上篇博文
这差不多就是反射了,就是不用new 然后只用字符串,在运行期获得类的实例,然后操作!
收工!