1.String简介

  1. String类实现CharSequence接口。(同时,实现Serializable, Comparable 接口)。
  2. String类使用final修饰符,为final类,不可被继承,同样的,其方法自然就不可被覆盖。
  3. String 内部通过数组来实现。
  4. Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其append 方法实现的。
  5. 字符串在java内存中总是按unicode编码存储的。

2.CharSequence接口定义

public interface CharSequence {
int length();
/*@throws IndexOutOfBoundsException*/
char charAt(int index);
/* @throws IndexOutOfBoundsException */
CharSequence subSequence(int start, int end);
public String toString();
}

已知的实现类有 CharBuffer, Segment, String, StringBuffer, StringBuilder。

3.String类详解

  • 变量
// 类静态常量
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
private static final int HASHING_SEED; // 在statick块中初始化了
private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
private static final long serialVersionUID = -6849794470754667710L;

// 成员变量
private final char value[];// 用于存储字符串
private int hash;// 存储String的hash值
private transient int hash32 = 0;// Cached value of the alternative hashing algorithm result
  • 构造函数
public    String()
public String(String original)
public String(char[] value)
public String(char[] value, int offset, int count)
public String(byte[] bytes)
public String(byte[] bytes, int offset, int length)
public String(byte[] ascii, int hibyte)
public String(byte[] ascii, int hibyte, int offset, int count)
public String(byte[] bytes, String charsetName)
public String(byte[] bytes, int offset, int length, String charsetName)
public String(byte[] bytes, Charset charset)
public String(byte[] bytes, int offset, int length, Charset charset)
public String(int[] codePoints, int offset, int count)
public String(StringBuffer buffer)
public String(StringBuilder builder)

// 部分构造函数代码 // 思考:为什么一般不用这个构造方法? 因为String是不可变类,使用此构造方法没什么用。
public String(){
this.value = new char[0];
} public String(String original) {
this.value = original.value;
this.hash = original.hash;
} public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
} // 通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String
// 扩展学习1:平台默认字符集 指的是操作系统默认的字符集,同时可通过 -Dfile.encoding="GBK"来设置jvm字符集
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
} // 通过使用指定的charset解码指定的 byte 子数组,构造一个新的 String
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null)
throw new NullPointerException("charsetName");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charsetName, bytes, offset, length);
} public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
} public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

演示程序

字符编码

        //切记一点:字符串在java内存中总是按unicode编码存储的!!

        System.out.println("平台默认字符集 = " + Charset.defaultCharset()); // 在eclipse中 可将 text-file-encoding 改为其它试试看
String str1 = "中文"; // 中文 unicode编码
byte[] b1 = str1.getBytes("unicode");
System.out.print("unicode编码 = ");
for(byte b : b1){
System.out.print(Integer.toHexString(b & 0xFF) + " ");
}
System.out.println();
String str2 = new String(b1, "unicode");
System.out.println(str2); // 中文utf-8编码 utf8中部分汉字占3个字节,有21000多个(大部分是原GBK中的字符); 部分汉字占4个字节 中日韩超大字符集里面的汉字,有 5 万多个
b1 = str1.getBytes();
System.out.print(Charset.defaultCharset() + "编码 = ");
for(byte b : b1){
System.out.print(Integer.toHexString(b & 0xFF) + " ");
}
System.out.println(); // 中文gbk编码
b1 = str1.getBytes("gbk");
System.out.print("gbk编码 = ");
for(byte b : b1){
System.out.print(Integer.toHexString(b & 0xFF) + " ");
}
System.out.println(); // 中文iso8859-1编码
b1 = str1.getBytes("iso8859-1");
System.out.print("iso8859-1编码 = ");
for(byte b : b1){
System.out.print(Integer.toHexString(b & 0xFF) + " ");
}
System.out.println(); // 中文 在ios8859-1编码下打印出来为乱码
String str5 = new String(b1, "iso8859-1");
System.out.println(str5); // unicode编码
String str13 = new String(new int[] {0x4e2d, 0x6587}, 0, 2);
System.out.println(str13); // utf-8编码 0xE4B8AD 0xE69687
String str09 = new String(new byte[]{
(byte)0xE4, (byte)0xB8, (byte)0xAD,
(byte)0xE6, (byte)0x96, (byte)0x87},0, 6, "utf-8");
System.out.println(str09); // GBK编码 0xD6D0 0xCEC4
String str12 = new String(new byte[]{
(byte)0xD6,(byte)0xD0,
(byte)0xce,(byte)0xc4}, 0, 4,"GBK");
System.out.println(str12);

jvm 对 String的优化

        // “中文”的unicode编码  =  0x4e2d 0x6587
