学习JavaEE的日子 Day40 反射案例

Day40

1.反射案例 之 万能数组扩容

java 复制代码
public class Test01 {
	public static void main(String[] args) {
		
		String[] ss = {"小希","小空","小丽","小光","小爱"};
		String[] newSS = MyArrays.copyOf(ss, 8);
		System.out.println(MyArrays.toString(newSS));
		
		int[] is = {1,2,3,4,5};
		int[] newIS = MyArrays.copyOf(is, 8);
		System.out.println(MyArrays.toString(newIS));
	}
}

MyArrays类

java 复制代码
public class MyArrays {
	
	/**
	 * 拷贝数组(以前的方法)
	 * @param original 目标数组
	 * @param newLength 新数组的长度
	 * @return 新数组
	 */
	public static int[] copyOf(int[] original, int newLength){
		
		int copyLength = original.length;
		if(copyLength > newLength){
			copyLength = newLength;
		}
		
		int[] newArr = new int[newLength];
		
		for (int i = 0; i < copyLength; i++) {
			newArr[i] = original[i];
		}
		return newArr;
	}
	
	/**
	 * 反射的方法
	 * 引用数据类型数组的扩容(不支持基本数据类型)
	 * @param original
	 * @param newLength
	 * @return
	 */
	public static <T> T[] copyOf(T[] original , int newLength){
		
		int copyLength = original.length;
		if(copyLength > newLength){
			copyLength = newLength;
		}
		
		//获取元素的类型
		Class<? extends Object[]> clazz = original.getClass();//String[].class
		Class<?> componentType = clazz.getComponentType();//String.clss
		
		//利用反射创建数组
		@SuppressWarnings("unchecked")
		T[] ts = (T[]) Array.newInstance(componentType, newLength);
		
		//遍历源数组,将数据复制到新数组中
		for (int i = 0; i < copyLength; i++) {
			//获取源数组的数据
			Object element = Array.get(original, i);
			//赋值给新数组
			Array.set(ts, i, element);
		}
		return ts;
	}
	
	/**
	 * 将数组转换为字符串
	 * @param a 目标数组
	 * @return 转换后的字符串
	 */
	public static String toString(int[] is) { 
		StringBuffer sb = new StringBuffer();
		
		sb.append("[");
		
		for (int element : is) {
			if(sb.length() != 1){
				sb.append(",");
			}
			sb.append(element);
		}
		sb.append("]");
		return sb.toString();
	}
	
	/**
	 * 将数组转换为字符串
	 * @param a 目标数组
	 * @return 转换后的字符串
	 */
	public static <T> String toString(T[] a){
		
		StringBuffer sb = new StringBuffer();
		
		sb.append("[");
		
		for (int i = 0; i < Array.getLength(a); i++) {
			if(sb.length() != 1){
				sb.append(",");
			}
			Object element = Array.get(a, i);
			sb.append(element);
		}
		
		sb.append("]");
		return sb.toString();
	}
	
}

2.反射案例 之 业务与逻辑分离 的思想

invoke方法参数的意义

参数一:表示代理对象,一般不用(了解)

参数二:就是方法名,我们可以对方法名进行判断,是增强还是拦截

参数三:调用方法时,传递的参数
需求:用户选择获取数据的方式(本地数据、网络数据)

java 复制代码
public class Test01 {
	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		showMenu();
		int num = scan.nextInt();
		
		DataSource dataSource = getDataSourceObject(num);
		dataSource.getDataSource();
		
		scan.close();
	}
	
	public static void showMenu(){
		System.out.println("请选择获取数据的方式:");
		ArrayList<String> menulist = DataCenter.menuList;
		for (String element : menulist) {
			System.out.println(element);
		}
	}
	
	public static DataSource getDataSourceObject(int num){
		DataSource dataSource = DataCenter.dataSourceList.get(num-1);
		return dataSource;
	}
}

配置文件

dataSourceConfig.properties

