java语言基础入门——反射机制实例

1、什么是反射呢?反射可以理解为在程序运行时获取对象类型信息的操作。它允许动态的发现和绑定类、方法、字段,甚至由其他语言产生的元素。运用反射可以做到列举对象所对应的类的详细信息,如访问修饰符,包名,类名,继承的父类和接口信息,以及类内部的所有成员变量,构造函数,成员函数,函数的修饰符,返回值,参数等信息,甚至还可以利用反射来创建对象,访问成员变量和函数。可以这么说,反射窥探到类的所有信息。

2、反射所需的类。反射很强大,但它用到的类并不多,主要有java.lang.Class类和java.lang.reflect包中的Field、Constructor、Method、Array类。

Class类:Class类的实例是表示正在运行的Java应用程序中的类和接口。可以这么理解,一个普通类是Class类的一个对象。

Filed类:提供有关接口或类的属性信息,以及对他的访问权限修饰符。反射的字段可能是一个类或接口的属性或实例属性。也就是说Filed用来反射类中的成员变量信息。

Constructor类:提供类的单个构造方法的信息以及对他的访问权限修饰符。也就是说Constructor用来反射类中的构造方法的信息。

Method类:提供关于类或接口上单独某个方法的信息,包括抽象方法,可以得到方法的访问修饰符,返回值类型,参数类型等信息。也就是说method类用来反射类的除构造方法以外的方法信息。

Array类:提供了动态创建数组和访问的数组的静态方法。该类的所有方法都为静态方法。

下面是反射操作的例子,包括了得到类的信息,成员变量,构造方法,成员方法;创建对象,调用方法,得到成员变量的值的操作。

package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import product.Producter;

class Book{
	private int id;
	protected String name;
	public double price;
	String type;
	public Book() {
		this(10001,"新华字典",30.3,"工具书");
	}
	public Book(int id,String name,double price,String type){
		this.id=id;
		this.name=name;
		this.price=price;
		this.type=type;
	}
	private  Book(int id) {
		this(10001,"新华字典",30.3,"工具书");
		this.setId(id);
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	private void setAll(int id,String name,double price,String type) {
		this.setId(id);
		this.setName(name);
		this.setPrice(price);
		this.setType(type);
	}
	public String toString(){
		return "书名为:"+name+" 编码为:"+id+" 类型为:"+type+" 价格为:"+price;
	}
}
public class ClassDemo {

