先来看一段程序,如下:

package basic;

import java.lang.reflect.Field;

public class TestField {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
@SuppressWarnings("rawtypes")
Class cache = Integer.class.getDeclaredClasses()[0];
Field myCache = cache.getDeclaredField("cache");
myCache.setAccessible(true);
Integer[] newCache = (Integer[]) myCache.get(cache);
newCache[132] = newCache[133];
int a = 2;
int b = a + a;
System.out.printf("%d + %d = %d", a, a, b);
}
}

程序正常运行,输出如下结果:

2 + 2 = 5

分析:

package basic;

/**
* 类TestDeclaredClass.java的实现描述:getDeclaredClasses() 方法返回一个Class对象,包括公共,保护,默认(包)访问的私有类和类中声明的接口的数组,但不包括继承的类和接口。
* 如果类没有声明的类或接口的成员,或者如果此Class对象表示一个基本类型,此方法返回一个长度为0的数组。
*
* @author 2016年6月16日 上午10:17:51
*/
public class TestDeclaredClass { public static void main(String[] args) {
try {
Class cls = TestDeclaredClass.class;
Class[] clss = cls.getDeclaredClasses();
for (int i = 0; i < clss.length; i++) {
System.out.printf("CLASS = %s \n", clss[i].getName()); }
} catch (SecurityException e) {
e.printStackTrace();
}
} public class InnerClass1 { public InnerClass1(){
System.out.println("InnerClass1");
}
} public interface Inner {
} public class InnerClass2 { public InnerClass2(){
System.out.println("InnerClass2");
}
} private class InnerPrivateClass { public InnerPrivateClass(){
System.out.println("InnerPrivateClass");
}
}
} class MyTestDeclaredClass extends TestDeclaredClass {
}

程序正常运行,输出如下结果:

CLASS = basic.TestDeclaredClass$Inner
CLASS = basic.TestDeclaredClass$InnerClass1
CLASS = basic.TestDeclaredClass$InnerClass2
CLASS = basic.TestDeclaredClass$InnerPrivateClass

接着再看:

package basic;

import java.lang.reflect.Field;

