皮皮网

皮皮网

【求-97源码】【抚州溯源码燕窝一般多少钱】【图标是机器人的源码编辑器】integer 源码分析

时间:2024-11-26 22:18:10 分类:热点

1.第7讲 | int和Integer有什么区别?
2.聊聊 Integer 吧
3.面试题系列第3篇:Integer等号判断的码分内幕,你可能不知道?
4.优雅的码分避坑不要轻易使用==比较两个Integer的值
5.《Lua5.4 源码剖析——基本数据类型 之 数字类型》
6.为何Mybatis将Integer为0的属性解析成空串?

integer 源码分析

第7讲 | int和Integer有什么区别?

       典型回答:

       int是Java中的一种基本数据类型,属于原始数据类型的码分一种。它是码分Java编程语言中的8个基本数据类型之一,包括boolean、码分byte、码分求-97源码short、码分char、码分int、码分float、码分double、码分long。码分

       Integer是码分int类型的包装类,它是码分一个对象,包含一个存储数据的码分int类型的字段,并提供了一些基本操作,如数学运算、int与字符串之间的转换等。在Java 5中,引入了自动装箱和自动拆箱功能,简化了相关编程。

       关于Integer的值缓存,这涉及Java 5中的一个改进。传统上,构建Integer对象的方式是直接调用构造器,创建一个新的对象。但实践表明,大部分数据操作都集中在有限的、较小的数值范围内。因此,在Java 5中引入了静态工厂方法valueOf,它利用一个缓存机制,提高了性能。按照Javadoc,这个值默认缓存范围是-到之间。

       知识扩展:

       1. 理解自动装箱、拆箱

       自动装箱是一种语法糖,它实际上是一种语法上的简化。简单来说,Java平台为我们自动进行了一些转换,以保证不同的写法在运行时等价。这些转换发生在编译阶段,生成的抚州溯源码燕窝一般多少钱字节码是一致的。

       2. 源码分析

       考察是否阅读过、是否理解JDK源代码可能是部分面试官的关注点。阅读并实践高质量代码也是程序员成长的必经之路。下面我来分析下Integer的源码。

       3. 原始类型线程安全

       前面提到了线程安全设计,你可能想过,原始数据类型操作是否线程安全。

       4. Java原始数据类型和引用类型局限性

       从Java平台发展的角度来看,原始数据类型和对象的局限性和演进是值得关注的。

       再扩展:

       你知道对象的内存结构是什么样的吗?比如,对象头的结构。如何计算或获取某个Java对象的大小?

