第一章 JacksonUtil 序列化与反序列化属性总结
1.json-lib与Jackson
关于json-lib与Jackson对比总结如下:
1).性能方面,Jackson的处理能力高出Json-lib10倍左右。
2).json-lib已经停止更新,最新的版本也是基于JDK1.5,而Jackson的社区则较为活跃。
3).json-lib依赖commons系列的包及 ezmorph包共 5个,而Jackson除自身的以外只依赖于commons-logging
2.1 Jackson序列化与反序列化方法
- 1 public static String encode(Object obj) {
- 2 try {
- 3 return objectMapper.writeValueAsString(obj);
- 4 } catch (Exception e) {
- 5 logger.error("jackson encode error:", e);
- 6 }
- 7 return null;
- 8 }
- 9
- 10 /**
- 11 * 将json string反序列化成对象
- 12 *
- 13 * @param json
- 14 * @param valueType
- 15 * @return
- 16 */
- 17 public static <T> T decode(String json, Class<T> valueType) {
- 18 try {
- 19 return objectMapper.readValue(json, valueType);
- 20 } catch (Exception e) {
- 21 logger.error("jackson decode(String, Class<T>) error: ", e);
- 22 }
- 23 return null;
- 24 }
- 25
- 26 /**
- 27 * 将json array反序列化为对象
- 28 *
- 29 * @param json
- 30 * @param typeReference
- 31 * @return
- 32 */
- 33 public static <T> T decode(String json, TypeReference<T> typeReference) {
- 34 try {
- 35 return (T) objectMapper.readValue(json, typeReference);
- 36 } catch (Exception e) {
- 37 logger.error("decode(String, JsonTypeReference<T>)", e);
- 38 }
- 39 return null;
- 40 }
2.2 Jackson自动检测机制
jackson默认的字段属性发现规则如下:
所有被public修饰的字段->所有被public修饰的getter->所有被public修饰的setter
若类中的一个private属性,且没有设置public的getter和setter方法,则对该类对象进行序列化时,默认不对这个private属性进行序列化。
若此时任然需要对该private属性进行序列化,可以通过设置自动检测功能来实现:
2.2.1 通过配置属性实现
- 1 objectMapper
- 2 .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) // 自动检测所有类的全部属性
- 3 .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) //自动检测所有类的public getter方法
- 4 .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY); //自动检测所有类的public setter方法
2.2.2 使用@JsonAutoDetect(作用在类上)来开启/禁止自动检测
fieldVisibility:字段的可见级别
ANY:任何级别的字段都可以自动识别
NONE:所有字段都不可以自动识别
NON_PRIVATE:非private修饰的字段可以自动识别
PROTECTED_AND_PUBLIC:被protected和public修饰的字段可以被自动识别
PUBLIC_ONLY:只有被public修饰的字段才可以被自动识别
DEFAULT:同PUBLIC_ONLY
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
3.序列化与反序列化属性总结
与json-lib相比,Jackson在序列化与反序列时,可以对序列化与反序列化进行配置,是的输出结果满足自己的要求。序列化与反序列化属性很多,下面对一些常用属性进行介绍。
3.1 序列化属性
- //这个特性,决定了解析器是否将自动关闭那些不属于parser自己的输入源。
- // 如果禁止,则调用应用不得不分别去关闭那些被用来创建parser的基础输入流InputStream和reader;
- //默认是true
- objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
- //是否允许解析使用Java/C++ 样式的注释(包括'/'+'*' 和'//' 变量)
- objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
- //设置为true时,属性名称不带双引号
- objectMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
- //反序列化是是否允许属性名称不带双引号
- objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
- //是否允许单引号来包住属性名称和字符串值
- objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
- //是否允许JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符和换行符)
- objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
- //是否允许JSON整数以多个0开始
- objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
- //null的属性不序列化
- objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
- //按字母顺序排序属性,默认false
- objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);
- //是否以类名作为根元素,可以通过@JsonRootName来自定义根元素名称,默认false
- objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);
- //是否缩放排列输出,默认false
- objectMapper.configure(SerializationFeature.INDENT_OUTPUT,false);
- //序列化Date日期时以timestamps输出,默认true
- objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true);
- //序列化枚举是否以toString()来输出,默认false,即默认以name()来输出
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
- //序列化枚举是否以ordinal()来输出,默认false
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false);
- //序列化单元素数组时不以数组来输出,默认false
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
- //序列化Map时对key进行排序操作,默认false
- objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);
- //序列化char[]时以json数组输出,默认false
- objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
- //序列化BigDecimal时是输出原始数字还是科学计数,默认false,即以toPlainString()科学计数方式来输出
- objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,true);
下面写一个Person类,对上面介绍的序列化属性进行测试,并进行直观输出:
- 1 import com.fasterxml.jackson.annotation.JsonRootName;
- 2 import org.apache.commons.lang3.StringUtils;
- 3 import java.util.Date;
- 4
- 5
- 6 @JsonRootName("Test")
- 7 public class Person {
- 8 // @JsonInclude(JsonInclude.Include.NON_NULL)
- 9 private String name;
- 10
- 11 private int age;
- 12
- 13 private SexEnum sex;
- 14
- 15 private Date birthDay;
- 16
- 17 public enum SexEnum{
- 18 MAN("M", "m"),
- 19 WOMAN("F", "f");
- 20
- 21 private String merchantCode;
- 22 private String nativeCode;
- 23
- 24 SexEnum(String merchantCode, String nativeCode) {
- 25 this.merchantCode = merchantCode;
- 26 this.nativeCode = nativeCode;
- 27 }
- 28
- 29 public String getMerchantCode() {
- 30 return merchantCode;
- 31 }
- 32
- 33 public void setMerchantCode(String merchantCode) {
- 34 this.merchantCode = merchantCode;
- 35 }
- 36
- 37 public String getNativeCode() {
- 38 return nativeCode;
- 39 }
- 40
- 41 public void setNativeCode(String nativeCode) {
- 42 this.nativeCode = nativeCode;
- 43 }
- 44
- 45 @Override
- 46 public String toString() {
- 47 return getMerchantCode();
- 48 }
- 49
- 50 public Person() {
- 51 }
- 52
- 53 public Person(String name, int age) {
- 54 this.name = name;
- 55 this.age = age;
- 56 }
- 57
- 58 public String getName() {
- 59 return name;
- 60 }
- 61
- 62 public void setName(String name) {
- 63 this.name = name;
- 64 }
- 65
- 66 public int getAge() {
- 67 return age;
- 68 }
- 69
- 70 public void setAge(int age) {
- 71 this.age = age;
- 72 }
- 73
- 74 public SexEnum getSex() {
- 75 return sex;
- 76 }
- 77
- 78 public void setSex(SexEnum sex) {
- 79 this.sex = sex;
- 80 }
- 81
- 82 public Date getBirthDay() {
- 83 return birthDay;
- 84 }
- 85
- 86 public void setBirthDay(Date birthDay) {
- 87 this.birthDay = birthDay;
- 88 }
- 89 }
下面是测试类:
- 1 import com.alibaba.fastjson.JSONObject;
- 2 import com.example.myFirstProject.domain.Person;
- 3 import com.example.myFirstProject.util.JacksonUtil;
- 4 import org.joda.time.DateTime;
- 5 import java.math.BigDecimal;
- 6 import java.util.ArrayList;
- 7 import java.util.Date;
- 8 import java.util.List;
- 9 import static com.example.myFirstProject.domain.Person.SexEnum;
- 10 import static com.example.myFirstProject.domain.Person.SexEnum.MAN;
- 11
- 12
- 13 /**
- 14 * Created by bjxiaojian on 2016/10/26.
- 15 */
- 16 public class JacksonTest {
- 17
- 18 public static void main(String[] args) {
- 19
- 20 Person person = new Person();
- 21
- 22 Person person1 = new Person("xiaojian", 1);
- 23 person1.setSex(MAN);
- 24 person1.setBirthDay(new Date());
- 25 List personList = new ArrayList();
- 26 personList.add(person);
- 27 personList.add(person1);
- 28 System.out.println(JacksonUtil.encode(person));
- 29 System.out.println(JacksonUtil.encode(person1));
- 30 System.out.println(JacksonUtil.encode(personList));
- 31
- 32 }
- 33 }
- 34
- 35
- 36 ---------------------------------输出结果--------------------------------------------
- 37 {"Test":{"age":0}} null的属性不进行序列化
- 38 {"Test":{"age":1,"birthDay":1477661674628,"name":"xiaojian","sex":"M"}} date类型的输出为时间戳,枚举类的输出默认为MAN或WOMAN,设置后为SexEnum的toString()的返回值
- 39 {"ArrayList":[{"age":0},{"age":1,"birthDay":1477661674628,"name":"xiaojian","sex":"M"}]}
3.2 反序列化属性
- 1 //当遇到未知属性(没有映射到属性,没有任何setter或者任何可以处理它的handler,是否应该抛出JsonMappingException异常
- 2 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- 3 //该特性决定对于json浮点数,是否使用BigDecimal来序列化。如果不允许,则使用Double序列化。 默认为false
- 4 objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, false);
- 5 //该特性决定对于json整形(非浮点),是否使用BigInteger来序列化。如果不允许,则根据数值大小来确定 是使用Integer或者Long
- 6 objectMapper.configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, false);
- 7 //该特性决定JSON ARRAY是映射为Object[]还是List<Object>。如果开启,都为Object[],false时,则使用List 默认为false
- 8 objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, false);
- 9 //是否使用Enum.toString()的值对json string进行反序列化。这个的设置和WRITE_ENUMS_USING_TO_STRING需要一致。
- 10 objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
3.3 Jackson序列化和反序列化注解
上面的配置是针对所有类的反序列化的设置,下面介绍针对某个类的属性和方法的反序列化的注解:
1. @JsonIgnore:作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性。
2.@JsonProperty:作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名。
对属性添加了@JsonProperty注解后,即使该属性为private且没有getter和setter方法,也会进行序列化。
3.@JsonIgnoreProperties
作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉,可以将它看做是@JsonIgnore的批量操作,它还有一个重要的功能是作用在反序列化时解析字段时过滤一些未知的属性,否则通常情况下解析到我们定义的类不认识的属性便会抛出异常。
可以注明是想要忽略的属性列表如@JsonIgnoreProperties({"name","age","title"}),
也可以注明过滤掉未知的属性如@JsonIgnoreProperties(ignoreUnknown=true)
4、@JsonUnwrapped作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象。示例如下:
- public void jsonUnwrapped() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setId(111);
- TestName testName = new TestName();
- testName.setFirstName("张");
- testName.setSecondName("三");
- testPOJO.setName(testName);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- //如果没有@JsonUnwrapped,序列化后将为{"id":111,"name":{"firstName":"张","secondName":"三"}}
- //因为在name属性上加了@JsonUnwrapped,所以name的子属性firstName和secondName将不会包含在name中。
- Assert.assertEquals("{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}",jsonStr);
- String jsonStr2 = "{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);
- Assert.assertEquals(111,testPOJO2.getId());
- Assert.assertEquals("张",testPOJO2.getName().getFirstName());
- Assert.assertEquals("三",testPOJO2.getName().getSecondName());
- }
- public static class TestPOJO{
- private int id;
- @JsonUnwrapped
- private TestName name;
- //getters、setters省略
- }
- public static class TestName{
- private String firstName;
- private String secondName;
- //getters、setters省略
- }
5.@JsonSerialize和@JsonDeserialize:作用于方法和字段上,通过 using(JsonSerializer)和using(JsonDeserializer)来指定序列化和反序列化的实现。下面的例子中自定义了日期的序列化和反序列化方式,可以将Date和指定日期格式字符串之间相互转换。
- @JsonSerialize(using = MyDateSerializer.class)
- @JsonDeserialize(using = MyDateDeserializer.class)
- private Date birthday;
6.@JsonPropertyOrder:作用在类上,被用来指明当序列化时需要对属性做排序。@jsonPropertyOrder(alphabetic = true)
7.@JsonView:视图模板,作用于方法和属性上,用来指定哪些属性可以被包含在JSON视图中,在前面我们知道已经有@JsonIgnore和@JsonIgnoreProperties可以排除过滤掉不需要序列化的属性,可是如果一个POJO中有h很多个属性,而我们可能只需要概要简单信息即序列化时只想输出其中几个属性,此时使用@JsonIgnore和@JsonIgnoreProperties就显得非常繁琐,而使用@JsonView便会非常方便,只许在你想要输出的属性(或对应的getter)上添加@JsonView即可。
- @Test
- public void jsonView() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
- String jsonStr = objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO);
- Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\"}",jsonStr);
- String jsonStr2 = objectMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO);
- Assert.assertEquals("{\"d\":\"4\",\"b\":\"2\"}",jsonStr2);
- }
- public static class TestPOJO{
- @JsonView(FilterView.OutputA.class)
- private String a;
- @JsonView(FilterView.OutputA.class)
- private String c;
- @JsonView(FilterView.OutputB.class)
- private String d;
- @JsonView(FilterView.OutputB.class)
- private String b;
- //getters、setters忽略
- }
- private static class FilterView {
- static class OutputA {}
- static class OutputB {}
- }
8.@JsonFilter:Json属性过滤器,作用于类,作用同上面的@JsonView,都是过滤掉不想要的属性,输出自己想要的属性。和@FilterView不同的是@JsonFilter可以动态的过滤属性。eg:
- @Test
- public void jsonFilter() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));
- objectMapper.setFilters(filters);
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"a\":\"1\"}",jsonStr);
- }
- @JsonFilter("myFilter")
- public static class TestPOJO{
- private String a;
- private String c;
- private String d;
- private String b;
- //getters、setters省略
- }
定义了一个名为myFilter的SimpleFilterProvider,这个过滤器将会过滤掉所有除a属性以外的属性。
9.@JsonAnySetter:作用于方法,在反序列化时用来处理遇到未知的属性的时候调用,在本文前面我们知道可以通过注解@JsonIgnoreProperties(ignoreUnknown=true)来过滤未知的属性,但是如果需要这些未知的属性该如何是好?那么@JsonAnySetter就可以派上用场了,它通常会和map属性配合使用用来保存未知的属性,
- @Test
- public void jsonAnySetter() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"name\":\"myName\",\"code\":\"12345\",\"age\":12}";
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("myName",testPOJO.getName());
- Assert.assertEquals("12345",testPOJO.getOther().get("code"));
- Assert.assertEquals(12,testPOJO.getOther().get("age"));
- }
- public static class TestPOJO{
- private String name;
- private Map other = new HashMap();
- @JsonAnySetter
- public void set(String name,Object value) {
- other.put(name,value);
- }
- //getters、setters省略
- }
3.4 Jackson序列化设置DateTime的输出格式:
simpleModule.addSerializer(new JodaDateSerializer(DateTime.class));
JodaDateSerializer类的代码如下:
- public class JodaDateSerializer extends StdSerializer<DateTime> {
- private static final Logger logger = LoggerFactory.getLogger(JodaDateSerializer.class);
- protected JodaDateSerializer(Class<DateTime> t) {
- super(t);
- }
- @Override
- public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
- if ( value == null ) {
- jgen.writeString("null");
- } else {
- try {
- //DateTimeUtils是自己定义的进行DateTime和各种String格式转换的工具类
- String str = DateTimeUtils.fmtYyyyMMddHHmmss(value);
- jgen.writeString(str);
- } catch (Exception e) {
- logger.error("joda serialize error: ", e);
- jgen.writeString("unknown");
- }
- }
- }
- }
DateTimeUtils是自己定义的进行DateTime和各种String格式转换的工具类,代码见 第二章 DateTime工具类
参考博客:http://blog.csdn.net/sdyy321/article/details/40298081#t30
第一章 JacksonUtil 序列化与反序列化属性总结的更多相关文章
- c# XML序列化与反序列化 属性字段标识
序列化对象 public class People { [XmlAttribute("NAME")] public string Name { set; get; } [XmlAt ...
- 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变
在net中json序列化与反序列化 准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...
- C#: .net序列化及反序列化 [XmlElement(“节点名称”)] [XmlAttribute(“节点属性”)] (上篇)
.net序列化及反序列化 序列化是指一个对象的实例可以被保存,保存成一个二进制串,当然,一旦被保存成二进制串,那么也可以保存成文本串了.比如,一个计数器,数值为2,我们可以用字符串"2&qu ...
- C#: .net序列化及反序列化 [XmlElement(“节点名称”)] [XmlAttribute(“节点属性”)] (下篇)
介绍 XML 序列化 .NET Framework 开发员指南 序列化是将对象转换为容易传输的格式的过程.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间 ...
- .net MVC 使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错,字符串的长度超过了为 maxJsonLength 属性设置的值
在.net mvc的controller中,方法返回JsonResult,一般我们这么写: [HttpPost] public JsonResult QueryFeature(string url, ...
- PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结
前 言 OOP 学习了好久的PHP,今天来总结一下PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化). 1 PHP中的抽象 ...
- 使用JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength属性
"/"应用程序中的服务器错误.使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错.字符串的长度超过了为 maxJsonLength 属性设置的值. ...
- C# 序列化与反序列化之xml对属性或者字段的子类化的子对象进行序列化的解决方案
C# 序列化与反序列化之xml对属性或者字段的子类化的子对象进行序列化的解决方案 xml序列化涉及到XmlRoot,XmlInclude,XmlElement,XmlAttribute,XmlType ...
- java oop第12章_IO、序列化和反序列化
引言:数据通常通过文件系统保存在外存中,有时需要将他们读取到程序中进行一些操作,Java针对文件系统的操作提供了一套规范,即IO,针对计算机内存而言,输入的称为输入流,输出的称为输出流. 一. ...
随机推荐
- 全景视频外包团队:技术分享Unity3D全景漫游
作者:未知 1.建模中使用的图片.文件.文件夹等以及模型中物体.材质等的名称都不能使用中文或者特殊符号,可以使用英文字母.数字.下划线等 2.调整Max的单位为米 3.烘培光影的设置 4.模型的中的植 ...
- bzoj4130: [PA2011]Kangaroos
Description 定义两个区间互相匹配表示这两个区间有交集. 给出长度为N的区间序列A,M次询问,每次询问序列A中最长的连续子序列,使得子序列中的每个区间都与[L,R]互相匹配 N<=50 ...
- 关于windows字体的一些笔记
windows如何管理字体 windows的字体管理在注册表的windows/font这部分(具体路径忘记了),这里会记录字体的名称和名称,如果有具体指出路径,windows启动的时候会从这个路径去加 ...
- myeclipse的debug模式中breakpoint窗口怎么调出来
myeclipse的debug模式中breakpoint窗口怎么调出来? 解决办法: window-->show view-->breakpoints. 如下:
- python---字符编码
获取系统默认字符编码 在Python代码中,普通字符串的编码方式与程序源文件编码方式一致的,而很多IDE在默认情况下,将程序源文件按照系统默认字符编码来保存的. 下面给出用Python获取系统默认编码 ...
- C语言操作mysql
php中 mysqli, pdo 可以用 mysqlnd 或 libmysqlclient 实现 前者 从 php 5.3.0起已内置到php中, 并且支持更多的特性,推荐用 mysqlnd mysq ...
- CORBA GIOP消息格式学习
想要深入理解ORB的工作过程与原理,学习与了解GIOP消息格式必不可少.我们知道GIOP是独立于具体通信的更高级别的抽象,因此这里针对GIOP在TCP/IP上的实现IIOP协议进行学习与分析(IIOP ...
- 理解JavaScript中的事件轮询
原文:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 为什么JavaScript是单线程 JavaScript语言的一大特点就是单线程,也 ...
- mysql中in和exists二者的区别和性能影响
mysql查询语句in和exists二者的区别和性能影响 还记得一次面试中被人问到in 和 exists的区别,当然只是草草做答,现在来做下分析. mysql中的in语句是把外表和内表作hash 连接 ...
- [转]CABasicAnimation用法
CABasicAnimation用法 CABasicAnimation 自己只有三个property fromValue toValue ByValue 当你创建一个 CABasicAni ...