深入java String.intern()

public String intern()  返回字符串對象的規範化表示形式。

一個初始時爲空的字符串池,它由類 String 私有地維護。 當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,並且返回此 String 對象的引用。它遵循對於任何兩個字符串 s 和 t,當且僅當 s.equals(t) 爲 true 時,s.intern() == t.intern() 才爲 true。


下來看看這方面的一個很好的例子

在例子之前我們先假設我們在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()方法就是完成的這個功能,其返回的只是裏面的同一個字符串,而沒有創建新的字符串,所以不會佔用太多的空間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章