String

String是由Char值序列组成

代码点(Code Point):Unicode是属于编码字符集(CCS)的范围。Unicode所做的事情就是将我们需要表示的字符表中的每个字符映射成一个数字,这个数字被称为相应字符的码点(code point)。例如“严”字在Unicode中对应的码点是U+0x4E25。

代码点是字符集被编码后出现的概念。字符集(Code Set)是一个集合,集合中的元素就是字符,比如ASCII字符集,其中的字符就是’A’、’B’等字符。为了在计算机中处理字符集,必须把字符集数字化,就是给字符集中的每一个字符一个编号,计算机程序中要用字符,直接用这个编号就可以了。于是就出现了编码后的字符集,叫做编码字符集(Coded Code Set)。编码字符集中每一个字符都和一个编号对应。那么这个编号就是代码点(Code Point)。

代码单元(Code Unit):是指一个已编码的文本中具有最短的比特组合的单元。对于UTF-8来说,代码单元是8比特长;对于UTF-16来说,代码单元是16比特长。换一种说法就是UTF-8的是以一个字节为最小单位的,UTF-16是以两个字节为最小单位的。

代码单元是把代码点存放到计算机后出现的概念。一个字符集,比如有10个字符,每一个字符从0到9依次编码。那么代码点就是0、1、。。。、9。为了在计算机中存储这10个代代码点,一个代码点给一个字节,那么这里的一个字节就是一个代码单元。比如Unicode是一个编码字符集,其中有65536个字符,代码点依次为0、1、2、。。。、65535,为了在计算机中表示这些代码点就出现了代码单元,65536个代码点为了统一表示每个代码点必须要有两个字节表示才行。但是为了节省空间0-127的ASCII码就可以不用两个字节来表示,只需要一个字节,于是不同的表示方案就形成了不同的编码方案,比如utf-8、utf-16等。对utf-8而言代码单元就是一个字节,对utf-16而言代码单元就是两个字节。

Java基本类型占用的字节数:
1字节: byte , boolean
2字节: short , char
4字节: int , float
8字节: long , double
注:1字节(byte)=8位(bits)

    String[] arrays1 = {"1","!","H","!","你"};
    for (String str : arrays1) {
        System.out.print("字符串"+"\""+str+"\"    ");
        System.out.print("代码点:" + str.codePointAt(0)+"    ");
        System.out.print("代码单元:" + str.charAt(0)+"    ");
        System.out.print("GBK:" + str.getBytes("GBK").length+"    ");
        System.out.print("GB2312:"+str.getBytes("GB2312").length+"    ");
        System.out.print("UTF-8:" + str.getBytes("UTF-8").length+"    ");
        System.out.print("UTF-16:" + str.getBytes("UTF-16").length);
    }

字符串”1” 代码点:49 代码单元:1 GBK:1 GB2312:1 UTF-8:1 UTF-16:4
字符串”!” 代码点:33 代码单元:! GBK:1 GB2312:1 UTF-8:1 UTF-16:4
字符串”H” 代码点:72 代码单元:H GBK:1 GB2312:1 UTF-8:1 UTF-16:4
字符串”!” 代码点:65281 代码单元:! GBK:2 GB2312:2 UTF-8:3 UTF-16:4
字符串”你” 代码点:20320 代码单元:你 GBK:2 GB2312:2 UTF-8:3 UTF-16:4

GBK和UTF-8
数字,符号,英文都占用一个字节。
中文,中文符号GBK占用两个字节,UTF-8占用3字节

public char charAt(int index)
返回指定索引处的 char 值。

    String str = "Hello";
    char c = str.charAt(0);
    System.out.println(c); //H

public int codePointAt(int index)
返回指定索引处的 代码点。

    String str = "Hello";
    int i = str.codePointAt(0);
    System.out.println(i); //72

public int codePointCount(int beginIndex, int endIndex)
返回此 String 的指定文本范围中的 Unicode 代码点数

    String str = "Hello";
    int i = str.codePointCount(0, str.length());
    System.out.println(i); //5

public int indexOf(int ch, int fromIndex)
返回该字符串中第一个出现的字符串中的索引。ch是代码点,从fromIndex索引开始计算。

    String str = "CACACCC";
    int i = str.indexOf(65, 2);
    System.out.println(i); //3 

