前言:
对于我之前所写的Java反射机制(一)让我们对反射有了最初步的了解,接下来就让我用更多的实例和介绍让你更加了解反射
反射实例演示
我们照样通过我们在Java反射机制(一) 中用到的案例代码(Student.java)来实现
代码如下:
package com.dengrenli.reflect;
public class Student {
private String sid;
private String sname;
public Integer age;
public static final int i = 37;
static{
System.out.println("加载进jvm中!");
}
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
}
}
实例一:
获得完整的类名
代码如下:
package com.dengrenli.reflect1;
/**
* 获得完整的类名
* @author machenike
*
*/
public class Demo1 {
public static void main(String[] args) {
Student stu = new Student();
System.out.println("通过类本身获得对象");
Class UserClass = stu.getClass();
System.out.println("获得对象成功!\n");
System.out.println("通过类对象获得类名");
String name = UserClass.getName();
System.out.println("获得类名成功!");
System.out.println("类名为:"+name);
}
}
结果如图所示:
实例二
获得类实现的接口
代码如下:
package com.dengrenli.reflect1;
/**
* //获得类实现的接口
* @author machenike
*
*/
public class Demo2 {
public static void getInterfaces(String className) {
try {
//取得类
Class cl = Class.forName(className);
Class[] ifs = cl.getInterfaces();
for (int i = 0; i<ifs.length;i++)
{
String IName = ifs[i].getName();
System.out.println("该类实现的接口名字为:"+IName);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo2 dd=new Demo2();
dd.getInterfaces("com.dengrenli.reflect1.Student");
}
}
我们让我们的Student.java案例里的代码实现object:
如图:
结果如图所示:
案例三
获得类的构造函数
代码如下:
package com.dengrenli.reflect1;
import java.lang.reflect.Constructor;
/**
*
//获得类的构造函数
* @author machenike
*
*/
public class Demo3 {
public static void getConstructorInfo(String className) {
try {
//获得类的对象
Class cl =Class.forName(className);
System.out.println("获得类"+className+"所有的构造函数");
Constructor[] ctorlist = cl.getDeclaredConstructors();
System.out.println("遍历构造函数\n");
for(int i =0 ; i<ctorlist.length; i++)
{
Constructor con = ctorlist[i];
System.out.println("这个构造函数的名字为:"+con.getName());
System.out.println("通过构造函数获得这个类的名字为:"+con.getDeclaringClass());
}
}catch (Exception e) {
System.err.println(e);
}
}
public static void main(String[] args) {
Demo3 dd=new Demo3();
dd.getConstructorInfo("com.dengrenli.reflect1.Student");
}
}
结果如图所示:
案例四
获得父类
我们让我们的Student.java案例里的代码继承SecurityManager:
如图:
代码如下:
package com.dengrenli.reflect1;
/**
*
//获得父类
* @author machenike
*
*/
public class Demo4 {
public static String getParentClass(Student stu) {
//获得父类
Class uimc = stu.getClass().getSuperclass();
System.out.println("获得父类的名字为:"+uimc.getName());
return uimc.getName();
}
public static void searchParentClass() {
}
public static void main(String[] args) {
Demo4 dd = new Demo4();
Student stu=new Student();
System.out.println("成功获得Student的父类:"+dd.getParentClass(stu));
}
}
结果如图所示:
案例五
package com.dengrenli.reflect1;
import java.lang.reflect.Method;
/**
*
//获得类的方法
* @author machenike
*
*/
public class Demo5 {
public static void getMethods(String className) {
try {
System.out.println("开始遍历类"+className+".class");
//获得类名
Class cls = Class.forName(className);
//利用方法获得所有该类的方法
System.out.println("利用类的getDeclaredMethods获得类的所有方法");
Method[] ml = cls.getDeclaredMethods();
System.out.println("遍历获得的方法数组\n");
for (int i = 0 ;i<ml.length;i++)
{
System.out.println("开始遍历第"+(i+1)+"个方法");
Method m = ml[i];
System.out.println("开始获取方法的变量类型");
Class ptype[] = m.getParameterTypes();
for (int j=0; j<ptype.length; j++)
{
System.out.println("方法参数"+j+"类型为"+ptype[j]);
}
Class gEx[] = m.getExceptionTypes();
for (int j=0 ; j<gEx.length; j++)
{
System.out.println("异常"+j+"为"+ gEx[j]);
}
System.out.println("该方法的返回值类型为:"+m.getReturnType()+"\n");
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo5 dd=new Demo5();
dd.getMethods("com.dengrenli.reflect1.Student");
}
}
结果如图所示:
反射机制的应用实例
1.利用反射,在泛型为int的arryaList集合中存放一个String类型的对象
原理:集合中的泛型只在编译器有效,而到了运行期,泛型则会失效,
如图所示:
2、利用反射,简化编写Servlet的个数。
每当我们写一个功能时,就需要写一个对应的Servlet,导致最后Servlet有很多,自己都看不过来,所以对其进行了优化,有两种方式,下面我来一一介绍
第一种方式 每次从页面传过来一个参数,method=“xxx”; 然后编写一个Servlet,获得其参数method的值,进行判断,如果是add,则调用add方法,如果是delete,则调用delete方法,这样就可以写在一个servlet中实现所有的功能了。
第二种方式 利用反射
编写一个BaseServlet继承HttpServlet,这是一个通用的BaseServlet。需要明白servlet的生命周期
编写具体实现的方法servlet类。
MySerlvet001 extends BaseServlet
解释:需要明白servlet的生命周期,也就是service方法,因为是servlet,所以在访问的时候,会经过service方法,而子类MyServlet001中并没有,所以就到父类BaseServlet中找,发现有,然后获取参数即知道了需要调用什么方法,因为方法的编写都在子类中,所以通过反射,获取到子类中对应的方法并运行,其中需要注意的是this这个参数在BaseServlet中的用法。需要理解它。才能理解我们这个程序。
动态代理的概述和实现
动态代理:一种设计模式,其非常简单,很容易理解,你自己可以做这件事,但是觉得自己做非常麻烦或者不方便,所以就叫一个另一个人(代理)来帮你做这个事情,而你就不用管了,这就是动态代理。
在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
分三步,但是注意JDK提供的代理正能针对接口做代理,也就是下面的第二步返回的必须要是一个接口。
第一步:new出代理对象,通过实现InvacationHandler接口,然后new出代理对象来。
第二步:通过Proxy类中的静态方法newProxyInstance,来将代理对象假装成那个被代理的对象,也就是如果叫人帮我们代买火车票一样,那个代理就假装成我们自己本人
第三步:执行方法,代理成功
将代理对象中的内容进行实现:
如下所示:
注意:newProxyInstance的三个参数,第一个,类加载器,第二个被代理对象的接口,第三个代理对象
最后在送大家一句话:反射反射,程序员的快乐!
谢谢大家,多多指教!