小白白让你懂之Java String类详解(一)

      对于java的学习,String类是一个重点,初学java,我们可能对于String类的认知也就在以下几点上吧:

    (1)new String()可以获得一个字符串的引用地址

    (2)String str=”abc”,也可以直接给String变量提供字符串的常量值。

    (3)String a=new String(“123”)

            String b=new String(“123”);

            System.out.println(a==b);//false

            System.out.println(a.equals(b))//true

    (4)String类的一些操作方法:trim()、replace()、substring()等。

            但java 是一个面向对象的语言,要学好面向对象,是不是更好地以java的这些类的设计思路上去体会和学习面向对象的精妙之处呢。

            下面让我们从不断提出问题到API中和源码中去获取到相关内容。

            我们先看API:

                小白白让你懂之Java String类详解(一)

            

            可以得到的信息有:

            String的类是从java.lang包中得到的

            实现了三个接口:

                    Serializable,CharSequence,Comparable<String>
             我们先分别看这个接口实现后会出现什么样的情况。

            假使我们自己写了一下Strings的类。

            先实现Serializalbe接口:

                    小白白让你懂之Java String类详解(一)

            实现后发现这个接口不用重写任何方法,F3查看Serializable的源文件:

                小白白让你懂之Java String类详解(一)

            

            看到其实它里面什么也没写,如果了解序列化会知道,这也许就是一个标志,不实现这个接口还做不了序列化。

            好了,第一个接口实际上是个标志。

            我们再看第二个接口:

                CharSequence

            小白白让你懂之Java String类详解(一)

            

            实现后发现必写3个方法。其中就有String类我们熟悉的length()和charAt方法

            所以与其说String类有长度的length()方法,不如说是CharSequence这个接口规范String必须有一个length方法,这样我们就可以理解API中的下面的内容。

            小白白让你懂之Java String类详解(一)

                  

               等效的这个char数组,应该有长度,而java数组的长度length是属性,String length()是方法,这个是CharSequence规范String必须完成的内容。当然也有一些好处,我们在后面会提到。

            然后我们再实现第三个接口,Comparable<String>来看一下效果:

            小白白让你懂之Java String类详解(一)

        

        我们又看到了实现的方法compareTo(),这个也是String API中的比较方法.可见Comparable<String>规范了CompareTo这个方法。

            其它的String API中的方法应该是String特有的方法,就是对字符串进行一系列的增、删、改、查。

            好了,那么我们看API上面介绍String的第一句话:

            小白白让你懂之Java String类详解(一)    

            以上是API 中的描述,字符串是一个常量,为什么,我们都知道常量是由final这个关键字来修饰的变量。我们看一下String的源文件。

            小白白让你懂之Java String类详解(一)

                可以看到前面的部分有一个fina char[]型的数组,而API下面介绍的内容也就成立了。

                小白白让你懂之Java String类详解(一)

            

            也就是说new String就相当于把String参数中的字符数组赋给了String当中的value;

            我们在String源文件中也看到了这样的构造器:

                小白白让你懂之Java String类详解(一)

            

            调用了Arrays的copyof复制了一个这样的char型数组,而数组的来源恰恰就是value;

            我们根据这样的方法就仿一个String类

            步骤是:

            (1)我们自己定义Strings

            (2)让他单独实现CharSequence;

            (3)定义一个常量char[] value;

            (4)构造器中用Arrays的copyof方法拷贝Strings传过来的字符数组。

            (5)把实现CharSequence 必须让我们实现的方法length(),用数组的length属性返回

            (6)把实现CharSequence 必须让我们实现的方法CharAt,用数组的下标值返回

            这样,我们得到的Strings的代码就是

            小白白让你懂之Java String类详解(一)

            

        这就相当于我们实现了一个简单的String类.

         我们可以在主程序中调用一下:

            小白白让你懂之Java String类详解(一)
        

        在Strings里面有一个value就是我们的char数组;

         既然Strings是个字符数组,我们就可以对里面的value成员变量进行遍历;

            小白白让你懂之Java String类详解(一)

            

        执行的结果就是:

            abcde

        那么String类是不是如此呢?

        我们把Strings改成String,发现str.value报错

                小白白让你懂之Java String类详解(一)

        

        为什么呢?

        

            从源码上看,这个变量被private了,实现了面向对象对成员变量的封装,但没有提供getter和setter方法,让我们使用这个量,这就是为什么String实际是一个char数组,但不能被我们直接遍历,因为成员变量被private私有化了。当我们在进行面向对象编程时,也可以学习这种方法,把一个成员变量封装后,不提供开放的方法,提供这个私有化成员的增、删、改、查方法。

            然后我们看后面任意的String方法,都是对这个value进行操作.

            例如substring

            小白白让你懂之Java String类详解(一)

            

            这里面的new Strings(this.value,start,len)是重载的构造方法,一样利 用了Arrays的工具类:

            小白白让你懂之Java String类详解(一)

            

            我们可以看到上述代码的Arrays.copyOfRange一样是复制了一个数组,产生另外的堆空间地址存放这个子字符串。

            这样我们就构建了自己的Strings类。

            我们把value的public改成private也就跟 String类没有什么差别了。

            我们也理解了String类的面向对象的思维:

            (1)String就是一个char数组.

            (2)在String类里value成员变量中存放着这个char数组。

            (3)成员变量value私有化,不提供直接的遍历和操作,我们只能借助于String类提供的方法来对value进行相关的增、删、改、查。

                紧接着,我们看一下这样的一个程序段:

                小白白让你懂之Java String类详解(一)

                

            传入的这些\u的数据是十六进制数,也就是两个字节拼接出的\u后面的内容,这些就是unicode编码。

            控制台的输出:

                    小白白让你懂之Java String类详解(一)

            

            看到这些unicode代码是汉字。

            其实unicode编码就是char数组里面存放的内容.

            所以String就是一个存放unicode编码的char型数组。