聊聊 Integer 吧

       当我们深入探讨Java编程语言时,基础知识的重要性便凸显出来。在忙碌的编码过程中,抽出时间梳理JDK源码,无疑是一种查缺补漏的高效方式。经过阅读,你或许会惊喜地发现,JDK源码中隐藏着许多让你大开眼界的内容。

       Java作为一种面向对象的编程语言,遵循万物皆对象的原则。但为了在编程中实现灵活性和方便性,Java引入了基本数据类型对应的包装类型,即所谓的“wrapper class”。作为整型int的包装类,Integer不仅在功能上与int相互补充,还通过自动装箱/拆箱机制实现了二者之间的无缝转换,自Java 5版本开始引入。

       为什么需要引入Integer(包装类)?答案在于面向对象思想的贯彻。在Java中,为了将基本类型转换为对象形式进行操作,一种直观的方式是将基本类型作为类属性保存。这样做的初衷,是让基本数据类型更符合面向对象的抽象和封装原则,从而更加适应Java的编程模式。

       创建Integer的途径多样,但最常见的方式是直接赋值。尽管第二种和第三种看似遵循Java语法规范,但实际上,Java类型分为基本类型和对象类型两种,int属于基本类型,Integer属于对象类型。图标是机器人的源码编辑器对于JVM而言,直接将基本类型赋值给对象类型的操作是不被允许的。不过,在实际开发中,这样的操作并不会导致报错,这是因为编译器采用了语法糖技术,巧妙地在不改变JVM基础语法的前提下,提供了更加便捷的编程体验。

       Integer缓存机制的实现,通过Integer类内部定义的私有静态类IntegerCache来完成。这个类负责存储一个特定范围内的静态Integer对象,并在静态代码块中进行初始化。默认情况下,缓存范围限定在[-, ]之间,因此只实例化了个Integer对象。当值落在这个范围内时,程序可以直接从缓存中获取相应的Integer对象,避免了重复实例化和回收,从而节省了资源消耗。此外,通过配置虚拟机参数-Djava.lang.Integer.IntegerCache.high=xxx,可以灵活地调整缓存值的最大值,满足不同的应用需求。

       深入剖析Integer的hashCode()方法和equals()方法,我们能更清晰地理解它们的作用。hashCode()方法返回的是对象本身的value值,而equals()方法比较的是两个对象的value值,即两个Integer对象的逻辑数值一致时,equals方法将返回true。

       Integer与int的区别主要体现在以下几个方面:1)Integer是int的包装类,而int是Java的基本数据类型;2)Integer变量在使用前必须实例化,而int变量则无需预先声明;3)Integer实际上是对象的引用,new一个Integer时实际上是生成一个指针指向该对象;而int则是直接存储数据值;4)Integer的默认值为null,而int的默认值为0。

       理解Integer与int之间的比较,对于深入掌握Java的基本数据类型和对象关系至关重要。通过分析不同类型的比较方法,我们可以更准确地识别出它们的区别。例如,两个Integer对象通过"=="比较时,返回false,因为它们实际上是网页源码模板百度网盘下载指向不同内存地址的对象;而使用equals方法时,只要value值相同,就会返回true。

       在实际开发中,我们应遵循以下建议:1)在表示一个值时,优先考虑使用int类型,以节省内存空间;2)Integer类型在使用前必须初始化,避免NullPointerException异常;3)针对特定场景,如考试成绩区分未参加考试与0分,使用Integer可以更清晰地区分未赋值与值为0的情况;4)推荐直接赋值而非通过new生成新对象,以提高内存利用率;5)根据实际情况调整JVM启动参数,适当扩展Integer缓存区间,以节省内存和提升性能;6)在进行两个对象的比较时,使用equals方法而非“==”。

       Java中与Integer类似的Long也有缓存机制,在[-, ]范围内获取缓存值,而Long与long的比较会先转换成long类型。至于Double类型,它没有缓存机制,但与double的比较会先转换成double类型。

       总结而言,基础知识往往蕴含着编程中的智慧与陷阱。保持求知欲,不断巩固基础知识,将使我们在编程之旅中少走弯路,面试时也能游刃有余。

