java反射机制的复习

转载出处:https://blog.youkuaiyun.com/sinat_38259539/article/details/71799078

1、Class类是被final修饰的类不能被继承
2、Class类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象 。基本的Java类型(boolean,byte,char,short,int,long,float和double)和关键字void也表示为Class对象。Class对象没有公共构造方法。Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的


一、获取构造方法并使用

自己写的练习demo

Student类

public class Student {
	//--------构造方法---------------
	//(默认的构造方法)
	Student(String str) {
		System.out.println("默认的构造方法="+str);
	}
	
	//无参的构造方法
	public Student(){
		System.out.println("调用了公有,无参构造方法");
	}
	
	//有一个参数的构造方法
	public Student(char name){
		System.out.println("姓名:"+name);
	}
	
	//有多个参数的构造方法
	public Student(String name,int age){
		System.out.println("姓名:"+name + "年龄:"+age);
	}
	
	//受保护的构造方法
	protected Student(boolean n){
		System.out.println("受保护的构造方法n = "+n);
	}
	
	//私有方法
	private Student(int age){
		System.out.println("私有的构造方法 年龄:"+age);
	}
}

测试类

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Constructors {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class class1 = Class.forName("com.sunj.test.Student");
		//获取所有共有的构造方法
		System.out.println("获取所有公有的构造方法");
		Constructor [] con1=class1.getConstructors();
		for (Constructor c1 : con1) {
			System.out.println(c1);
		}
		
		//获取所有的构造方法
		System.out.println("获取所有的构造方法,不管它的修饰符是公有,默认,保护,私有");
		Constructor [] con2 = class1.getDeclaredConstructors();
		for (Constructor c2 : con2) {
			System.out.println(c2);
		}
		
		System.out.println("获取公有,无参的构造方法");
		Constructor con3 = class1.getConstructor(null);//返回的是该构造方法的类对象
		System.out.println(con3);
		Object object = con3.newInstance(null);//调用该方法
		
		System.out.println("获取私有构造方法并调用");
		Constructor con4 = class1.getDeclaredConstructor(int.class);
		System.out.println(con4);
		//调用构造方法
		con4.setAccessible(true);//忽略掉访问修饰符
		object = con4.newInstance(22);
		
	}

}

getDeclaredConstructors和getConstructors方法的区别

1、getDeclaredConstructors是获取所有的构造方法,而getConstructor是获取所有的公有方法

2、两者都可以通过传参拿到指定的构造方法,这里的参数是构造方法的参数的类型,比如构造方法传的String name,那么这里就传的是String.class

 

调用方法:

1.获取构造方法:

  1).批量的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
            public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
     
  2).获取单个的方法,并调用:
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

  调用构造方法:

Constructor-->newInstance(Object... initargs)

 

2、newInstance是 Constructor类的方法(管理构造函数的类)

api的解释为:

newInstance(Object... initargs)
           使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用

二、获取成员变量

public class User {
	public User(){
		
	}
	//*************字段*************//
	public String name;
	protected int age;
	char sex;
	private String phoneNum;
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", sex=" + sex + ", phoneNum=" + phoneNum + "]";
	}
	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 char getSex() {
		return sex;
	}
	public void setSex(char sex) {
		this.sex = sex;
	}
	public String getPhoneNum() {
		return phoneNum;
	}
	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}
	
	
}

测试类

import java.lang.reflect.Field;

public class Fields {
	public static void main(String[] args) throws Exception {
		//1、获取class对象
		Class class1 = Class.forName("com.sunj.test.User");
		//2、获取字段
		System.out.println("获取所有的公有字段");
		Field[] f1 = class1.getFields();
		for (Field field1 : f1) {
			System.out.println(field1);
		}
		//3、获取所有的字段
		System.out.println("获取所有的字段");
		Field [] f2 = class1.getDeclaredFields();
		for (Field field2 : f2) {
			System.out.println(field2);
		}
		
		//4、获取公有字段并调用
		System.out.println("获取公有字段并调用");
		Field field1 = class1.getField("name");
		System.out.println(field1);
		//获取一个对象
		Object object = class1.getConstructor().newInstance();//相当于User user = new User();
		//为字段设值
		field1.set(object, "花花");//相当于user.setName("花花");
		//验证
		User user = (User)object;
		System.out.println(user.name);
		
		//5、获取私有字段并调用
		System.out.println("获取私有字段并调用");
		Field fi = class1.getDeclaredField("phoneNum");
		System.out.println(fi);
		fi.setAccessible(true);//忽略私有属性
		fi.set(object, "18712111");
		user = (User)object;
		System.out.println(user.getPhoneNum());
	}

}

调用字段时,第一个参数:要传入设置的对象,第二个参数:要传入实参,就相当于平时我们写的对象的set方法

三、获取成员方法并调用

public class Student {
	// **************成员方法***************//
	public void show1(String s) {
		System.out.println("调用了:公有的,String参数的show1(): s = " + s);
	}

