今天第一次翻看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方法的用处的更多相关文章

  1. java String 中 intern方法的概念

    1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...

  2. String 的intern() 方法说明

    1.说明 Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回. 2.源码说明 public native ...

  3. String 的 intern() 方法解析

    一.概述 JDK7 之前和之后的版本,String 的 intern() 方法在实现上存在差异,本文的说明环境是 JDK8,会在文末说明 intern() 方法的版本差异性. intern() 方法是 ...

  4. String中intern方法的作用

    前言 读完这篇文章你可以了解,String对象在虚拟机内存中的存放,intern的作用,这么多String对象的创建到底有什么区别,String 创建的对象有几个!! 正题 先科普几个知识点1.常量池 ...

  5. String的intern方法的使用场景

    在讲intern方法前,我们先简单回顾下Java中常量池的分类. 常量池的分类 Java中常量池可以分为Class常量池.运行时常量池和字符串常量池. 1. Class文件常量池 在Class文件中除 ...

  6. String的Intern方法详解

    引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念.常量池就类似一个JAVA系统级别提供的缓存.8种 ...

  7. String的Intern方法

    jdk6 和 jdk7 下 intern 的区别 相信很多 JAVA 程序员都做做类似 String s = new String("abc")这个语句创建了几个对象的题目. 这种 ...

  8. java String的intern()方法

    intern()方法用于将字符串对象加入常量池中. public native String intern(); intern()方法返回的是一个常量池中的String对象(即常量池中某个String ...

  9. Java - 记录String中intern()方法的学习与理解

    intern()方法:把堆中的引用丢入常量池中,然后返回这个引用.当常量池中已经存在这个引用,就直接返回这个引用.(jdk1.8) 由于jdk1.7中将字符串常量池改为存放在堆中,因此intern() ...

随机推荐

  1. 创建dataTable

    public void createTable() { DataSet ds = new DataSet(); using (DataTable dt = new DataTable("st ...

  2. ubuntu12.04 server + apache2 + wsgi + django1.6 部署

    最近在学Python和Django,想自己部署一个服务器试试 环境:ubuntu12.04 server | apache2 | django1.6 | python2.7 | mod_wsgi 在网 ...

  3. aaaa

    http://www.host.com http://www.host.com http://sz.weixun.com/scenery/details-3.htm http://sz.weixun. ...

  4. 微软职位内部推荐-SENIOR PRODUCER

    微软近期Open的职位: Role Based in Shanghai, ChinaTitle: ProducerWe are seeking a Senior Producer to lead Pr ...

  5. C# 写XML文件

    /// <summary>x /// 修改xml文件 /// </summary> /// <param name="dt"></para ...

  6. 4.4 spring-自定义标签的解析

    1.0 自定义标签的解析. 在之前的章节中,我们完成了对spring 默认标签的加载过程.那么现在我们将开始新的里程, spring 自定义标签的解析; 代码如下: /** * Parse the e ...

  7. 【数学/扩展欧几里得/线性求逆元】[Sdoi2008]沙拉公主的困惑

    Description 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁国现 ...

  8. string.Equals 比较2个字符串是否相同忽略大小写

    bool res = string.Equals(str1, str2, StringComparison.CurrentCultureIgnoreCase)

  9. hdu 3859 Inverting Cups

    题意是给出A个杯子,一开始都朝上,每次可以翻B个杯子,问最少需要翻转多少次可以让所有杯子都朝下. 分类讨论: 首先对于A%B==0一类情况,直接输出. 对于A>=3B,让A减到[2B,3B)区间 ...

  10. loadrunner java协议脚本要点

    常见问题 1. Error: Thread Context: Call to service of the driver failed, reason - thread context wasn't ...