八、反射

1.反射?

   反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2.如何得到类对象

   <1>类名.class
   <2>对象.getClass()
   <3>Class.forName("全限定名");
   <4>类加载的loadClass("全限定名");
   <5>子类.class.getSuperClass();

   <6>包装类.class

package com.zking.test;

import org.junit.Test;

import com.zking.entity.Person;
import com.zking.entity.Son;

public class TestReflect {
	   /**
	    * 获取类对象
	    */
	   @Test
	   public void test1(){
		      try {
			      //第一种方式:实体类.class
//				  Class clazz=Person.class;
//				  System.out.println(clazz);//打印出:class com.zking.entity.Person
				  
			      //2:对象.getClass()
//				  Person per=new Person();
//				  Class clazz=per.getClass();
//				  System.out.println(clazz);//打印出:class com.zking.entity.Person
				  
			      //3:Class.forName("全限定名");
//				  Class clazz=Class.forName("com.zking.entity.Person");
//				  System.out.println(clazz);//打印出:class com.zking.entity.Person
				  
				  //4:类加载的loadClass("全限定名");
//				  ClassLoader cl=Person.class.getClassLoader();
//				  Class clazz=cl.loadClass("com.zking.entity.Person");
//				  System.out.println(clazz);//打印出:class com.zking.entity.Person
				  
				  //5:子类.class.getSuperClass();
//				  Class clazz=Son.class.getSuperclass();
//				  System.out.println(clazz);//打印出:class com.zking.entity.Person
		    	  
		    	  //6:获取包装类的类对象   包装类.class
//		    	  Class clazz=Integer.class;
//		  		  System.out.println(clazz);//打印出:class java.lang.Integer
		  		  
		      } catch (Exception e) {
				   e.printStackTrace();
			  }
	   }
 }


3.根据类得到类名(全限定名)

    c.getName()------------>全限定名
    c.getSimpleName() ---->类名

    c.getPackage()---------->包名

 /**
	    * 根据类对象  获取 类名(全限定名  包名)
	    */
	   @Test
	   public void test2(){
		      Class clazz=Person.class;
		      System.out.println(clazz.getName());//获取全限定名     打印出:com.zking.entity.Person
		      System.out.println(clazz.getSimpleName());//获取类名(不包括包名)   打印出:Person
		      System.out.println(clazz.getPackage().getName());//获取包名     打印出:com.zking.entity
	   }


4.根据类得到类的属性    

    c.getField("field属性名");
    属性名:f.getName()
    属性修饰符:f.getModifiers()
    属性的数据类型:f.getType().getName()
    给属性设值:f.set()
    得到属性的值:f.get()
    得到私有的属性:f.getDeclaredField("属性名");

    得到所有的声明的属性 c.getDeclaredFields()

 
	   /**
	    * 根据类对象 获取 类的属性
	    */
	   @Test
	   public void test3(){
		      try {
		    	    //之前
//					Person person=new Person();
//					//person.setPid(1);
//					Person person2=new Person();
//					//person2.setPid(100);
//					Class clazz=Person.class;
//					Field[] fields=clazz.getFields();//只能获取public修饰的属性
//					Field[] fields2=clazz.getDeclaredFields();//获取所有的属性(包括私有)
//					for (Field field : fields2) {
//						//获取所有属性的属性名
//						System.out.println(field.getName());
//					}
//					
//					System.out.println(fields2.length);
//					//获取单个属性(获取的public)
//					Field field=clazz.getField("pid");
//					//给属性设值
//					field.setInt(person, 100);
//					//获取属性的值
//					System.out.println(field.getInt(person));
//					
//					//获取单个属性(修饰符为private)
//					//Field fieldPname=clazz.getField("pname");
//					Field fieldPname=clazz.getDeclaredField("color");
//					System.out.println(fieldPname);
//					
//					System.out.println("psex的数据类型为:"+fieldPname.getType().getSimpleName());
//					//private 2
//					//public 1
//					//protected 4
//					//默认 0
//					//static 8
//					//final 16
//					
//					System.out.println(Modifier.isPublic(25));
//					
//					System.out.println("color的修饰符为:"+fieldPname.getModifiers());
//					
//					//设置可以访问
//					fieldPname.setAccessible(true);
//					
//					//给私有的属性设值
//					fieldPname.set(person, "admin");
//					
//					//获取私有属性的值
//					System.out.println(fieldPname.get(person));
//					
		    	  
			  } catch (Exception e) {
				  e.printStackTrace();
			  }
	   }
	

  

