今天第一次翻看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. (转载)总结一下SQL语句中引号(')、quotedstr()、('')、format()在SQL语句中的用法

    总结一下SQL语句中引号(').quotedstr().('').format()在SQL语句中的用法 总结一下SQL语句中引号(').quotedstr().('').format()在SQL语句中 ...

  2. CentOS7下源码安装mysql5.6

    目录 准备工作 运行环境 确认你的安装版本 下载mysql 安装mysql 准备安装环境 编译和安装 配置mysql 单实例配置      单实例配置方法          添加防火墙         ...

  3. python3 pyqt5 和eric5配置教程

    一.大纲内容: 1.预备PC环境: 2.预备安装程序: 2.1.下载Python3.2 2.2.下载PyQt4 2.3.下载Eric5 3.安装配置步骤: 3.1.安装Pyhon3.2 3.2.安装P ...

  4. mysqlsla慢查询分析工具教程

    mysqlsla是一款帮助语句分析.过滤.和排序的功能,能够处理MySQL慢查询日志.二进制日志等.整体来说, 功能非常强大. 能制作SQL查询数据报表,分析包括执行频率, 数据量, 查询消耗等. 且 ...

  5. JS 实现取整(二)

    1.直接丢弃小数部分,保留整数部分 a:parseInt(1.5555) b: 0|1.5555 2.向上取整 a: Math.ceil(1.5555) b: (1.5555+0.5).toFixed ...

  6. EXTJS 4.2 添加滚动条

    bodyStyle: 'overflow-x:hidden; overflow-y:scroll',//显示滚动 文章来源:http://www.cnblogs.com/exmyth/archive/ ...

  7. HTMLParser获取属性名

    HTMLParser获取属性名方式: 原始网页文本: <a title="美军被曝虐尸" href="http://www.sogou.com/web?query= ...

  8. 过滤菜鸟的iOS面试题-b

    网上已经有很多针对各种知识点的面试题,面试时有些人未必真正理解也能通过背题看上去很懂.我自己总结了4道面试题,好快速的判断这个人是否是一个合格的工程师,欢迎大家点评. 1.struct和class的区 ...

  9. dtGrid插件集成到Angular环境实现表格化数据展现

    00没有抱怨的世界 周末效率好低,两天没更了,看看这看看那,装了个win10发现触摸板驱动不适配,然后找了好久都不行,23333. AngularJS用的时间很短,高级的用法有点吃不消了,$diges ...

  10. REST Design Concerns

    Less Requests, More data; one of the core RESTful API design paradigms is the concept of less API re ...