0002JDK源码分析之Appendable接口家族

Posted Java框架源码分析

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0002JDK源码分析之Appendable接口家族相关的知识,希望对你有一定的参考价值。

本文将介绍java.lang包下的常用接口和类,接口分别是Appendable、Serializable、CharSequence以及Comparable,类分别是String、StringBuffer、StringBuilder以及AbstractStringBuilder。提示:Serializable位于java.io包。

本文大纲:

一、继承体系图

二、接口的职责 

三、类的源码分析

一、继承体系图

二、接口的职责

1、Appendable接口的职责

Appendable的意思是可追加的,该接口提供可追加char序列的操作,声明了三个抽象方法,声明的方法的返回值都是自身对象,这是一种链式编程的方法定义,使用者可以直接通过.的方式进行调用(联想一下StringBuffer),在代码层面显得十分简洁。拓展一点,大家在定义一些类的时候,如果要实现不断的往类内某个属性追加内容或值,可以使用这种方式。声明的抽象方法如下图所示:

Appendable  append(CharSequence csq) throws IOException;

Appendable  append(CharSequence csq, int start, int end) throws IOException;

Appendable append(char c) throws IOException;

2、Serializable接口的职责

序列化接口,如果一个类要序列化,就要实现这个接口,具有序列化和反序列化的功能。

3、CharSequence接口的职责

CharSequencechar值的一个可读序列。其子类有StringBufferStringBuilderString等类。

4、Comparable接口的职责

    可比较的,Comparable接口主要用于比较两个对象大小实现排序,实现该接口的类需要实现其抽象方法:public intcompareTo(T o)

三、类的源码分析

1、AbstractStringBuilder抽象类

AbstractStringBuilder类是一个抽象类,子类有StringBuffer和StringBuilder,该类主要操作char数组进行追加或插入字符序列。

重要属性描述:

char value[]; //保存字符序列

int count;    //字符序列的实际长度

这是一个可变序列,其默认容量由子类确定,当追加字符序列的时候,会自动扩容,每次+1再翻倍。扩容的方法如下:

void expandCapacity(int  minimumCapacity) {

       int newCapacity = (value.length + 1) * 2;

        if (newCapacity < 0) {

            newCapacity = Integer.MAX_VALUE;

        } else if (minimumCapacity > newCapacity){

               newCapacity = minimumCapacity;

           }

        value = Arrays.copyOf(value,newCapacity);

    }

2、StringBuilder类

StringBuilder类继承AbstractStringBuilder抽象类,一个可变的字符序列,主要是对父类的方法进行重写,使其方法返回StringBuilder自身对象,而不是AbstractStringBuilder对象。这是一个对StringBuffer类的简单替换,用于单线程,性能优于StringBuffer。StringBuilder类的内部实现很简单,引人注目的是该类是可序列化的,实现了序列化接口,并提供了如下两个私有方法:

   static final long serialVersionUID = 4383685877147921099L;

   private void writeObject(java.io.ObjectOutputStream s)

        throws java.io.IOException {

       s.defaultWriteObject();

        s.writeInt(count);

       s.writeObject(value);

    }

    private void readObject(java.io.ObjectInputStream s)

        throws java.io.IOException, ClassNotFoundException {

       s.defaultReadObject();

        count =s.readInt();

        value = (char[])s.readObject();

    }

让人思考的是,这两个私有方法和一个序列化号是如何实现序列化的?回想一下序列化的过程,首先是序列化,毋庸置疑,序列化调用的是writeObject方法,参数是一个对象输出流,应该是写到文件或内存,私有的方法被调用肯定要通过反射,那私有的方法是如何被反射调用的呢?其次,就是反序列化,调用的自然是readObject私有方法,参数是一个对象输入流。序列化号是一个对象序列化的标识,标记着某个对象,用于反序列化时根据这个标识找到确切的对象。对于这个具体的对象序列化过程,我会单独撰文编写案例说明。

3、StringBuffer类

StringBuffer类继承AbstractStringBuilder抽象类,也是一个可变的字符序列,主要是对父类的方法进行重写,并对数据操作实现同步,因此该类是线程安全的,实现同步的策略是使用synchronized关键字,其源码中大量方法都是同步方法。StringBuffer类也是可序列化的,实现了序列化接口,也有私有的对象序列化和反序列化方法,实现原理和StringBuilder差不多。

4、String类

String类也是一个操作字符序列的类,这是我们开发使用最多的类了。这个类与StringBuffer、StringBuilder不同的是该类是不可变的,也就说你每次创建new对象的时候都会得到一个新的对象,但是String类使用了字符池来管理字符序列,所以不会重复创建对象,这是如何实现的呢?

源码中只有这么一行代码:

public native String intern();

该方法是字符池使用的,用于比较两个对象是否相等,如果相等则代表池中含有该对象,直接返回。如果不相等则代表该对象不存在于池中,创建这个对象并放进池中。对于池的内容,后期会有单独的文章介绍,在这只是简单阐述一下。

String类有一个内部类CaseInsensitiveComparator,实现忽略大小写比较功能,代码如下:

private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable {

    // use serialVersionUIDfrom JDK 1.2.2 for interoperability

    private static finallong serialVersionUID = 8575799808933029326L;

        public intcompare(String s1, String s2) {

            intn1=s1.length(), n2=s2.length();

            for (int i1=0,i2=0; i1<n1 && i2<n2; i1++, i2++) {

                char c1 =s1.charAt(i1);

                char c2 =s2.charAt(i2);

                if (c1 != c2) {

                    c1 =Character.toUpperCase(c1);

                    c2 =Character.toUpperCase(c2);

                    if (c1!= c2) {

                        c1= Character.toLowerCase(c1);

                        c2= Character.toLowerCase(c2);

                        if(c1 != c2) {

                           return c1 - c2;

                        }

                    }

                }

            }

            return n1 -n2;

        }

    }

String类还涉及到模式匹配,格式化等内容,这些将在java.util包的时候详细介绍。比如:Pattern类、Matcher类、Formatter类等。

四、总结

本文主要介绍了一些操作字符序列的常用类,String、StringBuffer、StringBuilder,这些都是开发者经常使用到的类,了解其原理以及实现,有利于我们更好的开发。

以上是关于0002JDK源码分析之Appendable接口家族的主要内容,如果未能解决你的问题,请参考以下文章

jdk源码阅读笔记-AbstractStringBuilder

JDK源码之HashMap 类分析

0013JDK源码分析之枚举

集合之HashSet(含JDK1.8源码分析)

jdk源码分析之List--常用实现类分析与对比

0006JDK源码分析之服务提供者框架