精华内容
下载资源
问答
  • String类的常用方法总结

    千次阅读 多人点赞 2019-02-24 19:20:51
    Java中的String类是字符串操作,提供了多种方法对字符串进行操作,以下对String类的常用方法进行总结: ...java把String类声明的final,对象创建后不可修改,由0或多个字符组成,包含在一对双引号之间。 二...

    Java中的String类是字符串操作类,提供了多种方法对字符串进行操作,以下对String类的常用方法进行总结:

    一、String类简介

    String类位于Java的lang包下,在使用时不需要通过import引入,java使用String类创建一个字符串变量,字符串变量属于对象。java把String类声明的final类,对象创建后不可修改,由0或多个字符组成,包含在一对双引号之间。

    二、String类创建对象

    用String类创建对象通常有两种形式:

    1、String str = "chengjunyu";

    2、String str1 = new String("chengjunyu");

    方法1通过字面量直接给字符串进行赋值,在栈中创建字符串str时,会先在字符串常量池中检查是否已有该字符串,如果没有则创建并存入字符串常量池中,如果已存在则直接从常量池中获取。

    方法2创建的字符串,不管内存有没有为“chengjunyu”字符串分配内存,都会在内存中重新分配一个内存区域存放“chengjunyu”,然后用str1指向它,相当于内存中有两个“chengjunyu”,只是存放的地址不一样。

    三、String类的构造方法

    1、public String();

    String类的无参构造方法,用来创建空字符串的String类;

    案例:String str = new String();

    2、public String(String value);

    用已知的字符串value值来创建一个字符串对象;

    案例:String str1 = new String("aaa");

    3、public String(char[] value)

    用字符数组value创建一个String对象。

    案例:char[] value = {"ab","cd","efg"};

               String str1 = new String(value);       (等同于new String("abcdefg"));

    4、public String(char[] value, int startIndex, int numChars)

    用字符数组chars的startIndex开始的numChars个字符创建一个String对象。

    案例:char[] value = {"ab","cd","ef","g"};

              String str2 = new String(value,1,2);     (等同于new string("cdef"));

    5、public String(byte[] values)

    用byte的数组value值来创建字符串对象。

    案例:byte[] values = new byte[]{"a","b","c","d","e"};

               String str3 = new String(values);      (等同于new String("abcde"))

    四、String类的常用方法

    1、获取字符串长度:

    str.length();

    案例:

    2、获取字符在字符传中出现的位置:

    str.indexOf(String str);

    从头开始查找str在字符串中第一次出现的位置;

    str.indexOf(String str,int fromIndex);

    从下标fromIndex处开始开始查找str在字符串中第一次出现的位置;

    str.lastIndexOf(String str);

    从尾部开始查找str在字符串中最后一次出现的位置;

    str.lastIndexOf(String str,int fromIndex);

    从下标fromIndex处开始开始查找str在字符串中最后一次出现的位置;

    案例:

    3、获取字符串中某一个位置的字符:

    str.charAt(int index);

    查找字符串中下标为index位置出现的字符串

    案例:

    4、截取字符串:

    str.substring(fromIndex,endIndex);

    从fromIndex处开始截取到endIndex处结束,不包含下标为endIndex的字符;

    str.substring(fromIndex);

    从fromIndex处开始截取到最后;

    案例:

    5、验证字符串开始或结束的字符:

    开始位置字符:str.startWith(String str1),返回Boolean值;

    结束位置字符:str.endWith(String str1),返回Boolean值;

    案例:

    6、字符串的比较:

    int num = str.compareTo(String str1);

    对字符串内容按字典顺序进行大小比较,通过返回的整数值指明当前字符串与参数字符串的大小关系。若当前对象比参数大则返回正整数,反之返回负整数,相等返回0。

    int num = str.compareToIgnore(String str1);

    和compareTo()方法类似,忽略大小写。

    boolean b = str.equals(Object obj);

    比较当前字符串和参数字符串,在两个字符串相等的时候返回true,否则返回false。

    boolean b = str.equalsIgnoreCase(Object obj);

    和equals方法类似,忽略大小写。

    案例:

    7、字符串连接:

    str2 = str.concat(String str1);

    用concat连接两个字符城成为一个新的字符串。

    案例:

    8、字符串中字符的大小写转换:

    小写转大写:str.toUpperCase();

    大写转小写:str.toLowerCase();

    案例:

    9、字符串中字符的替换:

    str.replace(oldStr,newStr);

    用新的字符代替就得字符。

    案例:

    10、字符串中清除空格:

    str.trim();

    清除字符串str两侧的空字符串。

    案例:

    11、字符传中分割字符串为数组:

    str.split(String str1);

    用str1将字符串str分割成数组。

    案例:

    展开全文
  • String声明

    千次阅读 2017-08-07 21:22:26
    String在java中是一个,这个里面有很多方法》》》》》》》》》》》》先来介绍一下String声明创建。。。

    这里介绍一下String,其实这是在java.lang中的一个类,


    String类位于java.lang包中,具有丰富的方法。
    计算字符串的长度,比较字符串,连接字符串,提取字符串


    字符串三种声明方式的区别:

    一般的创建对象:在堆内存中创建对象,在栈内存中形成引用

    然而,直接用引号来创建字符串时,在字符串常量池直接创建
    String s="hello";//通过双引号直接创建时在字符串常量池中直接创建的
    String s2=s;
    String s3="hello";//字符串常量池中的地址
    System.out.println(s==s2);
    System.out.println(s==s3);
    结果:【true true】
    还有一种穿件字符串对象的方式——通过new关键字
    String s4=new String("hello");//通过new关键字的方式创建,跟普通的创建方式一样,不能用==直接比较,应该使用equals的方式去比较
    System.out.println(s==s4);
    String s5="he";
    String s6="llo";
    String s7=s5+s6;
    System.out.println(s==s7);//这里是不相等的, 这里没有给出具体的值,而是给出了引用,是不相等的
    String s8="he"+"llo"; //这里是不相等的 如果是直接给出直接的值 就是想等的
    System.out.println(s==s8);
    结果为: 【false false true】

    length()


    String 了提供了一个length()方法,确定字符串的长度,这是一个方法,而数组的length长度是一个属性,区别方法和属性只要看后面有没有括号。
    用法和length的用法一样。


    字符串的值————equals()

    == 比较的是字符串的地址,比较出来的结果有可能会不一样
    这里比较字符串额方法equals
    String a="a";
    String b=null;
    System.out.println(a.equals(b));
    System.out.println(b.equals(a));
    【这里的结果是 false 和报错】

    空对象使用了属性或者方法,空对象使用了.语法 ,空对象使用语法倒置异常,所以把确定有值放在前面,不确定的就放在后面,这样就不会报错了

    equals 判别分方式,是将两个字符串中的字符一个一个比较。


    展开全文
  • 深入理解Java String类

    万次阅读 多人点赞 2018-06-28 21:15:55
    在Java语言了中,所有类似“ABC”的字面值,都是String类的实例;String类位于java.lang包下,是Java语言的核心,提供了字符串的比较、查找、截取、大小写转换等操作;Java语言为“+”连接符(字符串连接符)以及...

    在Java语言中,所有类似“ABC”的字面值,都是String类的实例;String类位于java.lang包下,是Java语言的核心类,提供了字符串的比较、查找、截取、大小写转换等操作;Java语言为“+”连接符(字符串连接符)以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象。String类的部分源码如下

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
        ...
    }
    

    从上面可以看出
    1)String类被final关键字修饰,意味着String类不能被继承,并且它的成员方法都默认为final方法;字符串一旦创建就不能再修改。
    2)String类实现了Serializable、CharSequence、 Comparable接口。
    3)String实例的值是通过字符数组实现字符串存储的。


    1. “+”连接符

    1.1 “+”连接符的实现原理

    Java语言为“+”连接符以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象。其中字符串连接是通过 StringBuilder(或 StringBuffer)类及其append 方法实现的,对象转换为字符串是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。有关字符连接和转换的更多信息,可以参阅 Gosling、Joy 和 Steele 合著的 《The Java Language Specification》

    我们可以通过反编译验证一下

    /**
     * 测试代码
     */
    public class Test {
        public static void main(String[] args) {
            int i = 10;
            String s = "abc";
            System.out.println(s + i);
        }
    }
    
    /**
     * 反编译后
     */
    public class Test {
        public static void main(String args[]) {    //删除了默认构造函数和字节码
            byte byte0 = 10;      
            String s = "abc";      
            System.out.println((new StringBuilder()).append(s).append(byte0).toString());
        }
    }
    

    由上可以看出,Java中使用"+"连接字符串对象时,会创建一个StringBuilder()对象,并调用append()方法将数据拼接,最后调用toString()方法返回拼接好的字符串。由于append()方法的各种重载形式会调用String.valueOf方法,所以我们可以认为:

    //以下两者是等价的
    s = i + ""
    s = String.valueOf(i);
     
    //以下两者也是等价的
    s = "abc" + i;
    s = new StringBuilder("abc").append(i).toString();
    

    1.2 “+”连接符的效率

    使用“+”连接符时,JVM会隐式创建StringBuilder对象,这种方式在大部分情况下并不会造成效率的损失,不过在进行大量循环拼接字符串时则需要注意。

    String s = "abc";
    for (int i=0; i<10000; i++) {
        s += "abc";
    }
    
    /**
     * 反编译后
     */
    String s = "abc";
    for(int i = 0; i < 1000; i++) {
         s = (new StringBuilder()).append(s).append("abc").toString();    
    }
    

    这样由于大量StringBuilder创建在堆内存中,肯定会造成效率的损失,所以在这种情况下建议在循环体外创建一个StringBuilder对象调用append()方法手动拼接(如上面例子如果使用手动拼接运行时间将缩小到1/200左右)。

    /**
     * 循环中使用StringBuilder代替“+”连接符
     */
    StringBuilder sb = new StringBuilder("abc");
    for (int i = 0; i < 1000; i++) {
        sb.append("abc");
    }
    sb.toString();
    

    与此之外还有一种特殊情况,也就是当"+"两端均为编译期确定的字符串常量时,编译器会进行相应的优化,直接将两个字符串常量拼接好,例如:

    System.out.println("Hello" + "World");
    
    /**
     * 反编译后
     */
    System.out.println("HelloWorld");
    
    /**
     * 编译期确定
     * 对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。
     * 所以此时的"a" + s1和"a" + "b"效果是一样的。故结果为true。
     */
    String s0 = "ab"; 
    final String s1 = "b"; 
    String s2 = "a" + s1;  
    System.out.println((s0 == s2)); //result = true
    
    /**
     * 编译期无法确定
     * 这里面虽然将s1用final修饰了,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定
     * 因此s0和s2指向的不是同一个对象,故上面程序的结果为false。
     */
    String s0 = "ab"; 
    final String s1 = getS1(); 
    String s2 = "a" + s1; 
    System.out.println((s0 == s2)); //result = false 
     
    public String getS1() {  
        return "b";   
    }
    

    综上,“+”连接符对于直接相加的字符串常量效率很高,因为在编译期间便确定了它的值,也就是说形如"I"+“love”+“java”; 的字符串相加,在编译期间便被优化成了"Ilovejava"。对于间接相加(即包含字符串引用,且编译期无法确定值的),形如s1+s2+s3; 效率要比直接相加低,因为在编译器不会对引用变量进行优化。

    2. 字符串常量池

    在Java的内存分配中,总共3种常量池,分别是Class常量池运行时常量池字符串常量池

    字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性,常量池中一定不存在两个相同的字符串

    /**
     * 字符串常量池中的字符串只存在一份!
     * 运行结果为true
     */
    String s1 = "hello world!";
    String s2 = "hello world!";
    System.out.println(s1 == s2);
    

    2.1 内存区域

    在HotSpot VM中字符串常量池是通过一个StringTable类实现的,它是一个Hash表,默认值大小长度是1009;这个StringTable在每个HotSpot VM的实例中只有一份,被所有的类共享;字符串常量由一个一个字符组成,放在了StringTable上。要注意的是,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。

    在JDK6及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中的,StringTable的长度是固定的1009;在JDK7版本中,字符串常量池被移到了堆中,StringTable的长度可以通过**-XX:StringTableSize=66666**参数指定。至于JDK7为什么把常量池移动到堆上实现,原因可能是由于方法区的内存空间太小且不方便扩展,而堆的内存空间比较大且扩展方便。

    2.2 存放的内容

    在JDK6及之前版本中,String Pool里放的都是字符串常量;在JDK7.0中,由于String.intern()发生了改变,因此String Pool中也可以存放放于堆内的字符串对象的引用。

    /**
     * 运行结果为true false
     */
    String s1 = "AB";
    String s2 = "AB";
    String s3 = new String("AB");
    System.out.println(s1 == s2);
    System.out.println(s1 == s3);
    

    由于常量池中不存在两个相同的对象,所以s1和s2都是指向JVM字符串常量池中的"AB"对象。new关键字一定会产生一个对象,并且这个对象存储在堆中。所以String s3 = new String(“AB”);产生了两个对象:保存在栈中的s3和保存堆中的String对象。
    这里写图片描述

    当执行String s1 = "AB"时,JVM首先会去字符串常量池中检查是否存在"AB"对象,如果不存在,则在字符串常量池中创建"AB"对象,并将"AB"对象的地址返回给s1;如果存在,则不创建任何对象,直接将字符串常量池中"AB"对象的地址返回给s1。

    3. intern方法

    直接使用双引号声明出来的String对象会直接存储在字符串常量池中,如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回。

    JDK1.7的改动:

    1. 将String常量池 从 Perm 区移动到了 Java Heap区
    2. String.intern() 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。
    /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();
    

    3.1 intern的用法

    static final int MAX = 1000 * 10000;
    static final String[] arr = new String[MAX];
    
    public static void main(String[] args) throws Exception {
        Integer[] DB_DATA = new Integer[10];
        Random random = new Random(10 * 10000);
        for (int i = 0; i < DB_DATA.length; i++) {
            DB_DATA[i] = random.nextInt();
        }
        long t = System.currentTimeMillis();
        for (int i = 0; i < MAX; i++) {
            //arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));
             arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();
        }
    
        System.out.println((System.currentTimeMillis() - t) + "ms");
        System.gc();
    }
    

    运行的参数是:-Xmx2g -Xms2g -Xmn1500M 上述代码是一个演示代码,其中有两条语句不一样,一条是未使用 intern,一条是使用 intern。结果如下图

    未使用intern,耗时826ms:
    这里写图片描述
    使用intern,耗时2160ms:
    这里写图片描述
    通过上述结果,我们发现不使用 intern 的代码生成了1000w 个字符串,占用了大约640m 空间。 使用了 intern 的代码生成了1345个字符串,占用总空间 133k 左右。其实通过观察程序中只是用到了10个字符串,所以准确计算后应该是正好相差100w 倍。虽然例子有些极端,但确实能准确反应出 intern 使用后产生的巨大空间节省。

    细心的同学会发现使用了 intern 方法后时间上有了一些增长。这是因为程序中每次都是用了 new String 后,然后又进行 intern 操作的耗时时间,这一点如果在内存空间充足的情况下确实是无法避免的,但我们平时使用时,内存空间肯定不是无限大的,不使用 intern 占用空间导致 jvm 垃圾回收的时间是要远远大于这点时间的。 毕竟这里使用了1000w次intern 才多出来1秒钟多的时间。

    4. String、StringBuilder和StringBuffer

    4.1 继承结构

    这里写图片描述

    4.2 主要区别

    1)String是不可变字符序列,StringBuilder和StringBuffer是可变字符序列。
    2)执行速度StringBuilder > StringBuffer > String。
    3)StringBuilder是非线程安全的,StringBuffer是线程安全的。

    5. 总结

    String类是我们使用频率最高的类之一,也是面试官经常考察的题目,下面是一个小测验。

    public static void main(String[] args) {
        String s1 = "AB";
        String s2 = new String("AB");
        String s3 = "A";
        String s4 = "B";
        String s5 = "A" + "B";
        String s6 = s3 + s4;
        System.out.println(s1 == s2);
        System.out.println(s1 == s5);
        System.out.println(s1 == s6);
        System.out.println(s1 == s6.intern());
        System.out.println(s2 == s2.intern());
    }
    

    运行结果:
    这里写图片描述

    解析:真正理解此题目需要清楚以下三点
    1)直接使用双引号声明出来的String对象会直接存储在常量池中;
    2)String对象的intern方法会得到字符串对象在常量池中对应的引用,如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;
    3) 字符串的+操作其本质是创建了StringBuilder对象进行append操作,然后将拼接后的StringBuilder对象用toString方法处理成String对象,这一点可以用javap -c命令获得class文件对应的JVM字节码指令就可以看出来。
    这里写图片描述

    参考文献
    https://docs.oracle.com/javase/8/docs/api/
    https://blog.csdn.net/sinat_19425927/article/details/38663461
    https://www.cnblogs.com/xiaoxi/p/6036701.html
    https://tech.meituan.com/in_depth_understanding_string_intern.html

    展开全文
  • String类介绍

    千次阅读 多人点赞 2018-09-17 01:09:42
    一、String类介绍:  String是一个引用数据类型默认为null;  String 为final类型不可更改,不能被继承;  基本类型与String结合都会转换为String类型; 二、String两种赋值方式: 1)直接赋值:String str = ...

    一、String类介绍:

            String是一个引用数据类型默认为null;
            String 为final类型不可更改,不能被继承;
            基本类型与String结合都会转换为String类型;

    二、String两种赋值方式:

    1)直接赋值:String str = " ";

    String str = "" 原理:
            在 JVM(虚拟机)中有一个字符串池,专门用来存储字符串。如果遇到 String a=”hello”时(注意没有 NEW,不是创建新串),系统在字符串池中寻找是否有 ”hello”,
            此时字符串池中没有”hello”,那么系统将此字符串存到字符串池中,然后将 ”hello”在字符串池中的地址返回 a。
            如果系统再遇到String b=”hello”,此时系统可以在字符串池中找到  “hello”。则会把地址返回b,此时 a与b 为相同。

     

    2)使用new进行赋值:String str = new String (" ");

     

    3) 两种赋值方式的区别:
                1、直接定义的String "a"是储存在常量存储区中的字符串常量池中;new String(“a”)是存储在中;
                2、常量池中相同的字符串只有一个,但是new String(),每new一个对象就会在堆中新建一个对象;
                3、String a = “a”在编译阶段就会在内存中创建;String a = new String(“a”);是在运行时才会在堆中创建对象;

    	    String a = "hello";
            String b = "hello";
            System.out.println(a == b );//true  a b 指向同一个值,地址相同
            System.out.println(a.equals(b));//true a b 是同一个值,当然相等
    
            String a1 = new String ("hello");
            String b1 = new String ("hello");
            System.out.println(a1 == b1 );//false  每次new都会创建一个新对象,a1 b1 地址不同 
            System.out.println(a1 .equals(b1) );//true 

    由此可以得出两种实例化方式的区别

          1)直接赋值(String str = "hello"):只开辟一块堆内存空间,并且会自动入池,不会产生垃圾。

          2)构造方法(String str=  new String("hello");):会开辟两块堆内存空间,其中一块堆内存会变成垃圾被系统回收

            在开发的过程中不会采用构造方法进行字符串的实例化。

    4)常量池

    字符串常量池在jdk1.6及之前在方法区中,但是在jdk1.7及以后就放在了堆中

    编译阶段确定的字符串才会被放到字符串常量池中

    分析下面创建几个对象:

                    String s1 = "java"; 
    		String s2 = "从0到1"; 
    		String s3 = "java从0到1"; 
    		String s4 = s1+s2;
    		System.out.println(s3==s4);

    s1和s2还有s4都会在字符串常量池中,这已经有三个对象了 。关键在于这行代码上String s3 = s1 + s2;

    对于s3无法在编译阶段确定下来,所以无论最后的字符串是什么都不会存在字符串常量池中,那么存在哪呢?因为对象创建在堆中,而字符串常量池也在堆中,既然不在字符串常量池中那就是在字符串常量池之外的堆中了,而s3最终的字符串对象是“Java从0到1”,那么也就是说这个字符串在常量池之外的堆中,这是一个对象了,加上之前的三个,这里一共四个了,但是我们还要分析这个s3是怎么来的,是通过s1和s2相加得到的,因为这个s3最终是在常量池之外的堆中形成的,而s1和s2都是在常量池中,因此会将s1和s2拷贝一份到字符串常量池之外的堆中来形成s3,我们看下面的一张图来加深理解

    堆内存复制s1,s2,这样的话要再加上两个对象,那一共就是创建6个对象了!

    三、String源码解析:

    Jdk1.7 的String源码如下: 

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
     
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    

    由以上的代码可以看出, 在Java中String类其实就是对字符数组的封装,除此之外还有一个hash成员变量,是该String对象的哈希值的缓存。
    value这个变量是final的, 也就是说在String类内部,一旦这个值初始化了, 也不能被改变。所以可以认为String对象是不可变的了。

    String s = new ("ABCabc"); 对应的内存模型为:

    当我们调用a.replace('A', 'a')时, 方法内部创建了一个新的String对象,并把这个新的对象重新赋给了引用a;

    因此结果为 aBCabc

    Spring是否真的是不可变?

    我们知道被final修饰的引用类型变量是引用的地址不可变,而不是引用的值不可变,因此我们能否改变value数组的值而使String改变???答案当然是可以的,反射可以搞定。

    反射可以访问私有成员,因此我们可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。

    	public static void testReflection() throws Exception {
    		
    		//创建字符串"Hello World", 并赋给引用s
    		String s = "Hello World"; 
    		
    		System.out.println("s = " + s);	//Hello World
    		
    		//获取String类中的value字段
    		Field valueFieldOfString = String.class.getDeclaredField("value");
    		
    		//改变value属性的访问权限
    		valueFieldOfString.setAccessible(true);
    		
    		//获取s对象上的value属性的值
    		char[] value = (char[]) valueFieldOfString.get(s);
    		
    		//改变value所引用的数组中的第5个字符
    		value[5] = '_';
    		
    		System.out.println("s = " + s);  //Hello_World
    	}
    

    在这个过程中,s始终引用的同一个String对象,但是再反射前后,这个String对象发生了变化, 也就是说,通过反射是可以修改所谓的“不可变”对象的。但是一般我们不这么做。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。例如一个Car对象,它组合了一个Wheel对象,虽然这个Wheel对象声明成了private final 的,但是这个Wheel对象内部的状态可以改变, 那么就不能很好的保证Car对象不可变。

    四、String进行字符串拼接:

    拼接原理:String是字符串常量的引用,String += String的本质是new了新的临时对象StringBuild,拼接后再把StringBuild.toString赋给原String。


            String s="a"+"b"+"c"+"d"; 实际只创建了一个对象  ,过程是new 了 一个临时的StringBuild,然后把"a"+"b"+"c"+"d"进行拼接,结果"abcd".toString 返回gei s;
            
            所有大量字符串拼接不要直接使用String,否则会生成大量临时对象,严重影响性能。 

    五、String,StringBuffer, StringBuilder比较:

            
            1、String是字符串常量,StringBuffer和StringBuilder都是字符串变量。后两者的字符内容可变,而前者创建后内容不可变(String进行字符串拼接时创建新对象)。

            2、StringBuffer是线程安全的,而StringBuilder是非线程安全的。

            3.线程安全会带来额外的系统开销,所以StringBuilder的效率比StringBuffer高。如果对系统中的线程是否安全很掌握,
            可用StringBuffer,在线程不安全处加上关键字Synchronize。

            4.  StringBuffer 和 StringBuilder 要调用.toString方法在进行比较

    展开全文
  • Java的常用String类与Object

    千次阅读 2018-08-06 23:21:47
    在java编程中,字符串类String可以说用得非常普遍,基本所有java程序都会或多或少的用到String类;而Object,作为Java中所有的父类,即使不常直接使用,也会经常使用到其中的方法。下面就讲一讲这两个常用的...
  • 【C++】STL常用容器总结之十二:string类

    万次阅读 多人点赞 2016-08-25 13:02:43
    13、string类声明string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍。 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必...
  • String类与StringBuffer区别

    千次阅读 2019-01-26 12:11:26
    在上一篇博客中我讲了String类的特点,其中有一点就是String类的常量一旦声明,不可改变,如果改变对象内容,改变的只是其引用指向而已,通常来讲,String类的操作比较简单,但是由于String类的不可更改特性,就使得...
  • Java String类源码分析

    万次阅读 多人点赞 2016-08-29 22:11:50
    String类介绍 String 是日常开发中使用最频繁的之一, String类源码 一 String类 String类被final所修饰,也就是说String对象是不可变量,并发程序最喜欢不可变量了。String类实现了Serializable, ...
  • String数组声明赋值

    千次阅读 2012-07-11 11:07:58
    [code="java"] String[] A = new String[]{}; ...这个String数组声明赋值哪里不正确?求指教 [/code] [code="java"] 数组的声明由几种方式: 1,String []a = new...
  • 《C++ string类

    千次阅读 2018-06-08 17:51:26
    C++标准库中string类以类型的形式对字符串进行封装,使得它除了像一个存储字符的容器外,更加包含了字符序列的处理操作。   string类所有函数 string类的所有成员函数 函数名称 实现功能 构造函数 ...
  • String用法详解

    万次阅读 多人点赞 2018-04-05 16:15:51
    string类声明string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍。 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心...
  • java String类用法

    千次阅读 2016-07-02 18:50:28
    查看源码就会发现String类为final型的(当然也不可被继承),而且通过查看JDK文档会发现几乎每一个修改String对象的操作,实际上都是创建了一个全新的String对象。  字符串为对象,那么在初始化之前,它的值为null...
  • // 声明istringstream对象 int i; double d; char c; inputString >> str1 >> str2 >> i >> d >> c; // 使用istringstream对象进行字符串输入 cout << str1 << str2 <...
  • String类和常量池

    千次阅读 2018-08-31 19:37:43
    String类和常量池 1、 String对象的两种创建方式: String str1 = "abcd"; String str2 = new String("abcd"); System.out.println(str1==str2);//false 这两种不同的创建方法是有差别的,...
  • C++string类的实现

    万次阅读 多人点赞 2017-09-04 12:53:41
    实际上string并不是C++的基本类型,它是在C++标准库中声明的一个字符串,用这种数据类型可以定义对象,每一个字符串变量都是string类的一个对象。标准库类型string表示可变长的字符序列,使用string类型必须首先...
  • String类型声明空值变量

    千次阅读 2011-10-24 11:10:00
    在C#当中,我们经常用到String str=null与String str=””还有String str=string.Empty这三种方法来声明一个 变量为空值,那么它们之间有什么区别吗?   null是C#关键字,是表示不引用任何对象的空引用的文字值。...
  • java String类详解

    万次阅读 2014-11-07 22:22:41
    java字符串(java.lang.String)是Java中使用最多的,也是最为特殊的一个,很多时候,我们对它既熟悉又陌生。一、从根本上认识java.lang.String类String池首先,我建议先看看String类的源码实现,这是从本质上...
  • Java String

    万次阅读 2018-01-31 19:39:05
    java把String类声明的final,不能有String类对象创建后不能修改,由0或多个字符组成,包含在一对双引号之间。 二、String类对象的创建 字符串声明String stringName; 字符串创建:stringName = new Stri
  • Java中String显式声明的对象创建问题

    千次阅读 2017-09-03 15:44:15
    Java中String显式声明的对象创建问题
  • Java中String类的常用方法

    千次阅读 多人点赞 2019-10-28 14:59:15
    Java中String类的常用方法 1,String类的介绍 String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象。 String类是所有语言最常用的一个,用于描述字符串事物。 String类在Java中被...
  • string类的方法

    千次阅读 2009-09-08 18:38:00
    string类的构造函数:string(const char *s); //用c字符串s初始化string(int n,char c); //用n个字符c初始化此外,string类还支持默认构造函数和复制构造函数,如string s1;string s2="hello";都是正确的写法。当...
  • Java中String类知识点总结

    千次阅读 2019-04-27 10:26:24
    博客原文 ---->... String 字符串总结 String声明为final,因此它不可被继承,是常量,不可变的。 a) 不可变的好处 1. 可以缓存hash值 因为String和hash值经常被使用,例...
  • C++string类常用函数 c++中的string常用函数用法总结

    万次阅读 多人点赞 2018-06-02 16:55:42
    string类的构造函数: string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 此外,string类还支持默认构造函数和复制构造函数,如string s1;string s2="hello";都是...
  • Java基础语法(九)——String类

    万次阅读 多人点赞 2021-05-26 12:20:57
    一、创建字符串 创建字符串的方式有很多种,常见的构造 String 的方式如以下: 方式一:直接赋值法 方式二: new String() 方式三:创建一个字符数组ch,new String ( ch )
  • Java String类详解(一)

    千次阅读 多人点赞 2016-10-08 22:11:03
    String类是一个字符串类型的,使用“XXXX”定义的内容都是字符串,虽然这个在使用上有一些特殊,但是String本身是一个。一、String的实例化两种方式1、直接赋值实例化:String StringName= "xxx";以上是String...
  • C++STRING类常用函数

    千次阅读 2012-03-15 10:50:42
    C++string类常用函数 string类的构造函数: string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 此外,string类还支持默认构造函数和复制构造函数,如string s1;string s2=...
  • String类中常用方法归纳

    万次阅读 2016-07-20 13:27:46
    版权声明:本文为博主原创文章,未经博主...String类中提供了大量的操作方法,这里例举13种关于String类常用的方法供大家参考。参考代码如下:  package cn.mc;  public class StringTestMc {   private Stri
  • String类和常量池内存分析例子以及8种基本类型

    万次阅读 多人点赞 2019-01-21 19:52:51
    该篇例子几乎涵盖了目前所有能解决的...String类和常量池内存分析 8种基本类型的包装和常量池 String 和常量池 1 String 对象的两种创建方式 String str1 = "abcd"; String str2 = new String("abcd"); Sy...
  • Java的java.lang.String类详解

    千次阅读 2019-10-22 23:45:22
    String类详解

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,288,679
精华内容 515,471
关键字:

string类声明