面试题系列第3篇:Integer等号判断的内幕,你可能不知道?

       《Java面试题系列》:深入挖掘面试题中经典内容,剖析源码,总结原理,形成公众号系列文章,不论面试与否,均可提升技能。本篇为系列第3篇。面试过程中关于Integer的比较“==”的问题层出不穷,但了解其底层原理后,即可轻松应对。根据《阿里巴巴Java开发手册》,所有整形包装类对象之间的值比较应使用equals方法,对于在-到范围内的赋值,Integer对象会在IntegerCache.cache产生并复用,这个区间内的Integer值可以直接使用“==”进行判断。然而,收盘缩量阴十字星源码该区间之外的所有数据会在堆上产生,并不会复用已有对象,这是个陷阱,推荐使用equals方法进行判断。

       执行下面的程序,打印结果为true的有几项?

       执行程序后,打印结果为:只有C和F项打印为false。读者可能疑惑为什么i1等于i2,i1等于i3,i2等于i4,都为true,根据等号的传递性,i3应该等于i4啊?为什么i1和i3相等,但i5和i6却不相等呢?

       在彻底弄清楚问题之前,我们先了解一下基础类型变量、引用类型变量在JVM中的存储。通常变量分为局部变量和全局(成员)变量。局部变量声明在方法内,而全局变量声明在类中。基础类型的变量和值在分配时一起,都在方法区、栈内存或堆内存。而引用类型的变量和值不一定在一起。

       局部变量存储在方法栈中,当方法被调用时,Java虚拟机同步创建一个栈帧,局部变量存储其中。方法结束后,栈帧销毁,其中声明的变量也随之结束。因此,局部变量只能在方法中有效。基础类型与引用类型的存储有所不同,基础类型存储在JAVA虚拟机的栈中,引用类型存储在栈中,指向堆中的对象。栈属于线程私有的空间,局部变量的生命周期和作用域一般都很短,为了提高gc效率,所以没必要放在堆里面。

       全局变量存储在堆中,不会随着方法结束而销毁。类中声明的变量分为基本类型和引用类型,基本类型存储在堆内存中,引用类型存储在堆中,是一个引用地址,指向所引用的对象。

       结合上述理论,我们通过一段代码来分析各种类型所存储的位置。

       基础类型的栈内存储,在同一栈帧中,针对int类型的处理模式如下:

       假设编译器先处理int a=3,此时会在栈中创建a的引用变量,然后查找栈中是否存在3这个值,如果没有就将3存放进来,然后将a指向3。接着处理int b=3,创建完b的引用变量后,同样进行查找。因为在栈中已经有3这个值,便将b直接指向3。此时,a与b同时指向3这个值,自然是相等的。

       对于“==”操作符号,JVM会根据其两边相互比较的操作数的类型,在编译时生成不同的指令。对于boolean、byte、short、int、long这种整形操作数会生成if_icmpne指令,用于比较整形数值是否相等。如果操作数是对象,则生成if_acmpne指令,与if_icmpne相比将i(int)改成了a(object reference)。

       学习了底层理论知识,我们得出以下两个int类型比较,直接使用双等号即可;int的包装类Integer对象比较时,使用equals进行比较即可。但结果只能说E项目是正确的,其比较项还涉及到整形的装箱拆箱操作、Integer的缓存。下面逐一分析。

       不同创建形式的比较,先看Integer的初始化,有三种创建形式,分别是直接赋值、valueOf方法和new关键字。因为通过new和valueOf创建的是完全两个对象,那么针对题目中的C项,直接比较两个对象的引用肯定是不相等的,因此结果为false。但B项为什么为true呢?后面我们会讲到。

       比较中的拆箱,在题目中,我们发现A、D都为true,它们的比较格式都是基础类型与包装类型的对比。针对这种形式的对比,包装类型会进行自动拆箱,变成基础类型(int)。很显然,结果是相等的。

       Integer的缓存机制,为什么i1和i3相等,但i5和i6却不相等呢?对应题目中的B和G项。我们已经知道,Integer直接赋值和valueOf是等效的,接下来看一下valueOf及相关的方法。valueOf方法判断数字是否大于low(-)并且小于high(),如果满足条件,则直接从IntegerCache中返回对应数字。IntegerCache用于存储一些常用的数,防止重复创建,在Integer类装入内存时通过静态代码进行初始化。因此,只要是用valueOf或者Integer直接赋值的方式创建的对象,其值小于且大于-的,无论对其进行“==”比较还是equals比较,都是true。

       关于Integer的比较核心点有以下三点:引用对象的存储结构、Integer的缓存机制、自动装箱与拆箱。总结Integer在“==”运算时的核心点如下:如果“==”两端有一个是基础类型(int),则会发生自动拆箱操作,这时比较的是值。如果“==”两端都是包装类型(Integer),则不会自动拆箱,首先会面临缓存问题,即便在缓存范围内的数据还会再次面临创建方式的问题,因此强烈建议使用equals方法进行比较。

       如果觉得文章写的还不错,就关注一下。下篇文章,我们来讲讲equals和hashcode方法的重写底层逻辑。本文首发来自微信公众号:程序新视界,一个软实力、硬技术同步学习的平台。

