Day44 Java的反射案例
文章目录
- Day44 Java的反射案例
- 一、反射案例 之 万能数组扩容
- 二、反射案例 之 业务与逻辑分离 的思想
- 三、反射案例 之 操作注解
一、反射案例 之 万能数组扩容
1、基本步骤:
- 获取原始数组的类型:
- 使用
array.getClass().getComponentType()
方法获取原始数组的元素类型。
- 使用
- 创建新数组:
- 使用
Array.newInstance(type, newSize)
方法根据原始数组的元素类型和新的大小创建一个新数组。
- 使用
- 复制原始数组元素到新数组:
- 使用
System.arraycopy()
方法将原始数组的元素复制到新数组中。
- 使用
- 返回新数组:
- 将新数组返回给调用者,完成数组扩容的操作。
2、示例代码:
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));
}
}
import java.lang.reflect.Array;
/**
* 数组工具类
* @author 小杨
* @version 1.0
*/
public class MyArrays {
/**
* 数组的排序
* @param a 目标数组
*/
public static void sort(int[] a){
for (int i = 0; i < a.length-1; i++) {
for (int j = 0; j < a.length-1-i; j++) {
if(a[j] > a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
/**
* 数组的查找,必须先排序,在查找
* @param a 目标数组
* @param key 需要查找的键
* @return 如果搜索的元素包含在数组中就返回元素的下标; 否则,返回(-插入点-1)
*/
public static int binarySearch(int[] a,int key){
int start = 0;
int end = a.length-1;
while(start <= end){
int mid = (start+end)/2;
if(key < a[mid]){
end = mid-1;
}else if(key > a[mid]){
start = mid+1;
}else{
return mid;
}
}
return -start-1;
}
/**
* 拷贝数组
* @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 original 目标数组
* @param from 开始下标-包含
* @param to 结束下标 - 排他
* @return 新数组
*/
public static int[] copyOfRange(int[] original, int from, int to){
int newLength = to-from;
int[] newArr = new int[newLength];
int index = 0;
for (int i = from; i < to; i++) {
newArr[index++] = original[i];
}
return newArr;
}
/**
* 替换全部元素
* @param a 目标数组
* @param val 替换的值
*/
public static void fill(int[] a, int val){
fill(a, 0, a.length, val);
}
/**
* 替换区间元素
* @param a 目标数组
* @param fromIndex 开始下标 - 包含
* @param toIndex 结束下标 - 排他
* @param val 替换的值
*/
public static void fill(int[] a, int fromIndex, int toIndex, int val){
for (int i = fromIndex; i < toIndex; i++) {
a[i] = val;
}
}
/**
* 将数组转换为字符串
* @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();
}
}
二、反射案例 之 业务与逻辑分离 的思想
1、基本步骤:
- 定义接口:
- 首先,定义一个接口来描述业务逻辑的操作,接口中包含需要实现的方法。
- 编写具体实现类:
- 编写实现接口的具体业务逻辑类,每个类负责实现接口中定义的方法,完成具体的业务逻辑。
- 利用反射动态加载类:
- 在一个通用的类中,通过反射机制动态加载指定的类,实现业务逻辑与具体实现类的解耦。
- 创建实例并调用方法:
- 利用反射创建实例,并调用接口中定义的方法执行业务逻辑。
2、示例代码:
import java.util.ArrayList;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Properties;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
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;
}
}
//数据中心
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();
}
}
}
}
public abstract class DataSource {
public abstract void getDataSource();
}
//获取本地资源的类
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();
}
}
}
}
}
//获取网络资源的类
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();
}
}
}
public class OtherDataSource extends DataSource{
@Override
public void getDataSource() {
System.out.println("获取其他数据");
}
}
三、反射案例 之 操作注解
1、基本步骤:
- 定义注解:
- 首先,定义一个注解,可以通过元注解
@Target
和@Retention
指定注解的作用目标和生命周期,定义注解的属性。
- 首先,定义一个注解,可以通过元注解
- 在类、方法、字段上使用注解:
- 在需要使用注解的类、方法、字段上使用定义好的注解,可以为注解的属性赋值。
- 利用反射获取注解信息:
- 使用反射机制获取类、方法、字段上的注解信息,可以通过
getAnnotation()
方法获取指定的注解实例,进而获取注解的属性值。
- 使用反射机制获取类、方法、字段上的注解信息,可以通过
- 根据注解信息进行处理:
- 根据获取到的注解信息,可以编写相应的逻辑来处理注解,例如根据注解的属性值执行不同的操作。
- 动态生成带有注解的类、方法、字段:
- 可以通过反射机制动态生成带有注解的类、方法、字段,并在运行时进行相应的处理。
注意: 通过这些步骤,可以实现对注解的操作,包括获取注解信息、根据注解信息进行相应的处理,实现了业务逻辑与注解的解耦,提高了代码的灵活性和可扩展性。
2、示例代码:
import java.lang.reflect.Field;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
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);
}
}
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;
}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldInfo {
String name();
String type();
}
@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;
public Student() {
}
public Student(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableInfo {
String name();
}