properties 复制代码
data=com.qf.reflex02.LocalDataSource,com.qf.reflex02.NetworkDataSource,com.qf.reflex02.OtherDataSource

menuConfig.properties

properties 复制代码
data=1-\u83B7\u53D6\u672C\u5730\u6570\u636E,2-\u83B7\u53D6\u7F51\u7EDC\u6570\u636E,3-\u83B7\u53D6\u5176\u4ED6\u6570\u636E
java 复制代码
public abstract class DataSource {

	public abstract void getDataSource();
	
}

数据中心类(选择1,2,3,继续第几个操作)

java 复制代码
//数据中心
public class DataCenter {

	public static final ArrayList<String> menuList;
	public static final ArrayList<DataSource> dataSourceList;
	
	//初始化菜单数据
	static{
		
		menuList = new ArrayList<>();
		
		Properties p = new Properties();
		try {
			p.load(DataCenter.class.getClassLoader().getResourceAsStream("menuConfig.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		String data = p.getProperty("data");
		String[] split = data.split(",");
		Collections.addAll(menuList, split);
	}
	
	//初始化数据源数据
	static{
		
		dataSourceList = new ArrayList<>();
		
		Properties p = new Properties();
		try {
			p.load(DataCenter.class.getClassLoader().getResourceAsStream("dataSourceConfig.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		String data = p.getProperty("data");
		String[] split = data.split(",");
		for (String classPath : split) {
			try {
				Class<?> clazz = Class.forName(classPath);
				DataSource dataSouce = (DataSource) clazz.newInstance();
				dataSourceList.add(dataSouce);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}		
		}
	}
}

获取本地资源的类(第一个选择)

java 复制代码
//获取本地资源的类
public class LocalDataSource extends DataSource{

	private Scanner scan;
	
	public LocalDataSource() {
		scan = new Scanner(System.in);
	}
	
	@Override
	public void getDataSource() {
		
		System.out.println("请填写需要拷贝文件的路径:");
		String path = scan.next();
		File file = new File(path);
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(path));
			bos = new BufferedOutputStream(new FileOutputStream(file.getName()));
			
			byte[] bs = new byte[1024];
			int len;
			while((len=bis.read(bs)) != -1){
				bos.write(bs, 0, len);
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(bis != null){
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(bos != null){
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}

获取网络资源的类(第二个选择)

java 复制代码
//获取网络资源的类
public class NetworkDataSource extends DataSource{

	private Scanner scan;
	
	public NetworkDataSource() {
		scan = new Scanner(System.in);
	}

	@Override
	public void getDataSource() {
		//https://wx2.sinaimg.cn/mw690/e2438f6cly1hoo3qpm7vrj21111jk4mn.jpg
		System.out.println("请填写下载图片的网址:");
		String path = scan.next();
		
		try {
			//创建链接对象
			URL url = new URL(path);
			//获取连接对象
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			
			//设置参数
			connection.setConnectTimeout(5000);//设置连接超时时间
			connection.setReadTimeout(5000);//设置读取数据超时时间
			connection.setDoInput(true);//设置是否允许使用输入流
			connection.setDoOutput(true);//设置是否允许使用输出流
			
			//获取响应状态码
			int code = connection.getResponseCode();
			if(code == HttpURLConnection.HTTP_OK){
				
				//文件名
				String fileName = path.substring(path.lastIndexOf("/")+1);
				
				BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
				byte[] bs = new byte[1024];
				int len;
				while((len = bis.read(bs)) != -1){
					bos.write(bs, 0, len);
				}
				
				bis.close();
				bos.close();
				
			}else if(code == HttpURLConnection.HTTP_NOT_FOUND){
				System.out.println("页面未找到");
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

其他数据(第三个选择)

java 复制代码
//其他数据
public class OtherDataSource extends DataSource{

	@Override
	public void getDataSource() {
		System.out.println("获取其他数据");
	}

}

3.反射案例 之 操作注解

利用注解使Student类的属性与数据库表名一致,与mybatis的起别名差不多

java 复制代码
public class Test01 {
	public static void main(String[] args) {
		
		Student stu = new Student("小威", "男", 18);
		
		String sql = DBUtil.generateInsertSQL(stu);
		System.out.println(sql);
		//INSERT INTO s_student(s_name,s_sex,s_age) VALUES('小威','男',18);
	}
}

类名注解

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableInfo {
	
	String name();
}

属性注解

java 复制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldInfo {
	String name();
	String type();
}

Student类

java 复制代码
@TableInfo(name="s_student")
public class Student {

	@FieldInfo(name="s_name",type="varchar")
	private String name;
	
	@FieldInfo(name="s_sex",type="varchar")
	private String sex;
	
	@FieldInfo(name="s_age",type="int")
	private int age;
	
	//有参构造,无参构造,get,set方法省略
}

数据库SQL拼接:INSERT INTO s_student(s_name,s_sex,s_age) VALUES('小威','男',18);

java 复制代码
public class DBUtil {
	public static String generateInsertSQL(Object obj){
		
		Class<? extends Object> clazz = obj.getClass();
		
		//获取表名
		TableInfo tableInfo = clazz.getAnnotation(TableInfo.class);
		if(tableInfo == null){
			throw new RuntimeException();
		}
		String tableName = tableInfo.name();
		
		StringBuffer names = new StringBuffer();
		StringBuffer values = new StringBuffer();
		
		//获取属性数据
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			
			FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);
			String name = fieldInfo.name();
			String type = fieldInfo.type();
			
			if(names.length() != 0){
				names.append(",");
			}
			names.append(name);
			
			try {
				
				if(values.length() != 0){
					values.append(",");
				}
				
				Object fieldData = field.get(obj);
				if(type.equals("varchar")){
					values.append("'");
				}
				values.append(fieldData);
				if(type.equals("varchar")){
					values.append("'");
				}
				
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		
		String sql = "INSERT INTO " + tableName + "(" + names.toString() + ") VALUES(" + values.toString() + ");";
		return sql;
	}
	
}

你觉得反射好不好?好,有两个方向

第一个方向:无视修饰符访问类中的内容。但是这种操作在开发中一般不用,都是框架底层来用的。

第二个方向:反射可以跟配置文件结合起来使用,动态的创建对象,动态的调用方法。

总结

1.反射案例 -- 万能数组扩展

注意:

1.泛型的使用

2.利用Array操作数组

2.反射案例 -- 业务与逻辑分离的思想

注意:

1.理解思想

2.灵活使用配置文件

3.理解数据中心DataCenter

3.反射案例 -- 操作注解

注意:

1.理解注解是可以给类、属性、方法提供额外信息

相关推荐
带刺的坐椅几秒前
Agent Harness 实战指南:构建生产级 AI Agent 的"马具"框架
java·ai·llm·agent·solon-ai
c238563 分钟前
互斥锁高频面试题全解:从基础概念到底层实现,一文通关
java·c++·面试·职场和发展
HERR_QQ24 分钟前
强化学习的数学原理 学习笔记
人工智能·笔记·学习·自动驾驶
error:(42 分钟前
【系统与实战双精通】VS Code 调试 ROS2 Python 节点与 Launch 系统指南
android·java·python
Tian_Hang1 小时前
Eclipse Ditto 的权限策略
java·服务器·前端·网络·ide·ubuntu·eclipse
MartinYeung51 小时前
[论文学习]DP-Fusion:面向大语言模型的令牌级差分隐私推理-深度解析
人工智能·学习·语言模型
小蓝波2 小时前
docker 的命令
java·docker·容器
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第155题】【06_Spring篇】第15题:Spring 如何解决循环依赖问题?
java·spring·循环依赖·三级缓存·aop代理
zwenqiyu2 小时前
非线性字符串数据结构串讲
数据结构·c++·学习·算法
唐青枫2 小时前
Java Maven 实战指南:从 POM、依赖管理到多模块构建
java