public int indexOf(String str, int fromIndex)
返回该字符串中第一个出现的字符串中的索引。str是字符串,从fromIndex索引开始计算。

    String str = "CACACCC";
    int i = str.indexOf("CA", 2);
    System.out.println(i); //2

public int lastIndexOf(String str)
返回指定字符串在这个字符串中最后出现的位置。

    String str = "ABAB";
    int i = str.lastIndexOf("A");
    System.out.println(i); //2

public boolean startsWith(String prefix)
判断此字符串是否以指定的前缀开始。

    String str = "abc";
    boolean b = str.startsWith("b");
    System.out.println(b); //false

public boolean endsWith(String suffix)
判断此字符串是否以指定的后缀结尾。

    String str = "abc";
    boolean b = str.endsWith("c");
    System.out.println(b); //true

public String substring(int beginIndex, int endIndex)
返回一个新字符串,这个字符串包含原字符串从beginIndex开始到endIndex - 1的所有单元代码。

    String str = "Hello";
    str = str.substring(2,5);
    System.out.println(str); //llo

public String replace(CharSequence target, CharSequence replacement)
返回一个新字符串,这个字符串用replacement代替原字符串中所有的target。
target 被替换的字符串
replacement 替换的字符串

    String str = "Hello";
    str = str.replace("l", "if");
    System.out.println(str); //Heififo

public String replaceFirst(String regex, String replacement)
代替这个字符串的替换,给定的正则表达式匹配的第一个子字符串。
regex 被替换的字符
replacement 替换的字符

    String str = "Hello";
    str = str.replaceFirst("l", "if");
    System.out.println(str); //Heiflo

public boolean matches(String regex)
在字符串匹配给定的正则表达式时,返回 true。

    String str = "18888888888";
    boolean b  = str.matches("^1[3|4|5|7|8][0-9]\\d{8}$");
    System.out.println(b); //true

public String[] split(String regex)
返回一个字符数组,将字符串与给定的正则表达式匹配,然后分离成多个子字符串。

    String str = "3.14";
    String[] strs  = str.split("\\.");
    System.out.println(strs[0]+"---"+strs[1]); //3---14

public String toUpperCase()
返回一个新字符串,把原始字符串改为大写。

    String str = "Hello";
    str = str.toUpperCase();
    System.out.println(str); //HELLO

public String toLowerCase()
返回一个新字符串,把原始字符串改为小写。

    String str = "HELLO";
    str = str.toUpperCase();
    System.out.println(str); //hello

public boolean equalsIgnoreCase(String anotherString)
不区分大小写比较两个字符串。

    String str = "HELLO";
    "hello".equalsIgnoreCase(str); //true

public boolean contains(CharSequence s)
字符串是否包含 *Char的子序列

    String str = "Hello";
    boolean b = str.contains("e");
    System.out.println(b); //true

public boolean contentEquals(CharSequence cs)
比较字符串,可以是CharSequence的子类

    String str = "Hello";
    StringBuilder builder = new StringBuilder("Hello");
    System.out.println(str.equals(builder)); //false
    System.out.println(str.contentEquals(builder)); //true

public int compareTo(String anotherString)
按照字典顺序比较两个字符串,如果字符串位于anotherString之前就返回负数,如果在anotherString之后返回正数,相等返回0。

    String str = "a";
    int i = str.compareTo("b"); //97 < 98   
    System.out.println(i); //-1

public byte[] getBytes(String charsetName)
将字符串转化为一系列字节用指定的字符集,并将结果存储到一个新的字节数组。

    String str = "Hello";
    byte[] b = str.getBytes("UTF-8");
    String s = new String(b);
    System.out.println(s); //Hello

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
将此字符串中的字符复制到目标字符数组中。
srcBegin 指标字符串中第一个字符复制。
srcEnd 在字符串中的最后一个字符复制后指数。
dst char[]字符数组。
dstBegin 在char[]的起始偏移。

    String str = "我爱这个世界";
    char[] c = new char[str.length()];
    str.getChars(2, 4, c, 0); //这个
    str.getChars(4, 6, c, 2); //这个世界。"世界"这个字符串往右边偏移2位
    str.getChars(1, 2, c, 4); //这个世界爱。"爱这"个字符串向右边偏移4位
    str.getChars(0, 1, c, 5); //这个世界爱我。"我"这个字符串向右偏移5位
    System.out.println(String.valueOf(c)); //这个世界爱我

