黑马程序员——反射机制

------- android培训java培训、期待与您交流! ----------

 

Class(反射的基石)

Java中的类是用来描述同一类事物的,比如, Person,Animal等等,java中的类也同属于一类事物,对于这些类就用Class类来描述, Class对象又称作字节码对象,数组和void也是数据类型

 

得到一个类的Class对象又三种方式

1.      类名.class;                例如: Class cla= Date.class;

2.      类对象的引用.getClass()         ;       例如: Date date = newDate(); Class cla = date.getClass();

3.      Class.forName(包名.类名);    例如Class.forName(Java.util.Date);

 

Java中预定义了9Class实例对象

1.      分别是8个基本数据类型和void,它们也可以用类型.class获得相应的Class对象

2.      基本数据类型的包装类可以通过包装类.Type获得对应基本数据类型的Class对象,例如 int.class == Integer.Class 返回的是true

3.      public boolean isPrimitive()判断是否为基本数据类型的字节码文件对象

 

数组类型的Class实例对象

public boolean isArray() 判断是否为数组类型的字节码文件对象

 

代码示例

package com.itcast.reflect;

public class ClassTest {
	public static void main(String[] args) throws Exception {
		// 得到Class对象的三种方式
		String str = "1234";
		Class cls1 = Class.forName("java.lang.String"); // 这里需要抛出异常
		Class cls2 = String.class;
		Class cls3 = str.getClass();

		// 比较这三个Class对象是否为同一个, 返回的都是true
		System.out.println(cls1 == cls2);
		System.out.println(cls1 == cls3);

		// 判断cls1是否为基本数据类型的Class对象, 返回false
		System.out.println(cls1.isPrimitive());

		// 判断int.class是否为基本数据类型的Class对象, 返回true
		System.out.println(int.class.isPrimitive());

		// 判断Integer.Type是否与int.class是同一对象, 返回true
		System.out.println(Integer.TYPE == int.class);

		// 判断int[]是否为数组类型的Class对象, 返回true
		System.out.println(int[].class.isArray());
	}
}


 

反射

反射是将Java类中的各个组成成分映射成相应的类,例如类可以用Class类来表示,那么类中的属性, 方法,构造方法, 修饰符,包等信息也可以用一个类来表示, 相对应的分别是Filed, Method, Constructor, Package等等,这些类需要通过Class类中的方法获得

 

Constructor

通过Class类中的getConstructors可以获得一个构造方法的数组Constructors[],如果想获得其中一个构造方法可以用Class类中的getConstructor(Class… paras),这个方法接收一个可变参数, 可以根据数据类型的Class对象获得相应的构造方法

 

Constructor对象后,可以通过Constructor中的newInstance(Object…objs)方法构建一个使用该构造方法创建的实例对象.

 

通过Class类中newInstance()方法也可以获得该Class对象的类的实例,是通过无参构造方法获得的, 一般不建议使用这个方法

 

代码示例

package com.itcast.reflect;

import java.lang.reflect.Constructor;
import java.util.Date;

public class ConstructorTest {
	public static void main(String[] args) throws Exception {
		// 得到String类的Class对象
		Class clazz1 = String.class;
		// 得到指定的String对象中的某个构造方法的Constructor对象, 这里是String(StringBuffer sbuff)
		Constructor cons = clazz1.getConstructor(StringBuffer.class); // 这里需要抛出异常
		// 通过Constructor对象构建一个String的对象
		String str = (String) cons.newInstance(new StringBuffer("abc"));
		System.out.println(str);

		// 利用Class中的newInstance()方法调用String的无参构造方法构建一个Date对象
		Class clazz2 = Date.class;
		Date date = (Date) clazz2.newInstance();
		System.out.println(date);
	}
}


 

Filed

Filed类对象表示的是类中的属性,可以通过Class类中的,getFields()getDeclaredFileds()获得类中所有的属性,返回Filed[], 如果想要获得某个指定的属性,需要用getFiled(“属性名”),或者getDeclaredFiled(“属性名”)获得.

 

Field类中的getFiled()只能获得显示的属性Field对象,不能获得私有的属性Field对象,getDeclareFile()可以获得声明的属性对象,但是不能直接对属性内容进行修改, 需要通过Filed类中的setAccessAble(true)来更改访问权限来修改属性的值, getFields()getDeclareFields()也是一样

 

要想通过Filed的对象获取属性值,需要使用Field中的get(类对象)来获取,要设置属性的值, 需要通过set(类对象, newValue)来重新设置

 

代码示例

package com.itcast.reflect;

import java.lang.reflect.Field;

public class FiledTest {
	public static void main(String[] args) throws Exception {
		// 获得Person的Class对象
		Class cls = Person.class;

		// 获得Person的对象
		Object obj = cls.getConstructor().newInstance();

		// 获取所有的Field对象
		Field[] fields = cls.getDeclaredFields();

		// 遍历获取每个属性的Field对象
		for (Field field : fields) {
			// 将所有field权限设置为可操作的
			field.setAccessible(true);
			// 获取属性原来的值
			String oldValue = (String) field.get(obj); // 这里会抛出异常
			// 将原来的值中的字符'b'全部替换成'a'
			String newValue = oldValue.replace('b', 'a');
			// 将原来的属性值设置为新的值
			field.set(obj, newValue);
		}

		// 打印Person对象的toString()
		System.out.println(obj);
	}
}

