草庐IT

自动内存管理之【常量池】

Jonckys 2023-05-02 原文

首先上一段代码,一起思考,打印的结果,基于jdk1.8。

        StringBuilder sb=new StringBuilder("我爱我媳妇儿");
        String s= sb.toString();
        System.out.println(s.intern()==s);  //false
        sb.append(",她也很爱我!");
        s=sb.toString();
        System.out.println(s.intern()==s);  //true
        StringBuilder stringBuilder = new StringBuilder("ja").append("va");
        String s2=stringBuilder.toString();
        System.out.println(s2.intern()==s2);//false

这里说一些String类的intern方法,它是一个本地方法。Api对它的解释是

Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

翻译过来的结果是:返回字符串对象的规范表示形式。字符串池最初是空的,由类String私下维护。当调用intern方法时,如果池中已经包含一个等于equals(object)方法确定的string对象的字符串,那么将返回池中的字符串。否则,该String对象将被添加到池中,并返回对此String对象的引用。因此,对于任何两个字符串s和t,s.inter()==t.inter()为真当且仅当s.equals(t)为真。

看到这里的朋友应该有点感觉了,我标红的地方是重点。

俗话说“万丈高楼平地起,辉煌智能靠自己”,要明白常量池 。何为常量池?

常量池分为:静态常量、全局常量、局部常量。

java中常量用final定义,也就是说不可变的值都会放到常量池中。比如int i=8,这个8是个不可变的值,string v="我爱我老婆",这个值就是常量。就是不可变的值就是常量,这些数据在编译的时候就会自动放到常量池中。

弄明白了这个,我们来分析上面的结果:

        StringBuilder sb=new StringBuilder("我爱我媳妇儿");
        String s= sb.toString();
        System.out.println(s.intern()==s);  //返回的是sb

首先这里说明一下,常量池和堆的关系,这是重点!!!!!!前提背景是jdk1.8

系统在编译期间将“我爱我媳妇儿”常量添加到了常量词,到第二行的s指向的是堆对象的引用,而s.intern是常量词的引用。所以这里会出现false的情况。

为什么在 sb.append(",她也很爱我!");之后又为true呢?

首先“,她也很爱我”会放到常量池中,在sb.toString()环节中将“我很爱我媳妇儿,她也很爱我”放到堆中。在变量s就会指向堆中的地址,当s.intern()进行查找的时候发现常量池中不存在,便会在常量池中创建,并执行堆中sb.toString()的地址。所以就是结果就是True。

那为什么输出Java那个又是false呢?

根据上面的这个思路我们去分解步骤,首先在常量词中分别创建了“ja”,“va”的常量。stringBuilder.toString()的时候在堆中进行了创建。这时候栈中的s2就会指向堆中“java”的地址,但是当s2.intern()被调用的时候,就会在常量池中进行查找,常量池中存在一个“java”的常量,将其返回。但是其对象的引用与我们的不一致。所以为false。

 这上面的难点为:1、弄清楚什么叫常量 2、对象存放的位置 

有关自动内存管理之【常量池】的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  4. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  5. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  7. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  8. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  9. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  10. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

随机推荐