char[] v1 = {0x4e2d, 0x6587};
String str14 = new String(v1); // new,存放在堆中 String str15 = "中文"; // 存放在常量池中(常量池自jdk7后移入堆中)
System.out.println(str15 == str14); String str16 = "中文"; // 此处常量池中已有“中文”,不再创建新的对象,
System.out.println(str15 == str16); String str17 = "中" + "文"; // 编译时优化, 在编译时,即将其转为“中文”
System.out.println(str15 == str17); String w = "文";
String str18 = "中" + w; // 有变量w, 编译期间不能确定其值,无法合并, 运行时会new一个新的对象
System.out.println(str15 == str18); String str19 = new String("中文");
System.out.println(str15 == str19); String str20 = str14.intern(); // intern(), 在常量池通过equals方法寻找“中文”,此时,常量池中已有str15,则将常量池中“中文”对象的引用
System.out.println(str20 == str15); // true System.out.println(Integer.toHexString(str15.hashCode()));
System.out.println(Integer.toHexString(str20.hashCode()));

部分函数实现

public char    charAt(int index)
public int compareTo(String anotherString)
public boolean endsWith(String suffix)
public boolean equals(Object anObject)
public String intern()
public String replace(char oldChar, char newChar)
public boolean startsWith(String prefix, int toffset)
public boolean startsWith(String prefix)
public String substring(int beginIndex)
public String substring(int beginIndex, int endIndex)
public String trim()
/**
*1.若长度不相等,返回长度差值;
2.若长度相等,则依次比较相同位置char, 若某个char不相等,则返回char差值;
由此可见,若结果大于0,则当前字符串大; 若结果等于0,则两字符串相等; 若结果小于0,则参数中的字符串大。
*/
  public int compareTo(MyString anString){
int len1 = value.length;
int len2 = anString.value.length; int limin = Math.min(len1, len2); char v1[] = value;
char v2[] = anString.value; int k = 0;
while(k < limin){
char c1 = v1[k];
char c2 = v2[k];
if(c1 != c2)
return c1 - c2;
k++;
}
return len1 - len2;
}
 /*
* 1. == 号比较,(两个变量在栈中存放的内容),若相等, true
2. 若参数不属于String类型,false
3. 若长度不等,false
4. 若长度相等,则从后向前,依次比较char,若出现不等, false
*/
1 public boolean equals(Object anObject){
if(this == anObject){
return true;
}
if(anObject instanceof String){
String anotherString = (String) anObject;
int n = value.length;
if(n == anotherString.length()){
char v1[] = this.value;
char v2[] = anotherString.value;
int i = 0;
while(n-- != 0){
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
    /*
* replace方法并没有一上来就创建新数组,循环复制;
* 而是
* 第一步 找出oldChar第一次出现的位置【index】
* 第二步 创建新数组,将【index】之前的char复制到新数组
* 第三步 再从index的位置开始循环比较, 将剩余的char添加到新数组
* 代码妙处:只有原串中出现了 oldChar, 这时才创建新数组,赋值;既没有重复比较操作,又避免了从头到尾的零差异复制操作。
*/
public MyString replace(char oldChar, char newChar){
if(oldChar != newChar){
int len = value.length;
char val[] = value; int i = -1;
while(i++ < len){
if(val[i] == oldChar){
break;
}
}
if(i <= len){
char buf[] = new char[len];
for(int j = 0; j<i; j++){
buf[j] = val[i];
}
while (i < len){
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new MyString(buf,true);
}
}
return this;
}
   public String trim(){
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */扩展学习2: getfield指令 及 String此处的优化在哪里 while((st < len ) && (val[st] <= ' ')){
st ++;
}
while((st < len) && (val[len - 1] <= ' ')){
len --;
}
return ((len < value.length) || (st>0)) ? subString(st, len) : this;
}
     public boolean startsWith(MyString prefix){
return startsWith(prefix,0);
} public boolean endsWith(MyString suffix) {
return startsWith(suffix, value.length - suffix.value.length);
} public boolean startsWith(MyString prefix, int toffset){
char[] ta = value;
int to = toffset;
char[] pa = prefix.value;
int po = 0;
int pc = prefix.value.length;
// Note: toffset might be near -1>>>1.
/*
* 扩展学习3:逻辑右移或叫无符号右移运算符“>>>“只对位进行操作,没有算术含义,它用0填充左侧的空
* -1 >>> 1 = int型最大值 2147483647
*-1 二进制 11111111 11111111 11111111 11111111
*-1 >>> 1 二进制 1111111 11111111 11111111 11111111
*/
if((toffset < 0) || (toffset > value.length - pc)){
return false;
}
while(--pc >= 0){
if(ta[to++] != pa[po++]){
return false;
}
}
return true;
}
     @Override
public CharSequence subSequence(int start, int end) {
return this.subString(start, end);
} public MyString substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new MyString(value, beginIndex, subLen);
} public MyString subString(int beginIndex, int endIndex){
if(beginIndex < 0){
throw new StringIndexOutOfBoundsException(beginIndex);
}
if(endIndex > value.length){
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if(subLen < 0){
throw new StringIndexOutOfBoundsException(subLen);
} return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new MyString(value, beginIndex, subLen);
}
  public native String intern();
//intern方法是Native调用,它的作用是在常量池里通过equals方法寻找等值的对象,如果没有找到则在常量池中开辟一片空间存放字符串并返回该对应String的引用,
否则直接返回常量池中已存在String对象的引用
 
 
 

String系列01 - String 60%的更多相关文章

  1. 实战c++中的string系列--std::string与MFC中CString的转换

    搞过MFC的人都知道cstring,给我们提供了非常多便利的方法. CString 是一种非常实用的数据类型. 它们非常大程度上简化了MFC中的很多操作,使得MFC在做字符串操作的时候方便了非常多.无 ...

  2. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  3. java‘小秘密’系列(一)---String、StringBuffer、StringBuilder

    java'小秘密'系列(一)---String.StringBuffer.StringBuilder 前言:本系列的主题是平时容易疏忽的知识点,只有基础扎实,在编码的时候才能更注重规范和性能,在出现b ...

  4. java基础解析系列(九)---String不可变性分析

    java基础解析系列(九)---String不可变性分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---In ...

  5. java基础解析系列(一)---String、StringBuffer、StringBuilder

    java基础解析系列(一)---String.StringBuffer.StringBuilder 前言:本系列的主题是平时容易疏忽的知识点,只有基础扎实,在编码的时候才能更注重规范和性能,在出现bu ...

  6. 实战c++中的string系列--std:vector 和std:string相互转换(vector to stringstream)

    string.vector 互转 string 转 vector vector  vcBuf;string        stBuf("Hello DaMao!!!");----- ...

  7. Java String系列

    String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1) StringBuilder 详解 (String ...

  8. String系列

    String 简介 String 是java中的字符串,它继承于CharSequence.String类所包含的API接口非常多.为了便于今后的使用,我对String的API进行了分类,并都给出的演示 ...

  9. [Java] 01 String 内存分析

    public class StringTest{ public static void main(String[] args){ String str1 = new String("123& ...

随机推荐

  1. antd-mobile的按需加载

    "babel": { "presets": [ "react-app" ] } 主要问题是 依赖项的版本问题 以及 配置问题 新添加的con ...

  2. Linux下vim(文本编译器)的使用

    vim (文本编译器): Vim是从 vi 发展出来的一个文本编辑器. vim的一些命令操作: 插入命令: a 在光标所在字符后插入 A 在光标所在行尾插入 i 在光标所在字符前插入 I 在光标所在行 ...

  3. [译] Z-variant (Z变体)

    阅读目录 1. Z轴上的区别 2. 问题 Unihan 的 kZVariant 字段 译自: en.wikipedia.org/wiki/Z-variant | 已发布zh.wiki 在Unicode ...

  4. java 中sendredirect()和forward()方法的区别

     一.文章1 HttpServletResponse.sendRedirect与RequestDispatcher.forward方法都可以实现获取相应URL资源. sendRedirect实现请求重 ...

  5. ZOJ Problem Set – 2321 Filling Out the Team

    Time Limit: 2 Seconds      Memory Limit: 65536 KB Over the years, the people of the great city of Pi ...

  6. web application 访问控制

    http://secappdev.org/handouts/2012/Jim%20Manico%20%26%20%20Eoin%20Keary/Final%20-%20Access%20Control ...

  7. Sqlserver函数基础使用

    函数基本功能: 转换工厂日期,将8点20之前的时间转化为前一天的时间. if exists (select * from sysobjects where xtype='fn' and name='F ...

  8. Storm 实现滑动窗口计数和TopN排序

    计算top N words的topology, 用于比如trending topics or trending images on Twitter. 实现了滑动窗口计数和TopN排序, 比较有意思,  ...

  9. Python学习---抽屉框架分析[ORM操作]180314

    Django ORM操作     1. 字段操作         class User(model.Model);             u=字段        用处:            1 . ...

  10. Python学习---生成器的学习1210

    在Python中,这种一边循环一边计算的机制,称为生成器: 结论: 生成器本质是一个函数,不同于函数的是它生成的是一个对象,不执行函数内的代码 1.1. 列表生成器 列表生成器: 列表是直接生成数字在 ...