class Person {
	private String str1 = "abcb";
	private String str2 = "basketball";
	private String str3 = "hello";

	public Person() {

	}

	@Override
	public String toString() {
		return str1 + ":" + str2 + ":" + str3;
	}
}


 

Method

Method类对象表示的是类中的方法,可以通过Class类中的getMethods()getDeclaredMethods()获得全部的方法,返回Method[],如果要获取某个方法, 需要用Class类中的getDeclaredMethod(“方法名”,参数类型.class…),或者getDeclaredMehod(“方法名”, 参数类型.class…),Filed一样, getDeclaredMethod()getMethod()可以得到声明的方法,要使用限制的方法需要使用setAccessable(true)来设置

 

Method类中提供了invoke(对象,参数…)来调用某个对象的方法,前提是先获取到相对应的Method对象,如果调用的是静态方法, 那么对象的位置写成null也可以

 

如果要被调用的方法需要接收一个数组类型的数据,例如 Method method = clazz.getMethod(“main”, String[].class),那么使用invoke方法的时候需要将传入的数组参数转换为Object,因为Java语法为了兼容jdk1.5之前的语法,会将数组内的内容先拆开, 视为多个参数传入方法,数组也是Object对象,因此, 将数组转换为Object就不会出现错误,或者还有一种方式是将要传入的数组作为Object[]的第一个参数,Object[]传入也可以

 

代码示例

package com.itcast.reflect;

import java.lang.reflect.Method;

public class MethodTest {
	public static void main(String[] args) throws Exception {
		// 获得Test类的Class对象
		Class cls = Test.class;
		// 获得Test类中的main方法的Method对象
		Method mth = cls.getMethod("main", String[].class);
		// 调用main方法, 因为是静态的方法, 所以对象出入null即可, 将传入的数组参数转换为Object
		mth.invoke(null, (Object) new String[] { "张三", "李四", "王五" });
	}
}

class Test {
	// 直接这行这个主方法就会爆出数组下标越界异常
	public static void main(String[] args) {
		System.out.println(args[0] + ":" + args[1] + ":" + args[2]);
	}
}


 

数组的反射

数组也是Object类的子类,一个一位数组就可以表示为一个Object, 多维数组同样也是Object,比较两个数组的Class对象是否相等,比较的是数组的数据类型和纬度, 如果是相同类型,并且纬度相同的两个数组, 那么它们的Class对象时同一个

 

Array类是用来操作数组的反射的,可以通过Array.getLenth(“数组对象”)来获取数组的长度,通过Array.get(“数组对象”, “数组下标”)来获取数组的元素,数组的数据类型是获取不到的,但是可以获取到数组元素的类型,使用getClass().getName()获得

 

代码示例

package com.itcast.reflect;

import java.lang.reflect.Array;

public class ArrayTest {
	public static void main(String[] args) {
		// 定义4个数组
		int[] arr1 = new int[] { 1, 2, 3 };
		int[] arr2 = new int[5];
		int[][] arr3 = new int[2][3];
		String[] arr4 = new String[3];

		// 分别比较每个数组的Class对象, 第一个结果为true, 其余都false
		System.out.println(arr1.getClass() == arr2.getClass());

		// 两个不同维度和不同类型的数组比较会编译错误
		// System.out.println(arr1.getClass()== arr3.getClass());
		// System.out.println(arr1.getClass() == arr4.getClass());

		// 先得到每个数组的Class对象, 再进行比较
		Class a1 = arr1.getClass();
		Class a3 = arr3.getClass();
		Class a4 = arr4.getClass();
		System.out.println(a1 == a3);
		System.out.println(a1 == a4);

		// 调用反射打印数组方法, 打印结果 1 2 3
		printArr(arr1);
	}

	// 遍历数组, 利用反射打印数组元素
	public static void printArr(Object obj) {
		// 得到参数的Class对象
		Class clazz = obj.getClass();
		// 判断clazz是否为数组的字节码文件
		if (clazz.isArray()) {
			// Array.getLength()可以通过反射获得数组的长度
			for (int i = 0; i < Array.getLength(obj); i++) {
				// Array.get()可以获取指定的元素
				System.out.println(Array.get(obj, i));
			}
		} else {
			System.out.println(obj);
		}
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
大学生在线租房平台管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、报修评价管理、字典管理、房东管理、房屋管理、房屋收藏管理、房屋留言管理、房屋租赁管理、租房论坛管理、公告信息管理、留言板管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生在线租房平台管理系统可以提高大学生在线租房平台信息管理问题的解决效率,优化大学生在线租房平台信息处理流程,保证大学生在线租房平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理大学生在线租房平台信息,包括房屋管理,培训管理,报修管理,薪资管理等,可以管理公告。 房屋管理界面,管理员在房屋管理界面中可以对界面中显示,可以对房屋信息的房屋状态进行查看,可以添加新的房屋信息等。报修管理界面,管理员在报修管理界面中查看报修种类信息,报修描述信息,新增报修信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
基于hal库的OLED显示屏驱动C语言实现源码.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值