Java中的反射

Java中的反射

认识反射

一、反射是什么,有什么作用?

反射---在程序运行的过程中,我们可以得到某个类的对象,可以调用某个类中的任何一个变量/方法,这种动态获取信息的过程就是反射。

当我们在没有见过某个类的情况下,仅凭一个完整的类名,就可以获取到整个类的所有信息。

反射的使用场景:

  1. jdbc加载数据库驱动
  2. Servlet的web.xml配置
  3. Spring框架

二、实例对象与反射对象的相互转换?

实例对象-----就是我们通过类创建的对象

反射对象-----通过反射机制得到的类对象

例如:

 反射就是一面镜子,镜子前面的你就是实例对象,通过镜子得到的镜子里面的你就是反射对象。

反射对象是一个Class类型的对象

Class---不是创建类的关键字,表示一个类,所以反射对象是一个Class类型的对象

public final class Class<T>

  通过实例对象得到反射对象

package com.wangxing.test1;

public class TestMain {
		public static void main(String[] args) {
			
		//得到反射对象
			//1.通过实例对象得到反射对象[getClass()]
			Student stu =new Student();
			Class stuclass=stu.getClass();
			//2.通过Class类的forname(类名【包名+类名】)
			try {
				Class stuclass2=Class.forName("com.wangxing.test1.Student");
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
}

通过反射对象得到实例对象

package com.wangxing.test1;

public class TestMain {
		public static void main(String[] args) {

		//通过反射对象得到实例对象[newInstance()]
			//Student stu=new Student();
			//stu.test1();
			try {
			Class	stuclass=Class.forName("com.wangxing.test1.Student");
				Student student=(Student) stuclass.newInstance();
					student.test1();
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			
		
		}
}

三、通过反射对象得到构造方法\成员变量\成员方法

Constructor<?>[]

getConstructors() 得到构造方法

Field[]

getDeclaredFields() 得到成员变量

Method[]

getDeclaredMethods() 得到成员方法

Class<?>[]

getInterfaces() 得到接口。

Class<? super T>

getSuperclass() 得到父类。

Package

getPackage() 得到包对象。

int

getModifiers() Java语言修饰符

Modifier的toString(int mod)

String

getName() 得到类名称

四、反射的应用

 

//Student类

package com.wangxing.test1;

public class Student extends Person implements MyTestInterface {
	private String stuname;
	private int stuage;
	public Student(){
		
	}
	public Student(String name){
		this.stuname=name;
	}
	public void test1(){
		System.out.println("Student类的实例方法");
	}
	public String testString(String args){
		return "Hello";
		
	}
	
}

 //Person类

package com.wangxing.test1;

public class Person {

}

//MyTestInterface 类

package com.wangxing.test1;

public interface MyTestInterface {

}

//反射应用,通过反射得到与Student类一样的java类

package com.wangxing.test1;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;



/**
 * 通过反射得到与Student类一样的java类
 * @author 14336
 *
 */
public class TestMain2 {
	private static String testName(String name) {
		String classname=name.substring(name.lastIndexOf(".")+1);
		return classname;
	}
	public static void main(String[] args) throws Exception {
	Class	stuclass= Class.forName("com.wangxing.test1.Student");
	//得到Student类的包名
	  String packname=stuclass.getPackage().getName();
	  String packageinfo="package "+packname+";";
	  System.out.println(packageinfo);
	//得到Student类的定义信息
	  //Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。
	  //getModifiers()返回此类或接口以整数编码的 Java 语言修饰符。修饰符由 Java 虚拟机的 public、protected、private、final、static、abstract 和 interface 对应的常量组成;它们应当通过 Modifier 类的方法来解码。 
	  String classxiushifu=Modifier.toString(stuclass.getModifiers());
	  //getName()以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
	  // 如果此类对象表示的是非数组类型的引用类型,则返回该类的二进制名称
	  //如果此类对象表示一个基本类型或 void,则返回的名字是一个与该基本类型或 void 所对应的 Java 语言关键字相同的 String
	  //如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。
	  /*
	   * 元素类型              编码  
         boolean     Z  
         byte        B  
		 char  		 C  
	             类或接口   	 Lclassname;  
		 double  	 D  
		 float  	 F  
		 int  	 	 I  
	 	 long  	 	 J  
 		 short  	 S  
	   */
	  String leiming=testName(stuclass.getName());
	  //getSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。如果此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象。
	  String supername=testName(stuclass.getSuperclass().getName());
	 //getInterfaces()确定此对象所表示的类或接口实现的接口,如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。数组中接口对象的顺序与此对象所表示的类的声明的 implements 子句中的接口名顺序一致
	  Class interfacearr[]=stuclass.getInterfaces();
	  //取出接口名称
	  StringBuilder interinfo=new StringBuilder();
	  for (Class inter : interfacearr) {
		String intername=testName(inter.getName());
		interinfo.append(intername+",");
	}
	  
	  interinfo.deleteCharAt(interinfo.length()-1);
	  String classinfo=classxiushifu+" class "+leiming+" extends "+supername+" implements "+interinfo.toString()+"{";
	  System.out.println(classinfo);
	  
//得到类中的成员变量
	  //getDeclaredFields()
	  /*返回 Field 对象的一个数组,这些对象反映此 Class 
	   * 对象所表示的类或接口所声明的所有字段,
	   * 包括公共、保护、默认(包)访问和私有字段,
	   * 但不包括继承的字段。返回数组中的元素没有排序,
	   * 也没有任何特定的顺序。如果该类或接口不声明任何字段,
	   * 或者此 Class 对象表示一个基本类型、一个数组类或 void,则
	   * 此方法返回一个长度为 0 的数组。 
	   */
	  //类中成员变量的修饰符
	  Field fieldarr[]=stuclass.getDeclaredFields();	
	  for (Field field : fieldarr) {
		  String fieldxiu=Modifier.toString(field.getModifiers());
		  /*   getType()---Field中的方法
		   * Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
		   * 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。 
			返回:标识此对象所表示字段的声明类型的 Class 对象
		   */
		  //数据类型
		  String fieldleixing=testName(field.getType().getName());
		  //名称
		  String fieldname=field.getName();
		  //
		  String fieldinfo=fieldxiu+" "+fieldleixing+" "+fieldname+";";
		  System.out.println("\t"+fieldinfo);
	  }
//得到类中的构造方法
	  //getConstructors()返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。如果该类没有公共构造方法,或者该类是一个数组类,或者该类反映一个基本类型或 void,则返回一个长度为 0 的数组。 
	  /* 
	   * Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。 
		 Constructor 允许在将实参与带有基础构造方法的形参的 newInstance() 匹配时进行扩展转换,但是如果发生收缩转换,则抛出 IllegalArgumentException
	   */
	  //通过反射获得类中的构造方法,
	     Constructor constructorarr[]=stuclass.getConstructors();
	     for (Constructor constructor : constructorarr) {
			String conxiu=Modifier.toString(constructor.getModifiers());
			String conname=testName(constructor.getName());
			//一个可变的字符序列
			StringBuilder canshu=new StringBuilder();
			//Constructor中的方法  getParameterTypes()按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。如果基础构造方法不带任何参数,则返回一个长度为 0 的数组。
			//返回:此对象表示的构造方法的参数类型
			Class conpyte[]=constructor.getParameterTypes();
			if (conpyte.length!=0) {
				for (Class typeclass : conpyte) {
					String typename=testName(typeclass.getName());
					canshu.append(typename+" name,");
				}
				canshu.deleteCharAt(canshu.length()-1);
			}
	    	 String coninfo=conxiu+" "+conname+"("+canshu.toString()+"){}";
	    	 System.out.println("\t"+coninfo);
		}
//得到实例方法
	     //getDeclaredMethods()
	     /*返回 Method 对象的一个数组,
	      * 这些对象反映此 Class 对象表示的类或接口声明的所有方法,
	      * 包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
	      * 返回数组中的元素没有排序,也没有任何特定的顺序。
	      * 如果该类或接口不声明任何方法,或者此 Class 对象表示一个基本类型、
	      * 一个数组类或 void,则此方法返回一个长度为 0 的数组。
	      * 类初始化方法 <clinit> 不包含在返回数组中。
	      * 如果该类声明带有相同参数类型的多个公共成员方法,
	      * 则它们都包含在返回的数组中。
	      * 返回:表示此类所有声明方法的 Method 对象的数组 
	      */
	     //Method
	     //Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 
	     //Method 允许在匹配要调用的实参与基础方法的形参时进行扩展转换;但如果要进行收缩转换,则会抛出 IllegalArgumentException。 
	     Method methodarr[]=stuclass.getDeclaredMethods();
	     for (Method method : methodarr) {
			String mothxiu=Modifier.toString(method.getModifiers());
			//getReturnType()返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。 
			String tereturn=testName(method.getReturnType().getName());
			//方法名
			String methname=method.getName();
			//
			StringBuilder canshu=new StringBuilder();
			//getParameterTypes() 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。如果基础方法不带参数,则返回长度为 0 的数组。 
			//返回:此对象所表示的方法的参数类型
			Class methodptype[]=method.getParameterTypes();
			if (methodptype.length!=0) {
				for (Class canshutypeclass : methodptype) {
					String typename=testName(canshutypeclass.getName());
					canshu.append(typename+" args,");
				}
				canshu.deleteCharAt(canshu.length()-1);
			}
			String methodinfo=mothxiu+" "+tereturn+" "+methname+"("+canshu.toString()+"){}";
			System.out.println("\t"+methodinfo);
	      }
	     System.out.println("}");
}
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值