优雅的避坑不要轻易使用==比较两个Integer的值

       直接进入主题,来看一段代码,让我们探索Integer比较的奥秘:

       许多人可能会理所当然地认为这段代码会打印出 j = ,但背后的原理却值得深入探讨。i作为Integer对象,而j为基本类型int,它们如何协同工作呢?这涉及到Java 5引入的自动装箱和拆箱机制。借助IDEA的jclasslib Bytecode viewer插件,我们可以看到程序运行的底层指令:

       这段程序的字节码指令揭示了自动装箱和拆箱的过程。第3行调用Integer的valueOf方法进行自动装箱,第8行则调用intValue方法进行自动拆箱,将Integer对象转换为int。

       进一步研究valueOf和intValue的源码,我们发现Integer类中有一个IntegerCache机制,它在虚拟机初始化时预加载了(-,]范围内的整数。这解释了为什么i1 == i2为true,而i3 == i4为false:在缓存范围内,而超出了。

       为了避免这类陷阱,正确的比较两个Integer值的方法是使用equals()函数,而不是简单的==。equals会比较两个对象的整数值,不受类型影响。

       阿里Java开发手册推荐的策略是,当比较整型包装类对象的值时,始终使用equals()方法,以确保准确无误的比较。

《Lua5.4 源码剖析——基本数据类型 之 数字类型》

       数字类型在编程中分为整数和浮点数两种。在Lua语言的5.3版本之前,所有数字都被底层实现为浮点数,整数的概念并未独立出来,而是通过浮点数的IEEE表示法进行表示与数据存储。这样,在进行整数运算时,可能会在多次运算后累积产生出意外的浮点误差。因此,从Lua5.3版本开始,Lua引入了对整数的支持,使其不再依赖于浮点数进行表示,并且支持位运算等整数运算操作符。

       在Lua语言中,每个基础对象需要存储其类型标识,这个标识在源码《lua.h》中定义为tt,数字类型的tt枚举值为LUA_TNUMBER(对应数字3)。由于数字类型分为整型和浮点型,它们通过类型变体来区分。在源码《lobject.h》中,类型变体LUA_VNUMINT表示整型,而LUA_VNUMFLT表示浮点型。

       数字类型在TValue中定义了Value字段,这个字段包含i和n两个字段,用于分别存储整型和浮点型的数值。在历史原因的影响下,lua_Number并不是指所有数字类型,而是专门指浮点类型;lua_Integer则专门指整型。因此,设置整数或浮点数时,需要先设置Value字段中的n字段(整型)或i字段(浮点型),然后使用settt_宏设置type tag(tt)字段为对应值LUA_VNUMFLT或LUA_VNUMINT。

       在底层,数字类型的数据类型具体表现为lua_Integer和lua_Number。在源码《lua.h》中声明,lua_Number为LUA_NUMBER,lua_Integer为LUA_INTEGER。深入学习它们的定义,可以看到整型有int、long、long long三种类型,浮点型有float、double、long double三种类型。Lua5.4的默认配置中,整型使用long long类型,浮点型使用double类型。在Windows平台上,整型使用__int类型。

       至此,数字类型的讲解就告一段落。希望本文对理解Lua语言中的数字类型有所帮助。

为何Mybatis将Integer为0的属性解析成空串?

       在一次代码审查中,同事分享了一个有趣的问题:在Mybatis中,Integer类型的age为0时,为什么会解析成空串,导致SQL语句的条件判断失效?

       为了解答疑问,作者查阅了Mybatis的源码。首先,从GitHub上的最新版本下载代码,构建测试用例。在SqlSessionFactoryBuilder的构建流程中,经过XMLConfigBuilder解析配置,构建Configuration类,进而生成SqlSessionFactory和SqlSession。执行过程中,mybatis使用SimpleExecutor或CachingExecutor,后者涉及动态代理和拦截器的执行,关键在于DynamicSqlSource和IfSqlNode类。

       在IfSqlNode的evaluator.evaluateBoolean方法中,使用了OGNLCache来获取值,而问题出在OGNL表达式对空字符串的处理上。在ASTNotEq类的compareWithConversion方法中,当字符串长度为0时,会被解析为0.0,这不仅影响Integer,也影响Float和Double类型。因此,问题的根源在于OGNL表达式对空字符串的解析规则。