今天第一次翻看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. 【转】#ifdef __cplusplus深度剖析

    原文:http://bbs.ednchina.com/BLOG_ARTICLE_251752.HTM 时常在cpp的代码之中看到这样的代码:     #ifdef __cplusplus extern ...

  2. Oracle的Export用法

    Oracle 的 Export 命令用于导出数据库信息,既可以导出表结构,也可以导出数据,表空间,或者按用户导出等等.按照通常的说法,该命令主要是用于数据库的迁移或者备份的.下面就介绍一下该命令的部分 ...

  3. oracle 绿色版本 instantclient 使用说明

    1,将instantclient直接放到D盘根目录 2,注册表修改 3,点击工具>>首选项, 在Oracle主目录名中输入“D:\instantclient_10_2\”,在OCI库中输入 ...

  4. easyui 多行文本框 Multiline TextBox

    <input class="easyui-textbox" data-options="multiline:true" value="This ...

  5. netty sample

    http://netty.io/wiki/ https://github.com/netty/netty/tree/master/example/src/main/java/io/netty/exam ...

  6. 苹果Mac操作系统下怎么显示隐藏文件

      对于新手而已民,苹果的MAC操作系统刚用时用得很不习惯,比如想要显示被隐藏的文件时,不像windows有个“文件夹选项”对话框可以来设置,百度出来的结果都是用命令来操作,但我建议不要用命令去操作, ...

  7. C#列表顺序替换思想

    /// <summary> /// 显示列顺序 /// </summary> /// <param name="list"></param ...

  8. Matlab中sortrows函数解析

    一.问题来源 返回检索到的数据(按相关度排序)在原始数据中的索引. 二.问题解析 x = [1 4 3 5; 1 3 2 6]:sortrows(x)其结果是按照row来排列,默认首先排第一列,1和1 ...

  9. 增强LSH

    通过LSH hash functions我们能够得到一个或多个hash table,每个桶内的数据之间是近邻的可能性很大.我们希望原本相邻的数据经过LSH hash后,都能够落入到相同的桶内,而不相邻 ...

  10. 深入js的面向对象学习篇(封装是一门技术和艺术)——温故知新(二)

    下面全面介绍封装和信息隐藏. 通过将一个方法或属性声明为私用的,可以让对象的实现细节对其它对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束.在代码有许多人参与设计的情况下, ...