A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始


【南京校区】利用反射玩转LinkedList



    本文案例再实际开发中并无太大的意义,但是希望大家通过本文的学习能更好的熟悉反射机制和掌握链表结构的原理。
    反射机制的重要性,就不必多说了。目前使用的框架的底层都大量的使用到了反射机制。
    首先反射的作用很简单,通俗来讲就是无视修饰符,可以通过字节码文件获取任意一个类中的任意一个成员变量和成员方法。简单粗暴。所以我们可以利用反射机制实现很多很好玩的效果。
    比如,LinkedList集合大家都非常的熟悉,底层链表结构的,以Node这个内部类来表示每一个节点的。
    通过前一个节点记录下一个节点的地址值,后一个记录前一个节点的地址值来一一连起来的。

   
[AppleScript] 纯文本查看 复制代码
[/align]
[align=left]    private static class Node<E> {[/align]
      E item;
      Node<E> next;
      Node<E> prev;

      Node(Node<E> prev, E element, Node<E> next) {
          this.item = element;
          this.next = next;
          this.prev = prev;
      }
     }


    其中item才是记录的本节点的值,next是记录下一个节点的地址值,prev是记录前一个节点的地址值。
   如图所示:
        


     在第一个Node的前一个和最后一个node的后一个因为没有元素了,所以记录的地址值为null
     在LinkedList中第一个节点是有一个成员变量表示的,Node<E> first;最后一个节点也是有一个成员变量表示的,Node<E> last;
    所以我们试想一下,如果可以通过反射技术,能得到一个链表的最后一个节点,再获取到第一个节点的地址值。把最后一个节点的next记录为第一个节点的地址值。那么就会将链表形成一个圆的形式。如果各位能把这个圆结构实现了,那么恭喜你,至少反射技术你就已经牢牢的掌握了。
    废话不多说,直接上代码。


[AppleScript] 纯文本查看 复制代码
public class Demo {
        public static void main(String[] args) throws ClassNotFoundException, Exception, SecurityException {
                LinkedList<Integer> list = new LinkedList<>();
                list.add(1);
                list.add(2);
                list.add(3);
                list.add(4);
                
                //反射节点的next
                //Node这个类是LinkedList的一个内部类
                //所以首先需要反射Node这个内部类
                Class LinkedList$Nodeclazz = Class.forName("java.util.LinkedList$Node");
                //得到Node这个内部类的next属性对象
                Field nextField = LinkedList$Nodeclazz.getDeclaredField("next");
                nextField.setAccessible(true);
                
                //反射集合的首个节点
                //反射LinkedList
                Class LinkedListClazz = Class.forName("java.util.LinkedList");
                //得到这个链表的first这个成员变量的对象
                Field firstField = LinkedListClazz.getDeclaredField("first");
                firstField.setAccessible(true);
                
                //反射集合的末尾节点
                Field lastField = LinkedListClazz.getDeclaredField("last");
                lastField.setAccessible(true);
                //得到最后一个节点的对象
                Object last = lastField.get(list);
                //得到第一个节点的对象
                Object first = firstField.get(list);
                System.out.println(first);
                
                //给集合的最后节点下一个元素记录未第一个节点的地址值,形成循环
                Object obj = nextField.get(last);
                //null打印结果为null,因为最后一个节点的下一个是没有节点的
                System.out.println(obj);
                //把最后一个节点的下一个设置为第一个节点
                //形成了一个圆圈
                nextField.set(last, first);
                
                //找5这个元素,因为LinkedList在底层中从第一个节点开始匹配
                //如果第一个节点不是5,那么就找下一个节点
                //因为集合中没有5,所以形成了一个死循环。
                System.out.println(list.contains(new Integer(5)));
        }
}

     通过以上的这个案例,相信大家至少是已经掌握了反射这个技术了。
    希望大家能通过不断的研究来提高自己的技术。
    学无止境,大家加油!




4 个回复

倒序浏览
感恩分享
回复 使用道具 举报
不明觉厉
回复 使用道具 举报
表示很崇拜
回复 使用道具 举报
不明觉厉,6666666666666
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马