Java中详述反射

如何获取Class对象

首先我们需要创建一个Student类,代码展示:

package venus;

public class Student {
	
	public String name;
	
	public Student() {
		
	}
	
	public void doHomework() {
		System.out.println(name+"正在写作业");
	}

}

创建一个Test类对象,代码如下:

package venus;

public class Test {

	public static void main(String[] args) {
		Student student = new Student();//调用构造方法
		student.name="wjq";
		student.doHomework();//调用普通方法
}

运行代码结果,此时,通过以上的方法可以看出,我们一般使用new+类名的方法创建对象。
在这里插入图片描述
什么是反射
反射是一种新的操作类中属性,构造方法和普通方法的机制(方式),两种方式等效,只是实现的过程不同。
而Class类是Java 反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。
Class类的特点
1、该类在java.lang包中;
2、该类被final所修饰,即该类不可以被子类继承;
3、该类实现了Serializable接口;
4、该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象;

反射操作类属性实现
在Test类中展现:
1、Class.forname();

		Class clazz=null;//clazz避免class关键字,
		
		try {
			clazz=Class.forName("venus.Student");
			System.out.println("1、"+clazz.getName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

2、类名.class;

		clazz=Student.class;
		System.out.println("2、"+clazz.getName());

3、对象.getClass();

		clazz=new Student().getClass();
		System.out.println("3、"+clazz.getName());

4、基本数据类型对应的class对象:包装类.TYPE

		clazz = Integer.TYPE;
		System.out.println("4、"+clazz.getName());
		clazz = Integer.class;
		System.out.println("4、"+clazz.getName());

5、数组类型对应class:元素类型[].class

		clazz = String[].class;
		System.out.println("5、"+clazz.getName());

6、某个类父类所对应的class对象

		clazz = Student.class.getSuperclass();
		System.out.println("6、"+clazz.getName());

以上代码效果展示为:
在这里插入图片描述

如何使用反射操作类属性

如何获取方法
a.public,不仅限于本类,还包括继承自父类的方法

			Method [] methods = clazz.getMethods();
			for(Method method : methods) {
				System.out.println(method.getName());
			}

结果显示为:
在这里插入图片描述

		b.本类中声明的方法
			Method [] methods = clazz.getDeclaredMethods();
			for(Method method : methods) {
				System.out.println(method.getName());
			}

结果显示为:
在这里插入图片描述
需要注意的是:这两种方法没有明显的完全包含或完全被包含关系,两者会有部分方法重叠,但是有时候不会完全包含或被包含。
获取信息
此时修改Student类中的doHomework方法:

	public static int doHomework(int a,String [] names) {
		System.out.println("正在写作业");
		return 1;
	}

Test类中代码块为:

			try {
				Method method = clazz.getMethod("doHomework", Integer.TYPE,String[].class);
				System.out.println(method.getDeclaringClass());
				System.out.println(Modifier.toString(method.getModifiers()));
				clazz = method.getReturnType();//☆
				System.out.println(clazz.getName());
				System.out.println(method.getName());
				Class [] clazzs = method.getParameterTypes();
				for(Class zz : clazzs) {
					System.out.println(zz.getName());
				}
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

结果显示为:
在这里插入图片描述
使用反射中的方法
反射中方法的调用不区分静态与非静态
代码展示为:

try {
				Method method = clazz.getMethod("doHomework", Integer.TYPE,String[].class);
				//反射中方法的调用不区分静态与非静态
				Object object = method.invoke(new Student(), 1,new String[] {});
				System.out.println(object);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

结果显示为:
在这里插入图片描述
需要注意的是:如果所调用的方法是非public的方法,则需要使用constructor.setAccessible(true);来实现突破访问权限的影响,从而成功调用类中的方法。

如何使用反射操作类中方法

获取该构造方法的信息
1、Class getDeclaringClass():返回声明Constructor对象对应构造方法的类的Class对象。
2、int getModifiers():以整数形式返回Constructor对象表示的构造函数的修饰符。
3、String getName() :以字符串形式返回Constructor对象所表示得构造方法的名称。
4、Class<?>[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组此 。如果构造方法没有参数,则数组长度为0。
注意:
getConstructors()和getConstructor(Class<?>… parameterTypes)方法均无法获取非public类中默认无参构造方法对应的Constructor对象。(参见代码1)
getDeclaredConstructors()和getDeclaredConstructor(Class<?>… parameterTypes)方法可以获取非public类中默认无参构造方法对应的Constructor对象。

Class clazz = Student.class;	
		try {
			Constructor constructor = clazz.getDeclaredConstructor(String.class);
			/*clazz = constructor.getDeclaringClass();
			System.out.println(clazz.getName());
			int mod = constructor.getModifiers();
			String result = Modifier.toString(mod);
			System.out.println(result);
			
			System.out.println(constructor.getName());
			
			Class [] clazzs = constructor.getParameterTypes();
			for(Class zz:clazzs) {
				System.out.println(zz);
			}*/
		} catch (Exception e) {
			e.printStackTrace();
		}

结果显示为:
在这里插入图片描述
使用该构造方法

Class clazz = Student.class;	
		try {
			Constructor constructor = clazz.getConstructor(String.class);
			Object object = constructor.newInstance("957");//上转型对象
			Student stu = (Student)object;
			stu.doHomework();

		} catch (Exception e) {
			e.printStackTrace();
		}

结果显示为:
在这里插入图片描述
此时如果将Student类中的方法权限改为private型,则会出现这种错误类型:
在这里插入图片描述

此时我们需要添加一段这样的代码,

			constructor.setAccessible(true);//将访问权限提升至public
			Object object = constructor.newInstance("957");//上转型对象
			Student stu = (Student)object;
			stu.doHomework();

从而实现调用private访问权限的方法。
在这里插入图片描述

如何使用反射操作类中构造方法

我们知道,构造方法是用于创建对象的,而我们使用反射这种方式也是为了创建对象,此时,如果我们如果需要调用某个类中的构造方法,我们首先需要获取这个构造方法所在类中对应的Class类中的对象。
获取的方式共四种,我们可以根据其特点分为两组:
1、Constructor[] getConstrutors():返回该Class对象表示类包含的所有public构造方法(不含继承)所对应Constructor对象数组。
2、Constructor getConstrutor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造函数(不含继承)对应的Constructor对象。
3、Constructor<?>[] getDeclaredConstructors():返回一个该Class对象表示类中声明的所有构造方法(不区分访问权限)对应的Constructor对象数组。
4、Constructor getDeclaredConstructor(Class<?>… parameterTypes):返回与该Class对象表示类中定义的形参类型相匹配的构造方法(不区分访问权限)的Constructor对象。
为了讲述方便,在Test类中添加一段代码,以此来区分不同的构造方法。

	public Student() {
		
	}
	
	public Student (String name)
	{
		this.name=name;
	}
	
	public Student(String name,Integer number ) {
		this.name=name;
		this.number=number;
	}

public级别

		Class clazz = Student.class;	
		try {
			Constructor constructor = clazz.getConstructor();
			System.out.println("1"+constructor.getName());
			constructor = clazz.getConstructor(String.class);
			System.out.println("2"+constructor.getName());
			constructor = clazz.getConstructor(String.class,Integer.class);
			System.out.println("3"+constructor.getName());
		} catch (Exception e) {
			e.printStackTrace();
		}

结果显示为:
在这里插入图片描述
由此可以看出与我们设想的一样。

不区分访问权限级别
此时我们将有参数的构造方法的访问权限改为private,

public Student() {
		
	}
	
	private Student (String name)
	{
		this.name=name;
	}
	
	private Student(String name,Integer number ) {
		this.name=name;
		this.number=number;
	}

保留以上代码,并添加一段新的代码:

//不区分访问权
		try {
			Constructor constructor = clazz.getDeclaredConstructor();
			System.out.println("1"+constructor.getName());
			constructor = clazz.getDeclaredConstructor(String.class);
			System.out.println("2"+constructor.getName());
			constructor = clazz.getDeclaredConstructor(String.class,Integer.class);
			System.out.println("3"+constructor.getName());
		} catch (Exception e) {
			e.printStackTrace();
		}

结果显示为:![在这里插入图片描述](https://img-blog.csdnimg.cn/20210130092939138.png?x-oss-
此时我们可以发现结果出现了异常,private级别的访问权限无法通过getConstructor()的方式实现获取其Class类。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值