public static String copyValueOf(char[] data, int offset, int count)
把char[]复制到字符串并返回。
data 参数数据的字符数组。
offset 偏移量。
count 要复制的字符长度

    char[] c = {'a','b','c','d'};
    String str = String.copyValueOf(c, 1, 2);
    System.out.println(str); //bc

public static String join(CharSequence delimiter, CharSequence… elements)
在指定 String 数组的每个元素之间串联指定的分隔符 String,从而产生单个串联的字符串
delimiter 分割符
elements 元素

    String all = String.join("/", "S","M","L");
    System.out.println(all);

    List<String> list = new ArrayList<>();
    list.add("I");
    list.add("Love");
    list.add("You");
    String str = String.join("-", list);
    System.out.println(str);//I-Love-You

public boolean isEmpty()
判断字符串是否为空,如果是返回true。相当于String.length() == 0

    String str = "";
    boolean b  = str.isEmpty();
    System.out.println(b); //true

public native String intern();
字符串常量池中查找相应的字符串找到并返回。

常量池

常量池分为两种:静态常量池和运行时常量池。
静态常量池:Class文件中的常量池
常量池中主要存放两类常量:字面量和符号引用。字面量比较接近Java语言层面的常量概念。
就是我们什么提到的常量。 而符号引用则属于编译原理的方面的概念。包括以下三类常量:
i> 类和接口的全限定名
ii>字段的名称和描述符
iii>方法的名称和描述符

运行时常量池:运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、
接口等描述信息外还有 一项信息是常量池。用于存放编译期生成的字面量和符号应用,这部分内
容将在类加载后进入方法区的时候存到运行时常量池中。运行时常量池还有个更重要的的特征:
动态性。Java要求,编译期的常量池的内容可以进入运行时常量池,运行时产生的常量也可以
放入池中。常用的是String类的intern()方法。

常量池的好处
常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。
例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
(1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
(2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用
是否相等,也就可以判断实际值是否相等。

先在栈中创建一个String类型的对象引用变量a,然后去常量池中找是否有”goodluck”字符串,
如果没有就将”goodluck”放入常量池中,如果有了就直接将a指向”goodluck”,在这里产生
一个对象”goodluck”,产生一个引用a。
String a = “goodluck”;
先在栈中创建一个String类型对象引用变量b,然后去常量池中找是否有“goodluck”字符串,
如果有了就直接将b指向”goodluck”,在这里产生一个引用a,没有再一次产生队象”goodluck”。
String b = “goodluck”;

先在栈中创建一个String类型的引用对象变量newA,然后new()操作,会在heap堆中创建一个
新的对象”goodluck”,然后将地址赋值给newA,newA指向堆中的“gooluck”,同时检查String
的常量池中是否 有对象”goodluck”,如果没有就在字符串常量池中创建,如果有则不产生。
String newA =new String(“goodluck”);

int a; //a变量
int b=10; //b为变量,10为字面量
string str=”hello world”; //str为常量,hello world为也字面量
字面量是指由字母,数字等构成的字符串或者数值,它只能作为右值出现,所谓右值是指等号右边的值,
如:int a=123这里的a为左值,123为右值。
常量和变量都属于变量,只不过常量是赋过值后不能再改变的变量,而普通的变量可以再进行赋值操作。
1) 字符串字面量和常量称为“静态字符串”
2) 字面量和常量的连接在编译期间执行,优化为一个静态字符串
3) 在运行期间,Java在静态缓冲池中创建静态字符串,并且尽量使用同一个字符串对象。
4) 动态字符串:字符串运算结果,或者连接结果或者 new运算创建的字符串,等运行期间创建的字符串不参与静态优化

