String的intern方法的用处

原创 2007年10月09日 20:39:00

今天第一次翻看Effective java,在其第一个item中讲静态工厂方法的有点的时候说到“它们每次被调用

的时候,不要非得创建一个新的对象”并在结尾处提到---"String.intern方法以一种有限的形式实现了这

种优化",由于以前没用过intern这个方法,所以去查了查,并把自己的理解写下来供以后参考
首先来看其中文API的描述:


intern

public String intern()
返回字符串对象的规范化表示形式。
一个初始时为空的字符串池,它由类 String 私有地维护。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true


总结出来其意思如下:
如果:s.intern()方法的时候,会将共享池中的字符串与外部的字符串(s)进行比较,如果共享池中有与之相等的字符串,则不会将外部的字符串放到共享池中的,返回的只是共享池中的字符串,如果不同则将外部字符串放入共享池中,并返回其字符串的句柄(引用)-- 这样做的好处就是能够节约空间


最后看看这方面的一个很好的例子

在例子之前我们先假设我们在sqlserver2000里面有Test数据库,里面有表如下:
test1
name
我们通过下面程序向里面添加8000条记录:

import java.sql.*;

public class TestDB {

 private static String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver";

 private static String dbURL =

"jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=TEST";

 private static String userName = "sa";

 private static String userPwd = "";

 private static Connection dbConn;

 public static void main(String[] args) {

  try {
   Class.forName(driverName);
   dbConn = DriverManager.getConnection(dbURL, userName, userPwd);
   Statement stmt = dbConn.createStatement();
   String sql = "insert into test1 values('123456789123456789123456789');";
   for (int i = 0; i < 8000; i++) {
    stmt.executeUpdate(sql);
   }
   System.out.println("Connection Successful!");
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

添加完成以后我们在查询分析器里面执行:
select count(*) from test1;
可以看到结果:8000  表明8000条数据插入正确

假设我们有这样一个类:Po.java
public class Po {
 private String name;

 public void setName(String s) {
  name = s;
 }

}

我们执行下面的类:TestStringIntern.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class TestStringIntern {
 private static String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver";

 private static String dbURL =

"jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=TEST";

 private static String userName = "sa";

 private static String userPwd = "";

 private static Connection dbConn;

 private static List<Po> list= new ArrayList<Po>();
 public static void main(String[] args) {

  try {
   Class.forName(driverName);
   dbConn = DriverManager.getConnection(dbURL, userName, userPwd);
   Statement stmt = dbConn.createStatement();
   ResultSet rs = stmt.executeQuery("select name from test1");
   while(rs.next()){
    String s = rs.getString(1);;
    Po p = new Po();
    p.setName(s);
    list.add(p);
    s = null;
    p = null;
   }
   long total = Runtime.getRuntime().totalMemory();
   long free = Runtime.getRuntime().freeMemory();
   System.out.println("The busy memory is: " + (total - free));
   rs.close();
   stmt.close();
   dbConn.close();
   System.gc();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}
我们可以看到执行的结果为:The busy memory is: 1252880
注意:如果把p.setName(s)这句换成p.setName(s.intern());
再执行该程序我们可以看到结果:The busy memory is: 515944
我们可以到经过细微的改变我们可以看到其占用的内存不是一个数量级的
那么这个intern()函数做了什么呢?我认为:
在String对象维持的一个私有池里面存放的字符串“123456789123456789123456789”可能只有一个,因为每次比对都是一样,所以是不会将这样的对象重复放到池里面的,所以调用intern()方法就是完成的这个功能,其返回的只是里面的同一个字符串,而没有创建新的字符串,所以不会占用太多的空间

注:以上很多只是个人理解,具体实现细节不太清楚,所以难免会有错的地方,希望指出。 

几张图轻松理解String.intern()

在翻《深入理解Java虚拟机》的书时,又看到了2-7的 String.intern()返回引用的测试。 其实要搞明白String.intern(),我总结了下面几条规则: 一、new String...
  • soonfly
  • soonfly
  • 2017-04-12 20:35:49
  • 6699

Java技术——你真的了解String类的intern()方法吗

说实话我本来想总结一篇Android内存泄漏的文章的,查阅了很多资料,发现不得不从Java的OOM讲起,讲Java的OOM又不得不讲Java的虚拟机架构。在JVM架构一文中也有介绍,在JVM运行时数据...
  • SEU_Calvin
  • SEU_Calvin
  • 2016-08-23 16:40:53
  • 34860

String的intern()方法详解

官方API: intern public String intern() 返回字符串对象的规范化表示形式。 一个初始时为空的字符串池,它由类 String 私有地维护。 当调用 intern 方...
  • wjzhang5514
  • wjzhang5514
  • 2017-04-17 11:42:14
  • 1117

String的intern方法详解

之前一直有个错误的观点,使用new关键字创建String对象的时候,只会在堆区创建一个对象,但是看到了这篇文章,从源码进行分析,让自己恍然大悟,使用new关键字创建String对象是会在常量池中创建一...
  • qq_38663729
  • qq_38663729
  • 2017-09-21 21:10:52
  • 200

深入理解java虚拟机(三):String.intern()-字符串常量池

深入理解java虚拟机(一):java内存区域(内存结构划分) 深入理解java虚拟机(二):java内存溢出实战   看源码:  public native String intern();    ...
  • MINEZHANGHAO
  • MINEZHANGHAO
  • 2014-02-19 14:47:44
  • 11826

深入解析String#intern

原文地址:http://www.importnew.com/14142.html 引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String。这些类型为了使他们在运行过程...
  • u013564276
  • u013564276
  • 2016-07-16 19:43:02
  • 242

string的intern方法的使用

String的intern方法的使用以及作用,这里涉及到jvm的方法区中运行时常量池总的字符串对象。...
  • crazyzhb2012
  • crazyzhb2012
  • 2014-09-21 20:47:54
  • 1655

String中intern的方法

转自:http://www.cnblogs.com/wanlipeng/archive/2010/10/21/1857513.html 首先查看官方API那个的解释: ——————————————...
  • limingluzhu
  • limingluzhu
  • 2014-04-23 14:14:46
  • 193

Java (JDK7)中的String常量和String.intern的实现

Java中的String常量和String.intern的实现
  • raintungli
  • raintungli
  • 2014-08-16 10:15:22
  • 7033

java String.intern() 方法

source : http://java-performance.info/string-intern-in-java-6-7-8/ 这篇文章介绍String.intern 方法在java 6中的实现...
  • u012941811
  • u012941811
  • 2016-09-02 16:38:19
  • 812
收藏助手
不良信息举报
您举报文章:String的intern方法的用处
举报原因:
原因补充:

(最多只允许输入30个字)