【反射】基于反射的实际应用——任意对象数组的排序

来源:互联网 发布:我的世界手机版js制作 编辑:程序博客网 时间:2024/05/22 12:54
日常应用中,经常碰到这么样的问题,比如说,我有一个int数组需要排序,还有一个long数组进行排序,可能还有未知的对象数组需要排序,就好比基础题里边的给学生成绩排序那样,每次我们都要重新写一个代码去排序吗?这样的话重复代码有多少,更万恶的就是如果你根本不知道运行时会有怎么的对象数组需要进行什么排序,这样的代码怎么写?我想很多人都崩溃了,呵呵,其实this is so easy

那么总结下命题,对任意对象的成员变量,或者方法的返回值做为依据而对对象数组进行排序。

这里可以发现,如果需要实现这个功能吗,那么首先我们要在不知道对象的类型的情况下知道他的成员变量的值,或者是相关方法的返回值。

首先,我们先解决怎么获得任意对象的成员变量的值的问题

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


原创粉丝点击