public static void test1() {
        //在Class静态常量池中存了常量"a",然后把常量a的地址赋给了str1
        String str1 = "a"; 
        //在Class静态常量池中寻找是否存在常量"a",所以str2直接引用常量"a"
        String str2 = "a"; 
        System.out.println(str1==str2); //true
        System.out.println(str1.equals(str2)); //true
        System.out.println(str1.intern() == str2.intern()); //true
    }

    public static void test2() {
        //str1 在Class静态常量池创建了"a",str1 指向了常量池的a
        String str1 = "a"; 
        //str2先在堆中创建了对象"a",然后又在运行常量池中查找是否存在常量"a",发现存在就不创建
        String str2 = new String("a"); 
        //str3先在堆中创建了对象"a",然后又在运行常量池中查找是否存在常量"a",发现存在就不创建
        String str3 = new String("a"); 

        System.out.println(str1==str2); //false
        System.out.println(str1.equals(str2)); //true
        System.out.println(str1.intern() == str2.intern()); //true
        System.out.println(str2==str3); //false
        System.out.println(str2.equals(str3)); //true
        System.out.println(str2.intern() == str3.intern()); //true

    }

    public static void test3() {
        //str1先在堆中创建了对象"a",然后又在运行时常量池中查找是否存在常量"a",发现不存在就创建常量"a"
        String str1 = new String("a"); 
        //str2先在堆中创建了对象"b",然后又在运行时常量池中查找是否存在常量"b",发现“存在”就直接引用常量"b"
        String str2 = new String("b"); 
        //因为在编译器就已经把"b"的字面量存在了class的静常量池
        String str3 = "b"; 

        System.out.println(str1==str2);//false
        System.out.println(str1.equals(str2));//false
        System.out.println(str1.intern() == str2.intern());//false
        System.out.println(str2==str3);//false
        System.out.println(str2.equals(str3));//true
        System.out.println(str2.intern() == str3.intern());//true

    }

    public static void test4() {
        //编译期编译优化时拼接,在Class静态常量池中创建"abc"对象
        String str1 = "a" + "b" + "c";
        //由于Class静态常量池存在"abc"常量,所以不再创建,直接引用常量"abc"
        String str2 = "abc"; 

        System.out.println(str1==str2);//true
        System.out.println(str1.equals(str2));//true
        System.out.println(str1.intern() == str2.intern());//true
    }

    public static void test5() {

        String str1 = "a";
        String str2 = "b";
        String str3 = "c";
        String str4 = "d";
        //编译期编译优化为abcd,然后在字符串常量池创建abcd
        String str5 = "a" + "b" + "c" + "d"; 
        String str6 = "abcd";
        System.out.println(str5==str6);//true
        System.out.println(str5.equals(str6));//true
        System.out.println(str5.intern() == str6.intern());//true

    }

    public static void test6() {
        String str1 = "a";
        String str2 = new String("a");
        String str3 = new String("b");
        System.out.println(str1 == str2.intern());//true
        //把str1运行常量池的字符串"a"的地址赋值给str3
        str3 = str1.intern();
        System.out.println(str1 == str3);//true

    }

    //String str4 = str1 + str2 + str3;
    //创建了三个对象
    //1 StringBuilder
    //2 new char[capacity] 
    //3 new String(value,0,count) StringBuilder的toString()方法
    //如果字符数超过16 就会调用expandCapacity(newCount); 重新分配,就会多创建一个对象。字符长度*2
    public static void test7() {
        //在Class静态常量池中存了常量"b",然后把常量a的地址赋给了str1
        //编译时变成了 "ab" + str1 ,运行时然后在运行时常量池寻找"ab"发现没有又创建。
        //StringBuilder.append("ab").append("b").toString();
        //一共创建了四个个对象
        //"ab" ,StringBuilder,new char[capacity],new String(value,0,count)
        String str1 = "b";
        String str2 = "a" + "b"+ str1; 
        String str3 = "abb";
        System.out.println(str2==str3);//false
        System.out.println(str2.equals(str3));//true
        System.out.println(str2.intern() == str3.intern());//true
    }

    public static void test8() {
        //StringBuilder builder = new StringBuilder();
        //builder.append("Str");
        //builder.append("ing");
        //builder.toString();
        //一共创建了7个对象 
        //StringBuider,
        //堆中的String,Str,ing
        //常量池中的String,Str,ing;
        String str1 = new String("Str") + new String("ing"); 
    }

http://blog.csdn.net/gcw1024/article/details/51026840
http://blog.csdn.net/shi1122/article/details/8053605
http://blog.csdn.net/java2000_net/article/details/3681385

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值