Java反射的基本概念

反射的概述

        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

获取Class对象的三种方式

1.Object ——> getClass();
2.任何数据类型(包括基本数据类型)都有一个“静态”的class属性
3. 通过Class类的静态方法:forName(String  className)(常用)

    //方式一:通过类名.class
	Class class1=String.class;
	//方式二:对象.getClass()
	String str=new String();
	Class class2=str.getClass();
	//方式三:Class的静态方法forName()
	Class class3=Class.forName("java.lang.String");

三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。

Class对象的基本使用

要进行反射操作必须要拿到这个类对应的Class对象。要用某个类的无参构造方法创建该对象时,可以省略创建Constructor类对象的过程(java运行环境的缓存中保存了类的无参构造方法所对应的Constructor对象),以我们自定义的Student对象为例:

public class Student {
public String name;
public int age;
private String id;
 String school;
  public Student() {

}
private Student(String name) {
	this.name=name;
}
 public Student(String name, int age, String id, String school) {
	this.name = name;
	this.age = age;
	this.id = id;
	this.school = school;
}


private void play(){
	System.out.println("游戏中+++++");
}
 public void study() {
	 System.out.println("正在学习+++++");
 }
public void eat() {
	System.out.println("正在吃饭+++++");
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}
public String getId() {
	return id;
}
public void setId(String id) {
	this.id = id;
}
public String getSchool() {
	return school;
}
public void setSchool(String school) {
	this.school = school;
}
@Override
public String toString() {
	return "Student [name=" + name + ", age=" + age + ", id=" + id + ", school=" + school + "]";
}

 
}

 我们可以直接使用class对象的newInstance方法通过无参构造方法来创建对象

    //获取Date的Class对象
    Class cla=Class.forName("demo.Student");
    //通过反射创建实例
	Student student=(Student) cla.newInstance();

1.获取Constructor对象

        一个类中往往会有多个构造方法,如果我们要调用有参构造来利用反射来创建实例对象,我们可以使用Class对象的Constructor数组,通过遍历数组来查看Student的所有公开的构造方法。

    //获取Student的Class对象
	Class cla=Class.forName("demo06.Student");
	//调用Class对象的getConstructors方法获取到Constructor[] 
	Constructor[] constructors=cla.getConstructors();
	//遍历构造器数组对象,查看Student对象拥有的public构造方法
	for(Constructor constructor:constructors) {
		//打印constructor
		System.out.println(constructor);
	}

        我们可以看到,在Student中,还有一个private修饰的构造方法,我们可以使用Class对象的getDeclaredConstructors来获取所有定义的构造方法。

    //获取Student的Class对象
	Class cla=Class.forName("demo06.Student");
	//调用Class对象的getConstructors方法获取到Constructor[] 
	Constructor[] constructors=cla.getDeclaredConstructors();
	//遍历构造器数组对象,查看Student对象所有定义的构造方法
	for(Constructor constructor:constructors) {
		//打印constructor
		System.out.println(constructor);
	}

获取到所有的构造方法后,我们便可以选用自己所需要的构造方法来获取实例对象 

    //获取Student的Class对象
	Class cla=Class.forName("demo06.Student");
	//根据传入参数类型获取到指定构造器
	//cla.getConstructor()为获取到指定的public的构造器
	//cla.getDeclaredConstructor()为获取到指定的定义构造器
	Constructor constructor=cla.getDeclaredConstructor(String.class);
	//判断构造器是否为受保护的
	if(!constructor.isAccessible()) {
		//设置构造器为可访问的
		constructor.setAccessible(true);
	}
	//调用constructor.newInstance()传入参数生成Student对象
	Student student=(Student) constructor.newInstance("张三");
	//打印对象
	System.out.println(student);

代码的输出结果为:Student [name=张三, age=0, id=null, school=null]

由此可知我们成功地调用了受保护的构造方法创建了Student对象。

2.Field

Field类用来表示类中的字段:

Class.getFields()得到Class对象的所有字段返回的是Field数组

Class.getField(String name)返回一个Field对象Field对象对应的是某一个类的属性

要想得到某一个对象对应的属性值,需要用get(Object object)方法

对于非公有属性,只能通过Class的getDeclaredField(String fieldName)方法的到

对于私有属性要得到它所关联的对象的值

需要通过Field的setAccessible(boolean boolean)方法设置

Field类的getType()方法用来得到字段所属的类型

    //获取Student的Class对象
	Class cla=Class.forName("demo06.Student");
	//获取Studen类的所有定义属性
	//cla.getFields()获取Student类的所有public属性
    //cla.getName()获取指定名称的属性
	Field[] fields=cla.getDeclaredFields();
	//对获取到的Field数组进行遍历
	for(Field field:fields) {
		//获取属性名称
		System.out.println("属性名:"+field.getName());
		//获取属性类型
		System.out.println("类型:"+field.getType());
		
	}

3.Method

Method getMethod(String name,Class<?>…parameterTypes)

按名称得到某个特定的public方法(包括从父类或接口继承的方法)

Method[] getMethods()

得到public方法(包括从父类或接口继承的方法)

Method[] getDeclaredMethods()

得到所有的方法(不包括继承的方法)

Method getDeclaredMethod(String name,Class<?>…parameterTypes)

按名称得到某个特定的方法(不包括继承的方法)

得到某个方法的对应Method对象,可以对其执行的方法:

Invoke(Object object, Object…obj)

用来调用Method所表示的方法。第一个参数表示该方法作用于哪个对象。(若调用的为静态方法,invoke()方法中第一个参数用null表示)

    //获取Student的Class对象
	Class cla=Class.forName("demo06.Student");
	//a.getDeclaredMethods()获取Student类的所有定方法
	//cla.getMethods()获取Student类的所有public方法
	//cla.getMethod(name, parameterTypes)根据名称和参数类型获取指定方法
	Method[] methods=cla.getDeclaredMethods();
	for(Method method:methods) {
		//获取方法名
		System.out.println("方法名:"+method.getName());
		//返回值为arameter数值
		System.out.println("参数:"+method.getParameters());
		//获取方法返回值
		System.out.println("返回值类型:" +method.getReturnType());
	}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

‏猿究院Sublate

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值