	/**
	 * 三种方式可以获得Class对象的方式
	 */
	public static void getClassObject() {
		//调用Object类的getClass()方法类获得Class对象,这是最常用的获得Class对象的方法
		Book book1=new Book();
		System.out.println(book1.getClass());	//显示形式:class 包名.类名
		
		//使用Class类的forName()静态方法获得与字符串参数相对应的Class对象
		try {
			//Class class1=Class.forName("java.lang.String");
			Class class1=Class.forName("reflection.Book");
			//字符串必须是类或接口的全限定名,所以带上包名
			System.out.println(class1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		//使用类型名.class获取该类型对应的Class对象
		Class class2=Double[].class;
		System.out.println(class2);
	}
	
	
	/**
	 * 获取Class对象的类型信息
	 */
	public static void getClassInformation(){
		Book book2=null;
		book2=new Book(321, "笑傲江湖", 44.5, "武侠");
		Class class4=book2.getClass();//获取class对象
		String packageName = class4.getPackage().getName();//获取类的包名
		System.out.println("包名为:"+packageName);
		String mod =Modifier.toString(class4.getModifiers());//获取类的修饰符
		//.getModifiers()返回的是个整数,调用Modifier的toString方法来转化为String类型
		System.out.println("类的修饰符为:"+mod);
		String className=class4.getName();//获取全限定名(数组类型会产生奇怪字符)
		System.out.println("类的全限定名称为:"+className);
		Class superClass = class4.getSuperclass();//获取父类
		System.out.println("父类为:"+superClass);
		Class[] interfaces=class4.getInterfaces();//获取接口
		System.out.println("接口为:"+interfaces);
		
	}
	
	
	/**
	 * 获取Class对象的类的成员变量的信息
	 */
	public static void getClassmember(){
		Book book2=null;
		book2=new Book(321, "笑傲江湖", 44.5, "武侠");
		Class class4=book2.getClass();//获取class对象
		Field [] fields=class4.getDeclaredFields();//获取所有成员变量
		Field []fields2=class4.getFields();//获取public修饰的成员变量
		System.out.println("所有成员变量为:");
		for(Field ff: fields){
			String moString=Modifier.toString(ff.getModifiers());//修饰符
			Class classType=ff.getType();//数据类型
			String name=ff.getName();//字段名
			if (classType.isArray()) {//如果是数组类型需要特别处理一下
				String arrType=classType.getComponentType().getName()+"[]";
				System.out.println(moString+"修饰的"+arrType+"类型的"+name);
			}else {
				System.out.println(moString+"修饰的"+classType+"类型的"+name);
			}
		}
		System.out.println("其中用public修饰的有:");
		for (Field ff:fields2) {
			System.out.println(ff.getName());
			
		}
	}
	
	/**
	 * 获取Class对象的类的构造方法的信息
	 */
	public static void getClassConstructor(){
		Book book2=null;
		book2=new Book(321, "笑傲江湖", 44.5, "武侠");
		Class class4=book2.getClass();//获取class对象
		Constructor[] constructors=class4.getConstructors();//获取该Class对象使用所有public修饰的构造方法
		Constructor[] constructors2=class4.getDeclaredConstructors();//获取该class对象所对应类的所有构造方法
		System.out.println("class4所属类的构造方法的信息为:");
		for (Constructor cc: constructors2) {
			String name=cc.getName();//获取构造方法名称
			String modifier =Modifier.toString(cc.getModifiers());//获取访问修饰符
			System.out.print(name+"  "+modifier+" (");
			Class [] paramTypes=cc.getParameterTypes();//得到方法的参数列表
			for (int i = 0; i < paramTypes.length; i++) {
				if (i>0) {
					System.out.print(",");
				}
				if (paramTypes[i].isArray()) {//参数类型为数组时
					System.out.print(paramTypes[i].getComponentType().getName()+"[]");
					//getComponentType()为数组时返回数组的类型,不为数组返回空
				}else {
					System.out.print(paramTypes[i].getName());
				}
				
			}
			System.out.println(")");
		}
		
	}
	
	
	/**
	 * 获取类的成员方法的信息
	 */
	public static void getClassmethod(){
		Book book2=null;
		book2=new Book(321, "笑傲江湖", 44.5, "武侠");
		Class class4=book2.getClass();//获取class对象
		System.out.println("class4对象实例的所属类的成员方法信息为:");
		Method[] methods1=class4.getMethods();
		//获取Class对象实例对应的类的所有用public修饰的成员方法
		Method[] methods=class4.getDeclaredMethods();
		//获取Class对象实例的类的所有成员方法
		for (Method mm:methods1) {
			String modifier=Modifier.toString(mm.getModifiers());//访问修饰符
			Class returnType=mm.getReturnType();//返回类型
			if (returnType.isArray()) {//如果是数组类型需要特别处理
				String arrType=	returnType.getComponentType().getName()+"[]";
				System.out.print(" "+ modifier+ " "+arrType+"  "+mm.getName()+" (");
			}else {
				System.out.print(" "+ modifier+ " "+returnType+"  "+mm.getName()+" (");
			}
			Class [] paramTypes=mm.getParameterTypes();//得到方法的参数列表
			for (int i = 0; i < paramTypes.length; i++) {
				if (i>0) {
					System.out.print(",");
				}
				if (paramTypes[i].isArray()) {//参数类型为数组时
					System.out.print(paramTypes[i].getComponentType().getName()+"[]");
					//getComponentType()为数组时返回数组的类型,不为数组返回空
				}else {
					System.out.print(paramTypes[i].getName());
				}
				
			}
			System.out.println(")");	
		}
		
	}
	
	
	/**
	 * 通过反射来创建类的对象—-通过无参数的构造方法
	 * @param args
	 */
	public static Object createNoneParameterObject(String className){
		Object object=null;
		try {
			//加载指定名称的类,获取对应的Class对象,然后调用无参数的构造方法创造一个对象
			object=Class.forName(className).newInstance();
			
		} catch (InstantiationException | IllegalAccessException
				| ClassNotFoundException e) {
			e.printStackTrace();
		}
		return object;
	}
	
	/**
	 * 通过反射来创建类的对象—-通过有参数的构造方法
	 * 第一步:获取指定类对应的Class对象
	 * 第二步:通过Class对象获取满足指定参数类型要求的构造方法类对象
	 * 第三步:调用指定Constructor对象类型的newInstance方法,传入对应的参数值,创建呢对象
	 * @param args
	 */
	public static Object createHaveParameterObject(String className) {
		Object object=null;
		Class class1;
		try {
			class1 = Class.forName(className);
			Constructor constructor=class1.getConstructor(
				int.class,java.lang.String.class,double.class,java.lang.String.class);
			 object=constructor.newInstance(100,"三国演义",33.2,"历史");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return object;
	}
	
	/**
	 * 使用反射来调用方法
	 * 使用反射可以取得指定类的指定方法的对象代表
	 * 方法的对象代表就是前面介绍的java.lang.reflect.Method类的实例,
	 * 通过Method类的invode方法可以动态的调用这个方法
	 * @param args
	 */
	public static void callMethods(String classNmae) {
		try {
			Class class1=Class.forName(classNmae);
			Book book=(Book)class1.newInstance();//利用无参构造方法创建一个Book对象
			//获取名为setName,带一个String的成员方法所对应的对象代表
			Method method1=class1.getDeclaredMethod("setName",String.class);
			//在book对象上调用setName,并传值给它,返回值为空
			Object returnType=method1.invoke(book, "西游记");
			System.out.println("通过反射访问setName函数,其返回值为:"+returnType);
			//获取名为toString不带参数的成员方法对应的参数列表
			Method method2=class1.getDeclaredMethod("toString");
			method2.setAccessible(true);//取消访问检查
			//在book对象上调用toString方法
			String string=(String) method2.invoke(book);
			System.out.println(string);
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 通过反射访问成员变量的值
	 * 通过反射可以取得类的成员变量的对象代表,成员变量的对象代表是java.lang.reflect.Field类的实例
	 * 可以使用它的get和set方法来对成员变量获取或设置它的值
	 * @param args
	 */
	public static void getmember(String className) {
		
		try {
			Class class1 = Class.forName(className);
			Book book=(Book)class1.newInstance();//使用无参构造方法创建对象
			//调取私有属性id
			Field idfield=class1.getDeclaredField("id");
			idfield.setAccessible(true);//取消对本字段的访问检查
			idfield.setInt(book, 202);
			//将book对象的IDfield成员变量设置为202
			System.out.println("设置后的Id为:"+idfield.getInt(book));
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
	}
	public static void main(String[] args) {
		ClassDemo.getClassObject();//三种方式可以获得Class对象的方式
		ClassDemo.getClassInformation();//获取Class对象的类型信息
		ClassDemo.getClassmember();//获取Class对象的类的成员变量的信息
		ClassDemo.getClassConstructor();//获取Class对象的类的构造方法的信息
		ClassDemo.getClassmethod();//获取类的成员方法的信息	
		//通过反射来创建类的对象—-通过无参数的构造方法
		Book book=(Book)ClassDemo.createNoneParameterObject("reflection.Book");//带上包名
		System.out.println("通过反射创建类的对象(无参构造方法)为:"+"\n"+book.toString());
		//通过反射来创建类的对象—-通过有参数的构造方法
		Book book2=(Book)ClassDemo.createHaveParameterObject("reflection.Book");//带上包名
		System.out.println("通过反射创建类的对象(有参构造方法)为:"+"\n"+book2.toString());
		ClassDemo.callMethods("reflection.Book");//通过Method类的invode方法可以动态的调用这个方法
		ClassDemo.getmember("reflection.Book");//通过反射访问成员变量的值
	}

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值