Java反射机制(二)

前言:

对于我之前所写的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的三个参数,第一个,类加载器,第二个被代理对象的接口,第三个代理对象

最后在送大家一句话:反射反射,程序员的快乐!

谢谢大家,多多指教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值