	protected void show2() {
		System.out.println("调用了:受保护的,无参的show2()");
	}

	void show3() {
		System.out.println("调用了:默认的,无参的show3()");
	}

	private String show4(int age) {
		System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
		return "abcd";
	}

}

测试类:

import java.lang.reflect.Method;

public class Methods {
	public static void main(String[] args) throws Exception {
		Class class1 = Class.forName("com.sunj.test.Student");

		// 1、获取所有的公有方法
		System.out.println("获取所有的公有方法");
		Method[] methods = class1.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}

		// 2、获取搜有的方法
		System.out.println("获取所有的方法");
		Method[] methods2 = class1.getDeclaredMethods();
		for (Method method : methods2) {
			System.out.println(method);
		}

		// 3、获取公有的show1方法
		System.out.println("获取公有的show1方法");
		Method m1 = class1.getMethod("show1", String.class);
		Object obj = class1.getConstructor().newInstance();
		m1.invoke(obj, "你好呐");

		// 获取私有的show4方法
		System.out.println("获取私有的show4方法");
		Method m2 = class1.getDeclaredMethod("show4", int.class);//调用定制方法(包括私有的),需要传入两个参数,第一个是调用的方法名称,第二个是方法的形参类型。
		m2.setAccessible(true);//解除私有绑定
		Object result = m2.invoke(obj, 18);//调用时需要两个参数,一个是要调用的对象(获取有反射),一个是实参
		System.out.println(result);


	}

}

注意:获取公有方法时,连父类Object的公有方法也会打印出来

           而获取所有的方法时,Object类的方法并没有打印出来。

四、反射main方法

public class Student {
	public static void main(String[] args) {
		System.out.println("main方法已执行"  + args[0]);
	}

}

测试类

import java.lang.reflect.Method;

public class Methods {
	public static void main(String[] args) throws Exception {
		Class class1 = Class.forName("com.sunj.test.Student");

	//获取main方法
		Method methodMain = class1.getMethod("main", String[].class);
		Object obj = class1.getConstructor().newInstance();
		methodMain.invoke(null,(Object)new String[]{"a","b","c"});
	}

}

反射main方法的调用:

methodMain.invoke(null,(Object)new String[]{"a","b","c"}); 

五、反射方法的其它使用之---通过反射运行配置文件内容

package com.sunj.test;

public class Student {
	public void show(){
		System.out.println("is show()");
	}

}

配置文件

className = com.sunj.test.Student
methodName = show

测试类

import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改
 * 我们只需要将新类发送给客户端,并修改配置文件
 * @author vela_sun
 *
 */
public class Demo {
	public static void main(String[] args) throws Exception{
		//通过反射获取class对象
		Class class1 = Class.forName(getValue("className"));
		//获取show方法
		Object object = class1.getConstructor().newInstance();
		Method method = class1.getMethod(getValue("methodName"));
		method.invoke(object);
	}
	
	//此方法接收一个key,在配置文件获取相应的value
	public static String getValue(String key) throws Exception{
		Properties properties = new Properties();//获取配置文件
		FileReader in = new FileReader("src\\main\\java\\com\\sunj\\test\\pro.txt");
		properties.load(in);
		in.close();
		return properties.getProperty(key);
	}
}
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改
 * 我们只需要将新类发送给客户端,并修改配置文件
 * @author vela_sun
 *
 */
public class Demo {
	public static void main(String[] args) throws Exception{
		//通过反射获取class对象
		Class class1 = Class.forName(getValue("className"));
		//获取show方法
		Object object = class1.getConstructor().newInstance();
		Method method = class1.getMethod(getValue("methodName"));
		method.invoke(object);
	}
	
	//此方法接收一个key,在配置文件获取相应的value
	public static String getValue(String key) throws Exception{
		Properties properties = new Properties();//获取配置文件
		FileReader in = new FileReader("src\\main\\java\\com\\sunj\\test\\pro.txt");
		properties.load(in);
		in.close();
		return properties.getProperty(key);
	}
}

注意:配置文件和测试类在同一个目录,获取属性文件时的路径也不能直接写名字

当我们升级这个系统时,不要Student类,而需要新写一个Student2的类时,这时只需要更改pro.txt的文件内容就可以了。代码就一点不用改动

六、反射方法的其它使用之---通过反射越过泛型检查

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * 通过反射机制越过泛型检查
 * 例如,有一个String泛型的集合,怎样像这个集合添加一个Integer类型的数据
 * @author vela_sun
 *
 */
public class Demo {
	public static void main(String[] args) throws Exception{
		ArrayList<String> list = new ArrayList<String>();
		list.add("aa");
		list.add("bb");
		list.add("cc");
		//获取Arraylist的Class对象,反向的调用add()方法,添加数据
		Class class1 = list.getClass();
		Method method = class1.getMethod("add", Object.class);
		method.invoke(list, 100);
		for (Object oo : list) {
			System.out.println(oo);
		}
	}
}

 

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值