通过反射取得hashmap的值

本人最近项目中在遇到个这个情况,需要做动态代理,invoke方法里的参数是object类型,实际参数是hashmap类型,需要从object类型里面取出key value键值对

首先hashmap和object是不能直接强制转换类型的,我采用反射取得数据

为了取得数据,首先得了解下hashmap的结构

在这里只讲点关键点,hashmap里面有个内部类,Node<K,Y>这个就是存放key value 的节点

 static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }
transient Node<K,V>[] table;

可以看出hashmap的值存在属性table数组里面

然后看到node内部类属性有hash值,key,value,指向相同hash值的下一个节点的引用next

因为在hashmap里面key虽然不同,然后有可能经过hash值转换后生成的hash值相同,这个时候,相同的hash值的节点形成一个链表的形式


类似于这个模样,相同的hash值,存储的键值对node节点,以链表组装起来

现在需要将object类参数(实际上是hashmap类型,用父类引用指向子类对象)反射出里面的值

HashMap<String,Object> hashmap=new HashMap<String, Object>();	 
	Class clsHashMap$Node = null;
	clsHashMap$Node = Class.forName("java.util.HashMap$Node");        //通过反射得到hashmap里面内部类node
        Field[] fields = parameter.getClass().getDeclaredFields();
        for(Field field:fields){
       		field.setAccessible(true);
                if(field.getName()=="table"){            //遍历属性,当时table属性时候
            	     Object[] node= (Object[]) field.get(parameter);   //得到table属性值
            	 	for (Object object : node) {  //遍历
				if(object!=null){	//有可能table数组有node为空,因为hash值特性
					try {
					    iteration(object, clsHashMap$Node, hashmap);   //递归	
						
					} catch (NoSuchFieldException | SecurityException e) {
						e.printStackTrace();
					}
				}
		}
            	
             }
             
       
         }


private void iteration(Object object,Class clsHashMap$Node,HashMap<String,Object> hashmap) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
		
		Field key = clsHashMap$Node.getDeclaredField("key");     //获取node类里面的key属性
		Field value = clsHashMap$Node.getDeclaredField("value");  //获取node类里面value属性
		Field next = clsHashMap$Node.getDeclaredField("next");   //获取node类里面next属性
		
		key.setAccessible(true);
		value.setAccessible(true);
		next.setAccessible(true);
		
		//得到三个属性的属性值
		String strkey = key.get(object).toString();		
		Object objValue = value.get(object);
		Object objNext = next.get(object);
		//判断next是否为空,不为空则递归
		if(objNext==null)
		{			
		
			hashmap.put(strkey, objValue);
		}else{
			iteration(objNext, clsHashMap$Node, hashmap);		
		}
	}


最后,我们就讲hashmap里面的值全部反射出来


猜你喜欢

转载自blog.csdn.net/qq_33330687/article/details/76854282
今日推荐