[转]了解String类的intern()方法

   相信绝大多数的人不会去用String类的intern方法,打开String类的源码发现这是一个本地方法,定义如下: 
   public native String intern(); 
   
   文档告诉我们该方法返回一个字符串对象的内部化引用。
众所周知: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() 计算



转自: http://www.java3z.com/cwbwebhome/article/article2/21063.html?id=1833 谢谢原作者。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值