5.根据类得到类的方法

    c.getMethod()

    c.getDeclaredMethod();       

6.根据类得到类的构造方法

	
	/**
	 * 获取该类所有的构造方法,并执行
	 */
	@Test
	public void test5(){
		Class clazz=Person.class;
		Constructor constructor[]=clazz.getDeclaredConstructors();
		for (Constructor c : constructor) {
			System.out.println(c.getModifiers());
			Class clazzType[]=c.getParameterTypes();
			for (Class cc : clazzType) {
				System.out.println(" "+cc.getSimpleName());
			}
		}
		//调用构造方法(使用构造方法进行实例化对象)
		try {
			//clazz.newInstance();//调用无参构造
			//调用有参构造
			Constructor constru=clazz.getDeclaredConstructor(Integer.class,String.class,Integer.class);
			constru.newInstance(1,"123",2);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	
	
	/**
	 * 根据类对象 获取 类的所有的方法
	 */
	@Test
	public void test4(){
		//获取所有的方法
		Class clazz=Person.class;
		Method methods[]=clazz.getDeclaredMethods();
		System.out.println(methods.length);
		for (Method method : methods) {
			//获取每个方法的名字
			System.out.println(method.getName());
			
			//每个方法的返回值类型
			System.out.println("  "+method.getReturnType().getName());
			
			//每个方法的修饰符
			System.out.println("  "+method.getModifiers());
			
			//获取每个方法的参数列表
			Class[] classType=method.getParameterTypes();
			for (Class c : classType) {
				System.out.println("   "+c.getSimpleName());
			}
		}
		
		
		//调用方法(无参数)
		try {
			Person person=new Person();
			Method method=clazz.getDeclaredMethod("sleep", String.class,String.class);
			//设置可访问
			method.setAccessible(true);
			//执行方法
			method.invoke(person, "小飞和小明","小芳");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


7.根据类得到类的实现接口列表    

/**
	 * 获取实现该类的所有接口 及 父类
	 */
	@Test
	public void test6(){
		Class clazz=Person.class;
		System.out.println(clazz.getSuperclass().getSimpleName());
		//实现的接口
		Class clazzInterface[]=clazz.getInterfaces();
		for (Class c : clazzInterface) {
			System.out.println(c.getSimpleName());
		}
	}


例子(删除实体类后再读取实体类的class文件):

package com.zking.entity;

import java.io.Serializable;

import javax.servlet.http.HttpServlet;

/**
 * 例子:
 * <1>新建实体类Person
 * <2>三个字段:pid pname psex
 * <3>要求该类有父类,并且实现多接口
 * <4>通过反射得到改类所有的属性和方法,父类和实现接口
 * 要求:在控制台打印实体类
 */
public class Person extends HttpServlet implements Serializable,Runnable{
       private Integer pid;
       private String pname;
       private String psex;
       
       //构造方法
       public Person() {
    	  
       }
       public Person(Integer pid, String pname, String psex) {
    	   super();
    	   this.pid = pid;
    	   this.pname = pname;
    	   this.psex = psex;
       }

       //封装
       public Integer getPid() {
    	   return pid;
       }
       public void setPid(Integer pid) {
    	   this.pid = pid;
       }
       public String getPname() {
    	   return pname;
       }
       public void setPname(String pname) {
    	   this.pname = pname;
       }
       public String getPsex() {
    	   return psex;
       }
       public void setPsex(String psex) {
    	   this.psex = psex;
       }
       
       //方法
       public void run() {
    	   // TODO Auto-generated method stub
       }
       public void eat(){
    	      System.out.println("打印吃的方法");
       }
       
       
       

}
package com.zking.diy;

import java.io.FileInputStream;

public class ClassLoaderDIY extends ClassLoader{

	   @Override
		protected Class<?> findClass(String name) throws ClassNotFoundException {
			      System.out.println("自定义加载器:"+name);
		          name=name.replaceAll("\\.", "/");
		          System.out.println("替换后:"+name);
		          
		          //截取
				  int a=name.lastIndexOf("/");
				  name=name.substring(a+1);
		          
		          String path="C:\\Users\\Administrator.USER-20170515AI\\Desktop\\"+name+".class";
		          try {
					  FileInputStream fis=new FileInputStream(path);
					  System.out.println(fis.available());
					  int len=0;
					  byte[] b=new byte[fis.available()];
					  len=fis.read(b);
					  return defineClass(null, b,0,len);
				  } catch (Exception e) {
					  e.printStackTrace();
				  }
			      return null;
		}
	
}
package com.zking.test;

import org.junit.Test;

import com.zking.diy.ClassLoaderDIY;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


public class TestReflect {

	   @Test
	   public void test1() throws IOException{
		      Map<Integer, String> map=new HashMap<Integer, String>();
		      map.put(0, "\t");
			  map.put(1, "public");
			  map.put(2, "private");
			  map.put(4, "protected");
			  map.put(8, "static");
			  map.put(16, "final");
			  
			  StringBuffer sb=new StringBuffer();
			  Class clazz= null;
		      try {
				   clazz=Class.forName("com.zking.entity.Person", true, new ClassLoaderDIY());
				   sb.append("=======================================================\r\n");
		      } catch (Exception e) {
				   e.printStackTrace();
			  }
			  //拿package+(全限定名  包名);
			  sb.append("package "+clazz.getName().substring(0, clazz.getName().lastIndexOf("."))+";\r\n\r\n");
			  //拿导包(实现接口)
			  Class[] interfaces= clazz.getInterfaces();
			  for (Class cl: interfaces) {
					sb.append("import  "+cl.getName()+";\r\n\r\n");
			  }
			  //拿导包(父类)
			  sb.append("import  "+clazz.getSuperclass().getName()+";\r\n\r\n");
			  /**
			   * public class Person extends HttpServlet implements Serializable,Runnable{
			   */
			  sb.append(map.get(clazz.getModifiers())+" class "+clazz.getSimpleName());//拿public class Person 
			  sb.append(" extends "+clazz.getSuperclass().getSimpleName()+" implements ");//拿extends 父类   implements 
			  //拿实现的接口     
			  int t1=0;
			  for (Class cl : interfaces) {
					t1++;
					if(t1==interfaces.length){
						sb.append(cl.getSimpleName()+"{\r\n");
					}else{
						sb.append(cl.getSimpleName()+",");
					}
			  }
			  /**
			    * 拿属性
			    * private int pid;
				* private String pname;
				* private String psex;
				*/
				Field[] fields=clazz.getDeclaredFields();//获取所有的属性(包括私有)
				for (Field f : fields) {
					sb.append("\t");
					sb.append(map.get(f.getModifiers())+" ");
					sb.append(f.getType().getSimpleName()+" ");
					sb.append(f.getName()+";\r\n");
				}
			  
			  /**
			    *拿构造方法
			    */
				Constructor[] con=clazz.getDeclaredConstructors();
				for (Constructor c : con) {
					sb.append("\t");
					sb.append(map.get(c.getModifiers())+" ");
					sb.append(clazz.getSimpleName()+"(");
					//参数params
					Class[] params=c.getParameterTypes();
					int i=0;
					for (Class cc : params) {
						i++;
						if(i==params.length){
							sb.append(cc.getSimpleName()+" 参数"+i);
						}else{
							sb.append(cc.getSimpleName()+" 参数"+i+",");
						}
				   }
				   sb.append("){\r\n\r\n\t}\r\n");
				}
			
			  /**
				* 获取所有的方法(封装+方法)
				*/
				//拿方法
				Method[] methods=clazz.getDeclaredMethods();
				for (Method m : methods) {
					sb.append("\t");
					sb.append(map.get(m.getModifiers())+" ");
					sb.append(m.getReturnType().getSimpleName()+" ");
					sb.append(m.getName()+"(");
					//方法参数
					//获取方法的参数列表
					Class[] params=m.getParameterTypes();
					int i=0;
					for (Class c : params) {
						i++;
						if(i==params.length){
							sb.append(c.getSimpleName()+" 参数"+i);
						}else{
							sb.append(c.getSimpleName()+" 参数"+i+",");
						}
					}
					sb.append("){\r\n\r\n\t}\r\n");
				}
				sb.append("}");
			    System.out.println(sb);
				   
			   /**
			    * 写入文件   
			    */
//			    File file=new File("D:\\桌面文件\\桌面\\控制台的打印文本.txt");
			    File file=new File("YuHuiLing.java");
			    if(!file.isAbsolute()){
					file.createNewFile();
				}
			    try {
					FileOutputStream fos=new FileOutputStream(file);
					//fos.write(sb.toString().getBytes());
					//fos.close();
					OutputStreamWriter osw=new OutputStreamWriter(fos);
					osw.write(sb.toString());
					osw.close();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} 
			    
				   
				//如果WebRoot路径下面没有YuHuiLing.java文件,即按F5刷新一下
				   
		      
	   }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值