java入门,JSONObject实现源码解析

一、前言

现在写java程序,很少需要写一些底层的数据结构和算法,因为这些轮子早已造好,拿来用就行。比如在代码中我们经常用到的这个类JSONObject ,还有我们经常使用的String类型,它都是有底层实现的,我们直接引用别人开发的java包就行了,无需要关心它是如何实现的, 所以平时开发其实对于底层的东西了解越来越少,这一节就分析一下JSONObject的源码,看它是如何实现的。

二、JSONObject源码


package com.alibaba.fastjson;import static com.alibaba.fastjson.util.TypeUtils.castToBigDecimal;
import static com.alibaba.fastjson.util.TypeUtils.castToBigInteger;
import static com.alibaba.fastjson.util.TypeUtils.castToBoolean;
import static com.alibaba.fastjson.util.TypeUtils.castToByte;
import static com.alibaba.fastjson.util.TypeUtils.castToBytes;
import static com.alibaba.fastjson.util.TypeUtils.castToDate;
import static com.alibaba.fastjson.util.TypeUtils.castToDouble;
import static com.alibaba.fastjson.util.TypeUtils.castToFloat;
import static com.alibaba.fastjson.util.TypeUtils.castToInt;
import static com.alibaba.fastjson.util.TypeUtils.castToLong;
import static com.alibaba.fastjson.util.TypeUtils.castToShort;
import static com.alibaba.fastjson.util.TypeUtils.castToSqlDate;
import static com.alibaba.fastjson.util.TypeUtils.castToTimestamp;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler {private static final long         serialVersionUID         = 1L;private static final int          DEFAULT_INITIAL_CAPACITY = 16;private final Map<String, Object> map;public JSONObject(){this(DEFAULT_INITIAL_CAPACITY, false);}public JSONObject(Map<String, Object> map){if (map == null) {throw new IllegalArgumentException("map is null.");}this.map = map;}public JSONObject(boolean ordered){this(DEFAULT_INITIAL_CAPACITY, ordered);}public JSONObject(int initialCapacity){this(initialCapacity, false);}public JSONObject(int initialCapacity, boolean ordered){if (ordered) {map = new LinkedHashMap<String, Object>(initialCapacity);} else {map = new HashMap<String, Object>(initialCapacity);}}public int size() {return map.size();}public boolean isEmpty() {return map.isEmpty();}public boolean containsKey(Object key) {boolean result = map.containsKey(key);if (!result) {if (key instanceof Number|| key instanceof Character|| key instanceof Boolean|| key instanceof UUID) {result = map.containsKey(key.toString());}}return result;}public boolean containsValue(Object value) {return map.containsValue(value);}public Object get(Object key) {Object val = map.get(key);if (val == null) {if (key instanceof Number|| key instanceof Character|| key instanceof Boolean|| key instanceof UUID) {val = map.get(key.toString());}}return val;}public Object getOrDefault(Object key, Object defaultValue) {Object v;return ((v = get(key)) != null) ? v : defaultValue;}public JSONObject getJSONObject(String key) {Object value = map.get(key);if (value instanceof JSONObject) {return (JSONObject) value;}if (value instanceof Map) {return new JSONObject((Map) value);}if (value instanceof String) {return JSON.parseObject((String) value);}return (JSONObject) toJSON(value);}public JSONArray getJSONArray(String key) {Object value = map.get(key);if (value instanceof JSONArray) {return (JSONArray) value;}if (value instanceof List) {return new JSONArray((List) value);}if (value instanceof String) {return (JSONArray) JSON.parse((String) value);}return (JSONArray) toJSON(value);}public <T> T getObject(String key, Class<T> clazz) {Object obj = map.get(key);return TypeUtils.castToJavaBean(obj, clazz);}public <T> T getObject(String key, Type type) {Object obj = map.get(key);return TypeUtils.cast(obj, type, ParserConfig.getGlobalInstance());}public <T> T getObject(String key, TypeReference typeReference) {Object obj = map.get(key);if (typeReference == null) {return (T) obj;}return TypeUtils.cast(obj, typeReference.getType(), ParserConfig.getGlobalInstance());}public Boolean getBoolean(String key) {Object value = get(key);if (value == null) {return null;}return castToBoolean(value);}public byte[] getBytes(String key) {Object value = get(key);if (value == null) {return null;}return castToBytes(value);}public boolean getBooleanValue(String key) {Object value = get(key);Boolean booleanVal = castToBoolean(value);if (booleanVal == null) {return false;}return booleanVal.booleanValue();}public Byte getByte(String key) {Object value = get(key);return castToByte(value);}public byte getByteValue(String key) {Object value = get(key);Byte byteVal = castToByte(value);if (byteVal == null) {return 0;}return byteVal.byteValue();}public Short getShort(String key) {Object value = get(key);return castToShort(value);}public short getShortValue(String key) {Object value = get(key);Short shortVal = castToShort(value);if (shortVal == null) {return 0;}return shortVal.shortValue();}public Integer getInteger(String key) {Object value = get(key);return castToInt(value);}public int getIntValue(String key) {Object value = get(key);Integer intVal = castToInt(value);if (intVal == null) {return 0;}return intVal.intValue();}public Long getLong(String key) {Object value = get(key);return castToLong(value);}public long getLongValue(String key) {Object value = get(key);Long longVal = castToLong(value);if (longVal == null) {return 0L;}return longVal.longValue();}public Float getFloat(String key) {Object value = get(key);return castToFloat(value);}public float getFloatValue(String key) {Object value = get(key);Float floatValue = castToFloat(value);if (floatValue == null) {return 0F;}return floatValue.floatValue();}public Double getDouble(String key) {Object value = get(key);return castToDouble(value);}public double getDoubleValue(String key) {Object value = get(key);Double doubleValue = castToDouble(value);if (doubleValue == null) {return 0D;}return doubleValue.doubleValue();}public BigDecimal getBigDecimal(String key) {Object value = get(key);return castToBigDecimal(value);}public BigInteger getBigInteger(String key) {Object value = get(key);return castToBigInteger(value);}public String getString(String key) {Object value = get(key);if (value == null) {return null;}return value.toString();}public Date getDate(String key) {Object value = get(key);return castToDate(value);}public Object getSqlDate(String key) {Object value = get(key);return castToSqlDate(value);}public Object getTimestamp(String key) {Object value = get(key);return castToTimestamp(value);}public Object put(String key, Object value) {return map.put(key, value);}public JSONObject fluentPut(String key, Object value) {map.put(key, value);return this;}public void putAll(Map<? extends String, ?> m) {map.putAll(m);}public JSONObject fluentPutAll(Map<? extends String, ?> m) {map.putAll(m);return this;}public void clear() {map.clear();}public JSONObject fluentClear() {map.clear();return this;}public Object remove(Object key) {return map.remove(key);}public JSONObject fluentRemove(Object key) {map.remove(key);return this;}public Set<String> keySet() {return map.keySet();}public Collection<Object> values() {return map.values();}public Set<Map.Entry<String, Object>> entrySet() {return map.entrySet();}@Overridepublic JSONObject clone() {return new JSONObject(map instanceof LinkedHashMap //? new LinkedHashMap<String, Object>(map) //: new HashMap<String, Object>(map));}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj instanceof JSONObject) {return this.map.equals(((JSONObject) obj).map);}return this.map.equals(obj);}@Overridepublic int hashCode() {return this.map.hashCode();}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Class<?>[] parameterTypes = method.getParameterTypes();if (parameterTypes.length == 1) {if (method.getName().equals("equals")) {return this.equals(args[0]);}Class<?> returnType = method.getReturnType();if (returnType != void.class) {throw new JSONException("illegal setter");}String name = null;JSONField annotation = TypeUtils.getAnnotation(method, JSONField.class);if (annotation != null) {if (annotation.name().length() != 0) {name = annotation.name();}}if (name == null) {name = method.getName();if (!name.startsWith("set")) {throw new JSONException("illegal setter");}name = name.substring(3);if (name.length() == 0) {throw new JSONException("illegal setter");}name = Character.toLowerCase(name.charAt(0)) + name.substring(1);}map.put(name, args[0]);return null;}if (parameterTypes.length == 0) {Class<?> returnType = method.getReturnType();if (returnType == void.class) {throw new JSONException("illegal getter");}String name = null;JSONField annotation = TypeUtils.getAnnotation(method, JSONField.class);if (annotation != null) {if (annotation.name().length() != 0) {name = annotation.name();}}if (name == null) {name = method.getName();if (name.startsWith("get")) {name = name.substring(3);if (name.length() == 0) {throw new JSONException("illegal getter");}name = Character.toLowerCase(name.charAt(0)) + name.substring(1);} else if (name.startsWith("is")) {name = name.substring(2);if (name.length() == 0) {throw new JSONException("illegal getter");}name = Character.toLowerCase(name.charAt(0)) + name.substring(1);} else if (name.startsWith("hashCode")) {return this.hashCode();} else if (name.startsWith("toString")) {return this.toString();} else {throw new JSONException("illegal getter");}}Object value = map.get(name);return TypeUtils.cast(value, method.getGenericReturnType(), ParserConfig.getGlobalInstance());}throw new UnsupportedOperationException(method.toGenericString());}public Map<String, Object> getInnerMap() {return this.map;}private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {SecureObjectInputStream.ensureFields();if (SecureObjectInputStream.fields != null && !SecureObjectInputStream.fields_error) {ObjectInputStream secIn = new SecureObjectInputStream(in);try {secIn.defaultReadObject();return;} catch (java.io.NotActiveException e) {// skip}}in.defaultReadObject();for (Entry entry : map.entrySet()) {final Object key = entry.getKey();if (key != null) {ParserConfig.global.checkAutoType(key.getClass());}final Object value = entry.getValue();if (value != null) {ParserConfig.global.checkAutoType(value.getClass());}}}static class SecureObjectInputStream extends ObjectInputStream {static Field[] fields;static volatile boolean fields_error;static void ensureFields() {if (fields == null && !fields_error) {try {final Field[] declaredFields = ObjectInputStream.class.getDeclaredFields();String[] fieldnames = new String[]{"bin", "passHandle", "handles", "curContext"};Field[] array = new Field[fieldnames.length];for (int i = 0; i < fieldnames.length; i++) {Field field = TypeUtils.getField(ObjectInputStream.class, fieldnames[i], declaredFields);field.setAccessible(true);array[i] = field;}fields = array;} catch (Throwable error) {fields_error = true;}}}public SecureObjectInputStream(ObjectInputStream in) throws IOException {super(in);try {for (int i = 0; i < fields.length; i++) {final Field field = fields[i];final Object value = field.get(in);field.set(this, value);}} catch (IllegalAccessException e) {fields_error = true;}}protected Class<?> resolveClass(ObjectStreamClass desc)throws IOException, ClassNotFoundException {String name = desc.getName();if (name.length() > 2) {int index = name.lastIndexOf('[');if (index != -1) {name = name.substring(index + 1);}if (name.length() > 2 && name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';') {name = name.substring(1, name.length() - 1);}if (TypeUtils.getClassFromMapping(name) == null) {ParserConfig.global.checkAutoType(name, null, Feature.SupportAutoType.mask);}}return super.resolveClass(desc);}protected Class<?> resolveProxyClass(String[] interfaces)throws IOException, ClassNotFoundException {for (String interfacename : interfaces) {//检查是否处于黑名单if (TypeUtils.getClassFromMapping(interfacename) == null) {ParserConfig.global.checkAutoType(interfacename, null);}}return super.resolveProxyClass(interfaces);}//Hack:默认构造方法会调用这个方法,重写此方法使用反射还原部分关键属性protected void readStreamHeader() throws IOException, StreamCorruptedException {}}public <T> T toJavaObject(Class<T> clazz) {if (clazz == Map.class || clazz == JSONObject.class || clazz == JSON.class) {return (T) this;}if (clazz == Object.class && !containsKey(JSON.DEFAULT_TYPE_KEY)) {return (T) this;}return TypeUtils.castToJavaBean(this, clazz, ParserConfig.getGlobalInstance());}public <T> T toJavaObject(Class<T> clazz, ParserConfig config, int features) {if (clazz == Map.class) {return (T) this;}if (clazz == Object.class && !containsKey(JSON.DEFAULT_TYPE_KEY)) {return (T) this;}return TypeUtils.castToJavaBean(this, clazz, config);}
}

代码量还是很多,还没包含其他第三方引用的源码。

接下来我们一步步看

1、首先定义了这个类型:

public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler

2、我们看它的构造方法

    public JSONObject(){this(DEFAULT_INITIAL_CAPACITY, false);}public JSONObject(Map<String, Object> map){if (map == null) {throw new IllegalArgumentException("map is null.");}this.map = map;}public JSONObject(boolean ordered){this(DEFAULT_INITIAL_CAPACITY, ordered);}public JSONObject(int initialCapacity){this(initialCapacity, false);}public JSONObject(int initialCapacity, boolean ordered){if (ordered) {map = new LinkedHashMap<String, Object>(initialCapacity);} else {map = new HashMap<String, Object>(initialCapacity);}}

粗略看一下,JSONObject的下一层大概就是hashMap来实现的。

    private static final long         serialVersionUID         = 1L;
    private static final int          DEFAULT_INITIAL_CAPACITY = 16;

DEFAULT_INITIAL_CAPACITY我们知道HasMap在构造JSONObject分配内存空间时 初始化是16

3、接下里的类里封装的方法都是map的方法

判断大小,判空,获取key等

   public int size() {return map.size();}public boolean isEmpty() {return map.isEmpty();}public boolean containsKey(Object key) {boolean result = map.containsKey(key);if (!result) {if (key instanceof Number|| key instanceof Character|| key instanceof Boolean|| key instanceof UUID) {result = map.containsKey(key.toString());}}return result;}public boolean containsValue(Object value) {return map.containsValue(value);}public Object get(Object key) {Object val = map.get(key);if (val == null) {if (key instanceof Number|| key instanceof Character|| key instanceof Boolean|| key instanceof UUID) {val = map.get(key.toString());}}return val;}

从这个方法我们可以看出,就是从HashMap转化过来的

   public JSONObject getJSONObject(String key) {Object value = map.get(key);if (value instanceof JSONObject) {return (JSONObject) value;}if (value instanceof Map) {return new JSONObject((Map) value);}if (value instanceof String) {return JSON.parseObject((String) value);}return (JSONObject) toJSON(value);}

三、封装的方法:

 

功能非常多,以至于源码就10000多行。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/157675.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django 社区志愿者管理系统

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 社区志愿者服务管理系统&#xff0c;主要的模块包括查看首页、个人中心、通知公告管理、志愿者管理、普通管理员管理、志愿活动管理、活动宣…

【数据结构】单向链表的增删查改以及指定pos位置的插入删除

目录 单向链表的概念及结构 尾插 头插 尾删 ​编辑 头删 查找 在pos位置前插 在pos位置后插 删除pos位置 删除pos的后一个位置 总结 代码 单向链表的概念及结构 概念&#xff1a;链表是一种 物理存储结构上非连续 、非顺序的存储结构&#xff0c;数据元素的 逻辑顺序 是…

笔记本电脑搜索不到wifi6 无线路由器信号

路由器更换成wifi6 无线路由器后&#xff0c;手机能搜索到这个无线信号&#xff0c;但是笔记本搜索不到这个无线信号&#xff0c;后网上搜索后发现是无线网卡驱动问题&#xff0c;很多无线网卡使用的是Intel芯片&#xff0c;Intel就此发布了公告&#xff0c;升级驱动就可以彻底…

设置防火墙

1.RHEL7中的防火墙类型 防火墙只能同时使用一张,firewall底层调用的还是lptables的服务: firewalld:默认 &#xff0c;基于不同的区域做规则 iptables: RHEL6使用&#xff0c;基于链表 Ip6tables Ebtables 2.防火墙的配置方式 查看防火墙状态: rootlinuxidc -]#systemct…

每日一练 | 网络工程师软考真题Day47

阅读以下关于Linux文件系统和Samba效劳的说明&#xff0c;答复以下【问题1】至【问题3】。 【说明】 Linux系统采用了树型多级目录来管理文件&#xff0c;树型结构的最上层是根目录&#xff0c;其他的所有目录都是从根目录生成的。通过Samba可以实现基于Linux操作系统的效劳器和…

【解锁未来】探索Web3的无限可能-02

文章目录 什么是Web3 &#xff1f;Web3对公司的意义&#xff1f; 什么是Web3 &#xff1f; 简单地说&#xff0c;Web3 是加密货币的延伸&#xff0c;它以新的方式使用区块链来达到新的目的。区块链可以存储钱包中代币的数量、自我执行合同的条款或去中心化应用程序&#xff08;…

【Proteus仿真】【51单片机】贪吃蛇游戏

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用8*8LED点阵、按键模块等。 主要功能&#xff1a; 系统运行后&#xff0c;可操作4个按键控制小蛇方向。 二、软件设计 /* 作者&#xff1a;嗨小易…

0基础学习PyFlink——时间滑动窗口(Sliding Time Windows)

在《0基础学习PyFlink——时间滚动窗口(Tumbling Time Windows)》我们介绍了不会有重复数据的时间滚动窗口。本节我们将介绍存在重复计算数据的时间滑动窗口。 关于滑动窗口&#xff0c;可以先看下《0基础学习PyFlink——个数滑动窗口&#xff08;Sliding Count Windows&#x…

IDEA 设置代码注释模板

功能简介&#xff1a; 每次看别人代码时&#xff0c;面对毫无注释的类&#xff0c;除了头大还是头大&#xff0c; 以下提供了一种代码类注释模板 新建java类的时候&#xff0c;自动增加类注释&#xff0c;养成代码开发好习惯 效果展示&#xff1a; 代码模板&#xff1a; #if (…

9.MySQL索引的操作

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 索引操作 查询索引 创建主键索引 唯一索引的创建 普通索引的创建 全文索引的创建 删除索引 索引创建原则 索引操作 查询索引 第一种方法&#xff1a; show keys from 表名\G 我们了解其中几个就好。 第二种方法…

半方差函数详解

1 引言 托布勒的地理第一定律指出&#xff0c;“一切都与其他事物有关&#xff0c;但近处的事物比远处的事物更相关。 在半变异函数的情况下&#xff0c;更接近的事物更可预测&#xff0c;变异性更小&#xff0c;而遥远的事物则难以预测&#xff0c;相关性也较低。 例如&…

零基础Linux_25(多线程)信号量+基于环形队列的生产消费模型+自选锁+读写锁

目录 1. 信号量 1.1 信号量和信号量操作的概念 1.2 信号量的基本使用接口 2. 基于环形队列的生产者消费者模型 2.1 环形队列再分析 2.2 代码分步实现 sem.hpp ringQueue.hpp testMain.cc 2.3 代码解析和再理解 3. 自旋锁和读写锁 3.1 自旋锁的概念和接口 3.2 读写…