Python常量池

本文深入探讨了Python中常量池的工作原理,特别是在整数对象的缓存方面,揭示了Python如何通过预先缓存常用整数来提高运行效率。特别关注了整数范围-5到256内的缓存特性,以及257这一特殊值的处理方式。

在python里,有一个神奇的机制:常量池

Python 内部做了一些优化,Python把常用的整数对象都预先缓存起来

特点:

  1.整数范围: -5 -- 257

  2.它永远不会被GC机制回收, 只要定义的整数变量在 范围: -5  --  256内,会被全局解释器重复使用, 257除外

  3.只要在这个 -5  --  256 范围内,创建同一区域代码块的变量的值如果是相等的,那么不会创建新对象(python万物皆对象,数值也是对象),直接引用。

一:

a = 123
b = 123
print(id(a)) >>> 1744793632
print(id(b)) >>> 1744793632 

二:

def test_a():
    a = 123
    print(id(a))


def test_b():
    b = 123
    print(id(b))

c = 123 
print(id(c)) >> 1744793632 test_a() >>>
1744793632
test_b() >>> 1744793632

三:奇葩的257


def test_a():
a = 257
b = 257
print(id(a)) # 1872078405424
print(id(b)) # 1872078405424


num1 = 257
num2 = 257
print(id(num1)) # 1872077827792
print(id(num2)) # 1872077827792
test_a()

257 这个整数对象是区分作用域的,它只有在相同的作用域, 内存地址才会相同

 

转载于:https://www.cnblogs.com/leixiansheng6f6/p/9282018.html

<think>好的,我现在需要回答用户关于Java字符串常量池中字符串拼接行为和规则的问题。根据用户提供的三个引用,我需要整合这些信息,并确保回答准确且符合用户的要求。 首先,用户提到在JDK9之后,字符串拼接遵循一定的规则,无论拼接的是常量还是变量,都会检查字符串常量池是否存在对应的字符串,不存在则创建新对象。引用1和引用2都提到了常量池的存在和用途,特别是池化技术的作用。引用3则介绍了intern()方法的作用,即在常量池中查找或添加字符串。 接下来,我需要将这些信息结构化。用户的问题涉及拼接的行为和规则,可能需要分情况讨论:字面量拼接、变量与字面量拼接、变量间拼接,以及使用intern()方法的情况。同时,要指出JDK版本的影响,比如JDK9之后的字符串处理优化。 需要注意的是,用户提供的引用中提到,无论常量还是变量拼接,都遵循同样的规则,即检查常量池是否存在,不存在则创建新的。这可能与之前的版本不同,比如JDK8及以前使用StringBuilder进行拼接,结果不会入池,除非显式调用intern()。因此,在回答中需要区分不同JDK版本的处理方式。 另外,用户示例中的Python代码可能与问题无关,但系统级指令要求生成相关问题,所以最后需要列出相关问题。同时,回答需使用中文,正确使用LaTeX格式,行内公式用$...$,独立公式用$$...$$,但这个问题可能涉及较少的数学公式,更多是代码和规则描述。 现在,组织回答结构: 1. 概述字符串常量池的作用和设计目的,引用引用2的内容。 2. 分点说明不同拼接情况下的行为,结合引用1的规则。 3. 解释intern()方法的作用,引用引用3。 4. 对比不同JDK版本的变化,特别是JDK9之后的优化。 5. 示例代码说明各种情况。 6. 总结关键点。 7. 生成相关问题。 需要确保每个引用在回答中正确标注,例如在解释规则时添加[^1],池技术时[^2],intern()方法时[^3]。 可能遇到的疑问点:用户的问题是否涉及编译时优化?比如字面量拼接在编译时处理,而变量拼接在运行时处理。例如,String s = "a" + "b"可能在编译时合并为"ab",并直接查看常量池是否存在。而变量拼接如s1 + s2会在运行时生成新对象,除非调用intern()。但根据引用1,JDK9之后无论常量还是变量,拼接后的处理是否相同?需要确认这一点。 根据引用1的描述,在JDK9之后,不论是字符串常量和变量,还是变量与变量拼接,都遵循同样的规则:拼接后的字符串如果在常量池中存在,则直接引用;否则创建新的String对象。这可能与之前的版本不同,以前可能对于变量拼接使用StringBuilder,结果不会自动入池,而字面量拼接在编译时优化并入池。 因此,在回答中需要明确说明JDK9前后的差异,并指出当前规则是基于JDK9及以后的版本。 此外,可能需要提到字符串常量池的位置,比如在堆内存中(JDK7之后),但用户的问题可能不涉及这个细节,除非必要。 现在,整理这些点,形成结构清晰的回答,并确保引用正确。</think>### Java字符串常量池的拼接行为与规则 #### 1. 字符串常量池的设计目的 字符串常量池是Java为优化`String`对象内存分配设计的特殊存储区域。它通过“池化技术”预存字符串字面量,避免重复创建对象,从而节省内存。 #### 2. 拼接行为规则(JDK9+) - **字面量拼接** 编译期直接合并并检查常量池,若存在则直接引用,否则创建新对象: ```java String s1 = "Hello" + "World"; // 编译后等价于"HelloWorld",检查常量池后引用 ``` - **变量与字面量拼接** 运行时生成新对象,但结果**不会自动入池**: ```java String s2 = "Hello"; String s3 = s2 + "World"; // 新对象,不在常量池中 ``` - **变量间拼接** 类似变量与字面量拼接,结果对象不入池: ```java String s4 = s2 + s3; // 新对象 ``` #### 3. `intern()`方法的作用 强制将字符串对象添加到常量池(若池中不存在),并返回池中引用: ```java String s5 = new String("Hello").intern(); // 返回常量池中的"Hello" ``` #### 4. JDK9+的优化 JDK9引入`StringConcatFactory`,优化拼接逻辑,但**行为规则不变**:拼接结果仅在常量池存在时引用,否则新建对象。 #### 5. 示例对比 ```java // 示例1:字面量拼接(编译期优化) String a = "ab"; String b = "a" + "b"; // 常量池已存在"ab",b直接引用 // 示例2:变量拼接(运行期生成) String c = "a"; String d = c + "b"; // 新对象,不在常量池 String e = d.intern(); // 将"ab"加入常量池,e引用池中对象[^3] ``` #### 6. 关键总结 - **常量池规则**:拼接结果存在则引用,否则新建[^1]。 - **变量拼接**:结果不入池(除非调用`intern()`)。 - **JDK版本差异**:JDK9前使用`StringBuilder`拼接,JDK9后优化实现但行为一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值