了解String类的intern()方法

相信绝大多数的人不会去用String类的intern方法,打开String类的源码发现这是一个本地方法,定义如下:

public native String 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)进行比较,如果共享池中有与之相等的字符串,则不会将外部的字符串放到共享池中的,返回的只是共享池中的字符串,如果不同则将外部字符串放入共享池中,并返回其字符串的句柄(引用)-- 这样做的好处就是能够节约空间

众所周知:String类维护一个初始为空的字符串的对象池,当intern方法被调用时,如果对象池中已经包含这一个相等的字符串对象则返回对象池中的实例,否则添加字符串到对象池并返回该字符串的引用。 
   
   从程序的角度上怎么来看这个方法呢,我们假设有两个字符串s1,s2,当s1.equals(s2)时,s1.intern()==s2.intern(),也就是说这两个字符串在内存中使用的是同一个实例。 
   
   Java语言规范中定义了字符串文字以及更一般的常量表达式的值的字符串是被内部化的,以便它们共享同一个实例。我们试验一下下面代码:

    String s1="你好,Java";
   String s2="你好,"+"Java";
   System.out.println(s1==s2);
   System.out.println(s1.intern()==s2.intern());

   这段代码将打印两个true,也就是说字符串s1和s2是共享同一个实例。不过前提是尽管使用了表达式,但是表达式中必须都是常量。 
   
  了解这个处理机制也可以让我们在用到字符串常量的时候了解如何节省这些字符串所占用的内存。

下面两个例子可以帮你:
其一:

  import   javax.swing.*;   

  public   class   StringIntern   {
          public   static   void   main(String   args[])
          {
                  String   s1,s2,s3,s4,output;
                  s1=new   String("hello");
                  s2=new   String("hello");   

                  if(s1==s2)
                          output="s1   and   s2   are   the   same   object   in   memory";
                  else
                          output="s1   and   s2   are   not   the   same   object   in   memory";   

                  if(s1.equals(s2))
                          output+="\ns1   and   s2   are   equal"   ;
                  else
                          output+="\ns1   and   s2   are   not   equal"   ;   

                  s3=s1.intern();
                  s4=s2.intern();   

                  if(s3==s4)
                          output+="\ns3   and   s4   are   the   same   object   in   memory"   ;
                  else
                          output+="\ns3   and   s4   are   not   the   same   object   in   memory"   ;   

                  if(s1==s3)
                          output+="\ns1   and   s3   are   the   same   object   in   memory";
                  else
                          output+="\ns1   and   s3   are   not   the   same   object   in   memory";   

                  if(s2==s4)
                          output+="\ns2   and   s4   are   the   same   object   in   memory";
                  else
                          output+="\ns2   and   s4   are   not   the   same   object   in   memory";   

                  if(s1==s4)
                          output+="\ns1   and   s4   are   the   same   object   in   memory";
                  else
                          output+="\ns1   and   s4   are   not   the   same   object   in   memory";   

                  JOptionPane.showMessageDialog(
                                  null,output,"Demonstrating   String   Method   intern",
                                  JOptionPane.INFORMATION_MESSAGE);   

                  System.exit(0);
          }
  } 

运行结果:

其二:  假定要加载许多数据库数据到内存,这些数据有很多是重复的。在反复测试之后,发现intern() 省了好多内存。
以下是表信息:
mysql> select count(*) from t1;
+------------+
| count(*)   |
+------------+
| 8000       |
+------------+
1 row in set (0.01 sec)
mysql> select name From t1 limit 0,1;
+--------------------------------------+
| name                                 |
+--------------------------------------+
| 123456789123456789123456789          |
+--------------------------------------+
1 row in set (0.00 sec)
总共8000行 ,每行的数据都是 "123456789123456789123456789"
下面是类 (连接异常忽略)
public static void a1() throws SQLException {
  List list = new ArrayList();
  Connection con = DB.getCon();
  Statement stmt = con.createStatement();
  ResultSet rs = stmt.executeQuery("SELECT name FROM t1");
  while (rs.next()) {
    String s = rs.getString(1);
    Po o = new Po();
   //o.setName(s); //注释掉
   o.setName(s.intern());
   list.add(o);
   s=null;
    o = null;
  }
  rs.close();
  stmt.close();
  con.close();
 }
public static void a2() throws SQLException {
  List list = new ArrayList();
  Connection con = DB.getCon();
  Statement stmt = con.createStatement();
  ResultSet rs = stmt.executeQuery("SELECT name FROM t1");
  while (rs.next()) {
   String s = rs.getString(1);
   Po o = new Po();
   o.setName(s);
   list.add(o);
   s=null;
    o = null;
  }
  rs.close();
  stmt.close();
  con.close();
 }
