【反射】基于反射的实际应用——任意对象数组的排序
来源:互联网 发布:我的世界手机版js制作 编辑:程序博客网 时间:2024/05/22 12:54
日常应用中,经常碰到这么样的问题,比如说,我有一个int数组需要排序,还有一个long数组进行排序,可能还有未知的对象数组需要排序,就好比基础题里边的给学生成绩排序那样,每次我们都要重新写一个代码去排序吗?这样的话重复代码有多少,更万恶的就是如果你根本不知道运行时会有怎么的对象数组需要进行什么排序,这样的代码怎么写?我想很多人都崩溃了,呵呵,其实this is so easy
那么总结下命题,对任意对象的成员变量,或者方法的返回值做为依据而对对象数组进行排序。
这里可以发现,如果需要实现这个功能吗,那么首先我们要在不知道对象的类型的情况下知道他的成员变量的值,或者是相关方法的返回值。
对于这个Cat类的age变量,取得他的值可以通过映射方式来获得,学过映射都应该知道映射其实就是把整个类的所有成员给你映射成相关的对象。
这样控制台就打印出了这个cat对象的age变量的值为1。
这样的私有成员,除非我们把访问权限改了,要不然会通过上边的字段方式是不能访问的,所以我们可以访问他的函数,拿返回值
这里的invoke方法就是执行一次这个方法,如果有返回值就返回,void返回null。
但是到这呢,我们会发现一个奇怪的问题,这和我们想的不太一样,因为变量有可能其他的类型(这里暂时只说整数和浮点),难道我们还需要去逐一检测类型?其实最简单的办法就是在排序时,把他们全变成double,这样子,包括整数和浮点都可以进行对比了。
这个代码是错误的,原因是强制转化失败,呵呵,还记得基本类型的包装类吗,parsexxx这个函数果断的是很好用的
现在准备工作做完了,我们可以开始写个简单的例子试试成果。
100.0
150.0
50.0
输出木有问题,这里用的是调用函数来取值,如果是访问成员的话,用field那个方式。但是有些对象的成员是私有的,你只能用函数,所以,这两种方式我们都应该提供。
这里还有一个新东西,没发现的去撞墙,呵呵,就是吧,我们说的是任意对象对吧,那我们在来一个Wolf吧
到这呢,其实输出就知道了,我们发所有具有getAge方法的对象,我们全可以拿来排序。。。或者只要具有相同的可以访问的成员变量的对象也行,这个跟以前我们需要他们都继承一个超类来达到上朔遍历不太一样,我们这个更开放,更自由,但是这个猫和狼呢,确实还是要一个动物的超类,这样更好理解一些东西,这个在我另外一个帖子抽象和接口选择那里有说。
好了,到这,我想应该都看明白了,只需要在实现下排序就可以了,拿值的问题都已经解决,排序的话就照葫芦画瓢就行了,下边把完整的代码贴一下,bug肯定多,就是演示下反射的简单用途,当然这是最简单的用法。
那么总结下命题,对任意对象的成员变量,或者方法的返回值做为依据而对对象数组进行排序。
这里可以发现,如果需要实现这个功能吗,那么首先我们要在不知道对象的类型的情况下知道他的成员变量的值,或者是相关方法的返回值。
首先,我们先解决怎么获得任意对象的成员变量的值的问题
class Cat{ public int age = 1;}
对于这个Cat类的age变量,取得他的值可以通过映射方式来获得,学过映射都应该知道映射其实就是把整个类的所有成员给你映射成相关的对象。
Cat cat = new Cat(); System.out.println(cat.getClass().getField("age").get(cat));
这样控制台就打印出了这个cat对象的age变量的值为1。
class Cat{ private int age = 1; public Cat() { } public Cat(int age) { this.age = age; } public int getAge() { return age; }}
这样的私有成员,除非我们把访问权限改了,要不然会通过上边的字段方式是不能访问的,所以我们可以访问他的函数,拿返回值
Cat cat = new Cat(); System.out.println(cat.getClass().getMethod("getAge").invoke(cat));
这里的invoke方法就是执行一次这个方法,如果有返回值就返回,void返回null。
但是到这呢,我们会发现一个奇怪的问题,这和我们想的不太一样,因为变量有可能其他的类型(这里暂时只说整数和浮点),难道我们还需要去逐一检测类型?其实最简单的办法就是在排序时,把他们全变成double,这样子,包括整数和浮点都可以进行对比了。
(double)cat.getClass().getMethod("getAge").invoke(cat)
这个代码是错误的,原因是强制转化失败,呵呵,还记得基本类型的包装类吗,parsexxx这个函数果断的是很好用的
Double.parseDouble(cat.getClass().getMethod("getAge").invoke(cat).toString())
现在准备工作做完了,我们可以开始写个简单的例子试试成果。
Cat[] cats = {new Cat(100),new Cat(150),new Cat(50)}; for (Cat cat : cats) { System.out.println(Double.parseDouble(cat.getClass().getMethod("getAge").invoke(cat).toString())); }
100.0
150.0
50.0
输出木有问题,这里用的是调用函数来取值,如果是访问成员的话,用field那个方式。但是有些对象的成员是私有的,你只能用函数,所以,这两种方式我们都应该提供。
这里还有一个新东西,没发现的去撞墙,呵呵,就是吧,我们说的是任意对象对吧,那我们在来一个Wolf吧
class Wolf{ public int age = 10; public Wolf() { } public Wolf(int age) { this.age = age; } public int getAge() { return age; } public String toString() { return ""+age; }}class Cat{ private int age = 1; public Cat() { } public Cat(int age) { this.age = age; } public int getAge() { return age; } public String toString() { return ""+age; }}Object[] objects = {new Wolf(100),new Cat(150),new Cat(50)}; for (Object object : objects) { System.out.println(Double.parseDouble(object.getClass().getMethod("getAge").invoke(object).toString())); }
到这呢,其实输出就知道了,我们发所有具有getAge方法的对象,我们全可以拿来排序。。。或者只要具有相同的可以访问的成员变量的对象也行,这个跟以前我们需要他们都继承一个超类来达到上朔遍历不太一样,我们这个更开放,更自由,但是这个猫和狼呢,确实还是要一个动物的超类,这样更好理解一些东西,这个在我另外一个帖子抽象和接口选择那里有说。
好了,到这,我想应该都看明白了,只需要在实现下排序就可以了,拿值的问题都已经解决,排序的话就照葫芦画瓢就行了,下边把完整的代码贴一下,bug肯定多,就是演示下反射的简单用途,当然这是最简单的用法。
import java.lang.reflect.InvocationTargetException;class Wolf{ public int age = 10; public Wolf() { } public Wolf(int age) { this.age = age; } public int getAge() { return age; } public String toString() { return ""+age; }}class Cat{ public int age = 1; public Cat() { } public Cat(int age) { this.age = age; } public int getAge() { return age; } public String toString() { return ""+age; }}public class lll{ public static final boolean FROM_SMALL_TO_LARGE = true; public static final boolean FROM_LARGE_TO_SMALL = false; public static void main(String[] args) throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Object[] objects = {new Wolf(15), new Cat(20), new Wolf(), new Cat()}; for (Object object : objects) { System.out.println(object.toString()); } bubbleSort(objects, "getAge()", FROM_SMALL_TO_LARGE); System.out.println("===============================>"); for (Object object : objects) { System.out.println(object.toString()); } System.out.println("===============================>"); bubbleSort(objects, "age", FROM_LARGE_TO_SMALL); for (Object object : objects) { System.out.println(object.toString()); } } public static void bubbleSort(Object[] src, String expression, boolean is) throws NumberFormatException, IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException { int index = expression.indexOf("()"); if(index != -1) { expression = expression.substring(0, index); } double a,b; for (int i = 0; i < src.length; ++i) { for (int j = 0; j < src.length - i - 1; ++j) { if(index != -1) { a = Double.parseDouble(src[j].getClass().getMethod(expression).invoke(src[j]).toString()); b = Double.parseDouble(src[j+1].getClass().getMethod(expression).invoke(src[j+1]).toString()); } else { a = Double.parseDouble(src[j].getClass().getField(expression).get(src[j]).toString()); b = Double.parseDouble(src[j+1].getClass().getField(expression).get(src[j+1]).toString()); } if(is && a > b) { swap(src, j, j+1); } else if(!is && a < b) { swap(src, j, j+1); } } } } public static void swap(Object[] data, int i, int j) { Object temp = data[i]; data[i] = data[j]; data[j] = temp; }}
1520101===============================>1101520===============================>2015101
- 【反射】基于反射的实际应用——任意对象数组的排序
- 反射的实际应用
- 黑马程序员——反射的实际应用
- SSM(九)反射的实际应用-构建日志对象
- 2013.9.10 反射的实际应用
- SSM(九) 反射的实际应用
- Java -- 利用反射 操作任意数组,包括对象数组 和 基本数据类型的数组
- 反射:Class类、反射概念、类中各成员的反射、反射的应用、数组的反射、框架
- 探讨Java代理模式与反射机制的实际应用
- java动态与反射的基本原理及实际应用
- 数组反射,判断Class 对象是否为数组及类型。将任意类型数组的大小加倍
- 数组反射,判断Class 对象是否为数组及类型。将任意类型数组的大小加倍 .
- java利用反射扩展任意数组的方法
- 程序清单-利用反射扩展任意类型的数组
- 黑马程序员—数组的反射
- java基础——反射的应用
- HLSL的应用—反射环境映射
- (小工具)Java反射机制实现任意对象集合排序并且获取排列名次的通用程序实践
- JSP中pageEncoding和charset区别,中文乱码解决方案
- jQuery BlockUI插件
- ymPrompt消息提示组件4.0版[2009-03-02]DEMO演示及使用简介
- Java+PHP整合=混血新宠儿
- jquery中手风琴效果实用源代码
- 【反射】基于反射的实际应用——任意对象数组的排序
- request 获取访问IP
- 建立索引时no segments* file found 的问题
- SendMessage 和 PostMessage 的区别
- CryENGINE Feathure
- 用了皮肤控件之后,报错:容量超出了最大容量 参数名:capacity
- jquery-dialog对话框的实现
- 超链接点击无效的实现方式
- 怎么使游戏按下home的时候进入暂停状态 然后再次进入点击按钮恢复?