-
2021-01-30 00:13:56
直接总结结论:
类继承于map或者list或者set后,在其他对于这个类的操作时需要特别注意,比如,使用fastjson等工具类进行转换成json时将不会转换map、list、set之外的属性。举例,A类继承list后,又在A类中添加了一个name属性,如果将A类转换成json将不会包含A类的属性,就是json中不包含name属性,只会调用list的中的比如迭代器进行遍历list的方式查询list中的数据。如果A类是自己set属性后自己get属性,那么没有影响。
扩展:将A类返回给jsp后使用jstl标签遍历也是遍历不到name属性的。
聚合优于继承,所以尽量将list、map、set作为类的属性而不要去继承。
扩展2、在使用feign进行远程调用时会自动进行json转换,所以远程调用收不到。更多相关内容 -
java继承hashmap的序列化问题
2021-08-19 16:20:07一开始我是用R继承hashmap然后定义一个私有属性data,没想到出错了,因为序列化过程中会忽略掉类的私有属性(继承hashmap的类),因此在反序列过程中会吧data的值丢失。 public class R<T> extends HashMap<...在springcloud微服务调用返回数据时,出现获取数据为null的情况:
一开始我是用R继承hashmap然后定义一个私有属性data,没想到出错了,因为序列化过程中会忽略掉类的私有属性(继承hashmap的类),因此在反序列过程中会吧data的值丢失。public class R<T> extends HashMap<String,T> { private T data; public void setData(T data){ this.data = (T) data; }; public T getData(){ return data; } } class t{ public static void main(String[] args) { R r = new R(); r.setData(new Integer(1)); System.out.println(r.getData()); //序列化 String s = JSON.toJSONString(r); System.out.println(s); //反序列化 R r1 = JSON.parseObject(s, R.class); System.out.println(r1.getData()); /**结果为 * 1 * {} * null */ } }
因此在放入数据时,需要利用put的方法放入map中,而又因为springcloud在调用其他服务后返回结果会转换为LinkedHashMap(前提是,如果map中的value为复杂对象,例如为List。这里不是很清楚,懂得人可以解答下),所以先将LinkedHashMap转换为json字符串,然后再转换为自己想要的类型对象
public class R extends HashMap<String, Object> { private static final long serialVersionUID = 1L; public <T> T getData(TypeReference<T> typeReference){ Object data = get("data"); String s = JSON.toJSONString(data); T t = JSON.parseObject(s, typeReference); return t; } public R setData(Object data){ put("data",data); return this; }
-
java7hashmap源码-java:Java
2021-06-04 16:02:34hashmap源码 Table Of Contents day01_JAVA语言概述与基本语法:标识符、变量也变量分类、源码_反码_补码、进制转换、编码与字符集 day02_基本语法.运算符:算术运算符、赋值运算符、比较运算符、逻辑运算符、位... -
反射获取hashmap以及继承hashmap的类
2021-12-10 09:43:39反射获取hashmap以及继承hashmap的类反射获取hashMap
反射是基于hashmap内部实现原理,Hashmap的核心在putval方法和内部类Node的组成.
核心方法putVal
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
可以看到hashmap由Node对象构成基础,那么我们反射的时候就要想法设法的把它的node给搞出来
Node构成
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; } }
node由hash,key,value,next这几个构成,他们都为属性名,那么就是可以通过反射获取到的。
反射的实现
//o 就是一个hash数组 里面有{code,msg,data} private Object GetHashTableValue(Object o){ Object resObj = new Object(); //定义hashmap Class clsHashMap = null; //定义hashmap里的Node Class clsHashMap$Node = null; Field[] f = null; Field t = null, fNode = null; try { clsHashMap = Class.forName("java.util.HashMap"); clsHashMap$Node = Class.forName("java.util.HashMap$Node"); // 获取hashmap里的全部属性 //里面有serialVersionUID,DEFAULT_INITIAL_CAPACITY,MAXIMUM_CAPACITY,DEFAULT_LOAD_FACTOR,TREEIFY_THRESHOLD,UNTREEIFY_THRESHOLD,MIN_TREEIFY_CAPACITY, f = clsHashMap.getDeclaredFields(); AccessibleObject.setAccessible(f, true); for (Field field : f) { // System.out.println(field.getName()); //获取属性名为table的,然后赋值给 filed if (field.getName() == "table") t = field; } //这这里的t为tree transient Node<K,V>[] table; 由此可见这个是一个数组,所以要Object[] 来转换下 //注:如果是继承hashmap那么继承的属性也会在这里面。比如有个getmes类,其中有code,msg属性,那么o1也会有 Object[] o1 = ((Object[]) t.get(o)); //这里面遍历的便是node for (Object o2 : o1) { if (o2!=null){ Object next = o2;//这个next就相当于是node一个类 while (next!=null){ //反射value属性 Field value = clsHashMap$Node.getDeclaredField("value"); //反射next属性 Field o_next = clsHashMap$Node.getDeclaredField("next"); //根据自己需要还可以反射key和hash,方法一样 o_next.setAccessible(true); value.setAccessible(true); //得到value值 resObj = value.get(next); //得到下个节点node 可以赋值给fNode Object objNext = o_next.get(next); next = objNext; } } } } catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) { e.printStackTrace(); } return resObj; }
可以看到hashmap有大量的属性
transient Node<K,V>[] table; private static final long serialVersionUID = 362498820763181265L; /** * The default initial capacity - MUST be a power of two. */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 /** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arguments. * MUST be a power of two <= 1<<30. */ static final int MAXIMUM_CAPACITY = 1 << 30; /** * The load factor used when none specified in constructor. */ static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * The bin count threshold for using a tree rather than list for a * bin. Bins are converted to trees when adding an element to a * bin with at least this many nodes. The value must be greater * than 2 and should be at least 8 to mesh with assumptions in * tree removal about conversion back to plain bins upon * shrinkage. */ static final int TREEIFY_THRESHOLD = 8; /** * The bin count threshold for untreeifying a (split) bin during a * resize operation. Should be less than TREEIFY_THRESHOLD, and at * most 6 to mesh with shrinkage detection under removal. */ static final int UNTREEIFY_THRESHOLD = 6; /** * The smallest table capacity for which bins may be treeified. * (Otherwise the table is resized if too many nodes in a bin.) * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts * between resizing and treeification thresholds. */ static final int MIN_TREEIFY_CAPACITY = 64; /** * Holds cached entrySet(). Note that AbstractMap fields are used * for keySet() and values(). */ transient Set<Map.Entry<K,V>> entrySet; /** * The number of key-value mappings contained in this map. */ transient int size; /** * The number of times this HashMap has been structurally modified * Structural modifications are those that change the number of mappings in * the HashMap or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the HashMap fail-fast. (See ConcurrentModificationException). */ transient int modCount; int threshold; final float loadFactor;
注:transient是短暂的意思。对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。 因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化
总结:
反射hashmap核心还是反射其中hashmap的内部类node类,只要拿的到它,就能反射相应的元素
-
JAVA基础 接口与继承 HashMap使用
2018-11-29 09:08:05抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量 接口不可继承抽象类,抽象类可实现多个接口。接口与接口之间是继承,用...mport java.util.HashMap; import java.util.Map; interface T...https://blog.csdn.net/u010575093/article/details/50731281
抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量
接口不可继承抽象类,抽象类可实现多个接口。接口与接口之间是继承,用extends,可继承多个接口mport java.util.HashMap; import java.util.Map; interface Test{ public void mm(); } interface Test1{ public void kk(); } //接口可以继承多个接口 interface Test2 extends Test, Test1{ public void mk(); } //抽象类成员都是public, //抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。 //抽象类可以继承接口,并实现接口方法 abstract class ATest1 implements Test1{ public void kk(){ System.out.println("ATtest mm"); } } abstract class ATest2 implements Test1, Test{ public void mm(){ System.out.println("ATest2 mm"); } public void kk(){} } // 抽象类可以继承抽象类 也可以继承实体类 abstract class ATest3 extends ATest1{ } class Solution{ //时间复杂度n public void tosum(int[] nums, int target){ Map<Integer, Integer> map = new HashMap<>(); for(int i = 0; i < nums.length; i++) map.put(nums[i],i); for(int i = 0; i < nums.length; i++){ int comp = target - nums[i]; System.out.println("comp="+comp+" containsKey "+map.containsKey(comp)); System.out.println("map get "+map.get(comp)); if(map.containsKey(comp) && map.get(comp)!=i){ System.out.println("match:"+i+" "+map.get(comp)); } } System.out.println("tosum"); } //时间复杂度1 public int[] tosum1(int[] nums, int target){ Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } throw new IllegalArgumentException("No two sum solution"); } } class HashSum{ public static void main(String argv[]){ System.out.println("111"); new Solution().tosum(); } }
-
Java 关于hashmap的创建。
2021-02-27 20:53:30Java关于hashmap的创建:问题描述如下,有这样一个编程要求step1:创建类StudentJavaScore,实现comparable接口,包含两个字段intjavaScore记录java成绩,Stringname表示学生姓名,生成...Java 关于hashmap的创建:... -
继承HashMap导致的Json序列化问题
2021-04-11 19:49:53新建一个继承了HashMap的Bean @Data @EqualsAndHashCode(callSuper = true) public class R<T> extends HashMap<String,Object> implements Serializable { private T data; } 进行fastjson... -
【Java基础】HashMap的put方法
2021-04-06 16:07:42// hashMap底层存储结构 transient Node<K,V>[] table; // onlyIfAbsent- 如果为true,改变已存在的值(暂时还不太理解) // evict- 如果为false,表明该table目前是创建模式,看了下,目前仅发现有两个地方... -
Java中HashMap详解
2021-06-16 10:54:34HashMap的扩容 -
Java之hashMap遍历方式
2022-02-19 20:20:10在java开发中,hashMap是非常重要的容器类,存储的是键值对(key,value)。 HashMap继承AbstractMap,实现了Map、Cloneable、Serializable接口,非线程安全类,但是效率高。HashMap允许null健和null值,允许value重复... -
java中HashMap的用法
2021-03-14 13:55:33重点介绍HashMap。首先介绍一下什么是Map。在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。在下文中会有例子具体说明。再来... -
Java之HashMap和Hashtable
2022-04-15 14:00:01主要介绍Java中HashMap和Hashtable的区别。 -
Java的HashMap基本操作
2021-02-05 00:48:23HashMap 是一个散列表,它存储的内容是键值对(key-value)...HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。 HashMap类常用操作 方法 功能 描述 put() 将键/值对添加到 hash -
Java中HashMap和HashSet的知识点汇总
2022-03-30 14:31:54目录HashMap介绍HashSet介绍HashMap的一些特点HashMap的一些重要方法HashSet的一些特点HashSet的一些方法 ...HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。 HashSet介绍 HashSe -
Java语言里Hashmap序列化的一个坑
2021-02-12 17:34:01本文主要向大家介绍了Java语言里Hashmap序列化的一个...在一个继承了 Serializable 接口的java bean里按照常规操作添加了一个hashmap和与之对应的getter、setter,就像这样:...private HashMapmChooseMap;publicHas... -
Java中HashMap和HashTable的区别
2020-10-20 00:06:03HashMap是继承自AbstractMap类,而Hashtable是继承自Dictionary类。不过它们都实现了同时实现 了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。 2、对外提供的接口不同 Hashtable比HashMap多提供... -
java7hashmap源码-for-java:java学习笔记
2021-06-04 16:03:41hashmap源码 Java学习笔记 Effective Java Topic2:插件销毁对象 2. 多参数情况 使用重叠构造器; 使用Build模式【构建器】: new A.Build().set.set.build(); Build模式也适用于类层次结构 递归类型参数 /* * 递归... -
【Java】HashMap原理及相关面试题
2022-01-03 13:07:16HashMap与Hashtable两个类都是通过Key-Value对存储的数据结构。...由于Hashtable效率较低,所以Java官方不建议使用这个类了;单线程的情况下使用HashMap,多线程的时候使用ConcurrentHashMap。 一、数据结构 1. 结构 H -
Java HashMap基本用法
2022-01-18 12:08:47HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。...HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。 // 创建 HashMap 对象 Sites HashMap<Integer, Strin -
java7hashmap源码-JavaInterview:Java面试汇总
2021-06-04 16:06:48hashmap源码 『Java面试』 - - - - - - - - - - - - - - - - - 基础篇 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 3、与平台无关性(JVM是... -
Java中的HashMap详解
2020-01-10 17:48:50HashMap继承了AbstractMap,实现了Map接口,存储的是一个键值对对象。 二、HashMap数据结构解析 1、继承关系:HashMap继承了AbstractMap,实现了Map接口。 public abstract class AbstractMap<K,V> implements... -
Java HashMap使用方法教程及示例代码
2021-02-27 20:52:381、Java HashMapHashMap 是一个散列表,它存储的内容是键值对(key-value)映射。HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的...HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.... -
【Java_基础深入】LinkedHashMap 继承 HashMap又实现 Map 接口背后的设计思想
2020-03-08 14:06:26public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable public class LinkedHashMap<K,V> extends HashMap<K,V> implements... -
Java HashMap
2020-11-17 23:35:231.HashMap 是一个散列表,它存储的内容是键值对(key-value)映射...4.HashMap 继承于AbstractMap,实现了 Map、Cloneable java.io.Serializable 接口。 5.HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符 -
Java集合- HashMap 和 TreeMap 的区别
2022-02-01 16:10:38HashMap通过hashcode对其内容进行快速查找(哈希表通过把关键码值映射到表中一个位置来访问记录,不需比较便可直接取得所查记录,加快了查找的速度)。 而 TreeMap中所有的元素都保持着某种固定的顺序,如果... -
java7hashmap源码-JavaInterview:适用于Java面试的文档
2021-06-04 16:05:17hashmap源码 JavaInterview - - - - - - - - - - - - - - - - - 基础篇 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 3、与平台无关性(JVM是... -
java HashMap与TreeMap总结
2021-04-06 22:12:571、HashMap简介 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射... HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。 HashMap 类位于 java.util 包中,使用前需要引入它. -
java中的HashMap用法总结
2020-11-23 20:40:45二、Java HashMap 常用方法代码示例总结 前言 HashMap学习笔记 一、HashMap是什么? HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,... -
一张图看懂java HashMap继承关系
2018-08-05 12:34:20这是JDK1.8.0_151下的HashMap类定义: public class HashMap<K,V> extends AbstractMap<K,V> implements Map&...根据类定义,追根刨底,看看HashMap的继承结构图: ...