注意:
 a1 方法测试 使用内存: 2046544
 a2 方法测试 使用内存: 3475000
如果在函数的结尾加上 System.gc();  去除connection 的影响
 a1 方法测试 使用内存:   668856
 a2 方法测试 使用内存:2262232
然后再把 写函数 a3() ,把rs.getString(1) 换为 get()
static String get() {
  return "123456789123456789123456789123456789123456789";
 }
public static void a3() throws SQLException {
  List list = new ArrayList();
  Connection con = DB.getCon();
  Statement stmt = con.createStatement();
  ResultSet rs = stmt.executeQuery("SELECT name FROM t1");
  while (rs.next()) {
    String s = get();
    Po o = new Po();
    o.setName(s);
    list.add(o);
    s=null;
    o = null;
  }
  rs.close();
  stmt.close();
  con.close();
 }
a3 方法测试 使用内存:666536
a2 (668856)比a3 的内存使用量多了一点点,这个估计就是常量池那一点内存
8000条数据 差别这么大, 数据量再大的话,优势更加明显.建议大家在连接数据库查询出来的数据,用intern();
注:内存使用 用 Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory() 计算
时间: 2024-11-19 03:00:20

了解String类的intern()方法的相关文章

String类的intern()方法

public native String intern(); 这个是在String类源码中申明的一个方法,是一个本地方法,返回的是一个String对象的引用.先看一下代码: String s1="123"; String s2 = new String("123"); System.out.println(s1==s2);//false System.out.println(s1==s2.intern());//true s1==s2结果为false,这个不再详述.

测试String类的intern方法

<pre name="code" class="java">package com.ckw.mianshi; /** * 测试String类的intern方法 * @author Administrator *intern():返回一个字符串,内容与此字符串相同,但它保证来自字符串池中. */ public class StringOfIntern { public static void main(String[] args) { /** * 例1 *

String类中intern方法的原理分析

一,前言 ? 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今天就弥补昨天缺失的知识点. 二,String.intern() ? 先来看下网上流行的关于intern()方法的示例代码: public static void main(String[] args) { String s = new String("1"); s.intern(); St

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

0.引言 转载请注明出处:http://write.blog.csdn.net/postedit/52291082 什么都先不说,先看下面这个引入的例子: String str1 = new String("SEU")+ new String("Calvin"); System.out.println(str1.intern() == str1); System.out.println(str1 == "SEUCalvin"); 本人JDK版本1

JAVA中String类的intern()方法的作用

一般我们平时很少使用到 intern这个方法,今天我就来解释一下这个方法是干什么的,做什么用的 首先请大家看一个例子: [java] view plaincopyprint? public static void main(String[] args) throws Exception { String a =  "b" ; String b =  "b" ; System.out.print( a == b); String c = "d" ;

java基础知识回顾之---java String final类之intern方法

public class StringObjectDemo { /** * @param args */ public static void main(String[] args) { String hello = "Hello", lo = "lo"; System.out.print((hello == "Hello") + " ");//true System.out.print((Other.hello == hel

java.lang.String 类的所有方法

java.lang.String 类的所有方法 方法摘要 char charAt(int index) 返回指定索引处的 char 值. int codePointAt(int index) 返回指定索引处的字符(Unicode 代码点). int codePointBefore(int index) 返回指定索引之前的字符(Unicode 代码点). int codePointCount(int beginIndex, int endIndex) 返回此 String 的指定文本范围中的 Un

关于JAVA的String类的一些方法

一.得到字符串对象的有关信息 1.通过调用length()方法得到String的长度. String str=”This is a String”; int len =str.length(); 2.StringBuffer类的capacity()方法与String类的 length()的方法类似,但是她测试是分配给StringBuffer的内存空间的大小,而不是当前被使用了的内存空间. 3.如果想确定字符串中指定字符或子字符串在给定字符串的位置,可以用 indexOf()和lastIndexO

【java】String类的基本方法

Java的String类基本方法 一.构造函数 函数 返回值 作用 String(byte[] bytes) String 通过byte数组构造字符串对象 String(char[] chars) String 通过char数组构造字符串对象 String(String string) String 拷贝一个值为string的字符串对象 String(StringBuffer buffer) String 通过StringBuffer构造字符串对象 二.String类的基本方法 函数 返回值 作