/**
* 类TestGetDeclaredField.java的实现描述:getDeclaredField() 方法返回一个Field对象,它反映此Class对象所表示的类或接口的指定已声明字段。
* name参数是一个字符串,指定所需字段的简单名称。
*
* @author 2016年6月16日 上午10:36:21
*/
public class TestGetDeclaredField { Long size; public TestGetDeclaredField(Long size){
super();
this.size = size;
} public static void main(String[] args) {
try {
Class cls = TestGetDeclaredField.class;
Field field = cls.getDeclaredField("size");
System.out.println("Field = " + field.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}

程序正常运行,输出如下结果:

Field = java.lang.Long basic.TestGetDeclaredField.size

在Java的反射中Field类和Method类的说明:要想使用反射,首先需要获得类对象所对应的Class类的类对象。一个Field对象对应的是一个反射类的属性(成员变量)信息。Field类中定义了一些方法,可以用来查询字段的类型以及设置或读取字段的值。Method类使得我们可以获得方法声明的完整信息。

基于以上信息分析代码如下:

Class cache = Integer.class.getDeclaredClasses()[0];
Field myCache = cache.getDeclaredField("cache");

获取到内部类和内部类中成员变量名为cache的属性信息。

java.lang.Integer$IntegerCache
static final java.lang.Integer[] java.lang.Integer$IntegerCache.cache

我们来看JDK中关于Integer内部类IntegerCache中属性cache的源码如下:

    /**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the -XX:AutoBoxCacheMax=<size> option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/ private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[]; static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
} private IntegerCache() {}
}

JavaInteger对-127到128的整形数据是有缓存的,你这里通过反射缓存中的第133号数据(既整数5)赋值给了第132号数据(既整数4),所以4就会变成5来表示。在使用int数据计算时结果是正常的,但是在打印时由于做了装箱,int数据变成了Integer,这时会采用缓存,所以4就会打印出5来。

1、易百教程:http://www.yiibai.com/html/java/

2、Java机智的让1+1的结果变成3:http://www.tuicool.com/articles/nIzQJjb

3、segmentfault问题地址:https://segmentfault.com/q/1010000005732476

Java中2+2==5解读的更多相关文章

  1. Java中Websocket使用实例解读

    介绍 现在很多网站为了实现即时通讯,所用的技术都是轮询(polling).轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服端的浏览器 ...

  2. java中jdbc源码解读

    在jdbc中一个重要的接口类就是java.sql.Driver,其中有一个重要的方法:Connection connect(String url, java.util.Propeties info); ...

  3. java中对象的简单解读

    对象=属性(int double之类都是变量的属性)+方法(想要实现内容,所做的一套算法) 属性=变量的所有数据 方法(c语言中叫做函数)=算法 总而言之 对象就是  给他所需要的的数据-->& ...

  4. 全面解读Java中的枚举类型enum的使用

    这篇文章主要介绍了Java中的枚举类型enum的使用,开始之前先讲解了枚举的用处,然后还举了枚举在操作数据库时的实例,需要的朋友可以参考下 关于枚举 大多数地方写的枚举都是给一个枚举然后例子就开始sw ...

  5. Java面试-List中的sort详细解读

    最近看了一些排序相关的文章,因此比较好奇,Java中的排序是如何做的.本片文章介绍的是JDK1.8,List中的sort方法. 先来看看List中的sort是怎么写的: @SuppressWarnin ...

  6. Java中的泛型 (上) - 基本概念和原理

    本节我们主要来介绍泛型的基本概念和原理 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以 ...

  7. Java中Properties类知识的总结

    一.Properties类与配置文件 注意:是一个Map集合,该集合中的键值对都是字符串.该集合通常用于对键值对形式的配置文件进行操作. 配置文件:将软件中可变的部分数据可以定义到一个文件中,方便以后 ...

  8. java中的23中设计模式(转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  9. [JavaWeb]关于DBUtils中QueryRunner的一些解读.

    前言:[本文属于原创分享文章, 转载请注明出处, 谢谢.]前面已经有文章说了DBUtils的一些特性, 这里再来详细说下QueryRunner的一些内部实现, 写的有错误的地方还恳请大家指出. Que ...

随机推荐

  1. Web前端开发大系概览 (前端开发技术栈)

    前言 互联网建立50多年了,网站开发技术日新月异,但web前端始终离不开浏览器,最终还是HTML+JavaScript+CSS这3个核心,围绕这3个核心而开发出来大量技术框架/解决方案. 我从2000 ...

  2. python3.5 正则表达式

    我们平时上网的时候,经常需要在一些网站上注册帐号,而注册帐号的时候对帐号名称会有一些要求. 比如: 上面的图片中,输入的邮件地址.密码.手机号 才可以注册成功. 我们需要匹配用户输入的内容,判断用户输 ...

  3. Transaction Replication6:Transaction cleanup

    distribution中暂存的Transactions和Commands必须及时cleanup,否则,distribution size会一直增长,最终导致数据更新耗时增加,影响replicatio ...

  4. 模板引擎Nvelocity实例

    前言 最近一直忙于工作,没时间来管理博客,同时电脑也不给力,坏了一阵又一阵,最后还是去给修理了,这不刚一回来迫不及待的就写一篇文章来满足两个月未写博客的紧迫感. Nvelocity 关于nveloci ...

  5. Ruby之入门(一)

    前言 这门语言很少去听过,可能是没怎么用到就不会听到太多关于ruby的消息,工作需要这门语言,需要从0开始学习这门语言,慢慢学习简直...太神奇了...,原谅我见识浅薄.原来很早就已经出世了,园子中也 ...

  6. MySQL监控利器-Innotop

    Innotop是一款十分强大的MySQL监控工具,用perl所写,通过文本模式展示MysQL服务器和Innodb的运行状况. 安装innotop 下载地址:https://github.com/inn ...

  7. Repository 仓储,你的归宿究竟在哪?(一)-仓储的概念

    写在前面 写这篇博文的灵感来自<如何开始DDD(完)>,很感谢young.han兄这几天的坚持,陆陆续续写了几篇有关于领域驱动设计的博文,让园中再次刮了一阵"DDD探讨风&quo ...

  8. Java内存模型深度解析:顺序一致性--转

    原文地址:http://www.codeceo.com/article/java-memory-3.html 数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java内存模型规范对数据 ...

  9. 【解决】查询无法完成,因为其包含的查找列数已超过管理员强制实施的查找列阈值。Error code=0x80070093; Error source=Groove

    前因: 修改了SharePoint Server 2013 下面的文档库的名称,原先2个汉字,现在8个汉字.结果,SkyDrive Pro 就无法同步了,无论是停止重新同步还是手动填写进行同步都不可以 ...

  10. ssh整合问题总结--使用HibernateTemplate实现数据分页展示

    在进行大量的数据展示时,必须要使用分页查询,第一次使用在SSH框架整合中使用分页查询,遇到了一些问题,下面以我练习的项目为例详细介绍,如何在Spring+hibernate(+action)的环境下完 ...