【小白的java成长系列】——String类的深入分析(基于源码)

来源:互联网 发布:软件质量保证的过程 编辑:程序博客网 时间:2024/05/01 18:00

接着前面面向对象来说吧~今天来说说String类。。其实String类也包含很多面向对象的知识的~

首先来问一个问题:我们在开发过程中,如果要使用一个类的话,就要创建对象,这句话没什么问题吧~在实际开发的时候确实是这样的,只有创建了对象才能真正的去使用一个普通的类,我们一般创建对象,几乎所有的类创建对象都是要通过new关键字来创建的~

问题就来了。。为什么我们的String可以直接写成String str = "abc";这样子呢?

当然String类也可以通过new来创建对象的。。。

其实也不难,我们看到它的源码说明就知道的:

 * Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. For example: * <p><blockquote><pre> *     String str = "abc"; * </pre></blockquote><p> * is equivalent to: * <p><blockquote><pre> *     char data[] = {'a', 'b', 'c'}; *     String str = new String(data); * </pre></blockquote><p>

进入String的源码,最前面就能看到上面的文字的:大致的意思是,String的对象值其实是通过char[]数组来存储的,String str = "abc";等同于char data[] = {'a', 'b', 'c'};  String str = new String(data);明白清晰了吧~

1、String类的定义:

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence 

问题:在开发过程中,我们可以继承String类吗?

答案:不行的,我们看定义就知道,String的定义使用了final修饰符,定义为了终结类,所以String是不能做扩展的。

implements:这个关键字是用来表示实现接口作用的,意思就是Serializable、Comparable和CharSequence都是接口的。

查看接口源码:

Comparable<T>  :表示比较器作用,<T>采用了java泛型的形式

Serializable:

public interface Serializable {}

我们可以看到Serializable接口里面啥都木有,那为什么我们要实现这个接口呢?这个接口的作用是啥呢?

作用:java类的序列化,至于序列化,后面会详细介绍。其实Serializable是java的一个标记接口,什么叫标记接口?Serializable只是作为一个标记的作用,关于它具体的功能和作用交给了JVM底层去实现了,实现了这个接口,只是通知JVM,String这个类可以序列化。

CharSequence:表示字符序列吧~这个没啥好说的,String的存储方式依赖于字符序列的~


2、属性

    private final char value[];//String值就是存储在value[]上的    private int hash; // Default to 0  表示hash值,    private static final long serialVersionUID = -6849794470754667710L;//序列化作用    private static final ObjectStreamField[] serialPersistentFields =            new ObjectStreamField[0];//序列化作用

我们只要了解String类的属性就可以,几乎都不会用到的,因为都是定义成了private,私有化了~

3、构造方法

这里也只说几个特殊的,一般在开发过程中也不会用到构造方法的,因为很少使用new来创建String对象的,都是直接使用String str = "abc";这样子的形式。。

在面试过程中,很多面试官会问到String str = new String("abc");这个创建了几个对象?至于答案和解释,这边就不做介绍了,想知道的就去网上查找了解~这个涉及到底层的内存问题的,描述起来篇幅会很长的~

    public String(String original) {        this.value = original.value;        this.hash = original.hash;    }
从上面可以看到,String两个核心就是value和hash的,这两个值基本决定了String对象的。

    public String(char value[]) {        this.value = Arrays.copyOf(value, value.length);    }
这个是通过底层数组拷贝的方式创建,其实底层使用的是System.arrayCopy()这个方法,此方法使用了native修饰的,底层是由C/C++来实现的,其实就是一个拷贝的作用

public String(byte bytes[], int offset, int length) {        checkBounds(bytes, offset, length);        this.value = StringCoding.decode(bytes, offset, length);    }
这个表示的是通过字节(byte)来构造字符串,其实底层的实现也是通过System.arrayCopy()这个方法的。

其他的基本也没什么好说的,了解一下就可以的。我们可以看到有些构造使用了@Deprecated注解,这个注解表示的过时,不推荐使用这个方法的

4、常用方法

    public int length() {//返回字符串长度        return value.length;    }public boolean isEmpty() {//判断字符串是不是为空        return value.length == 0;    }public char charAt(int index) {//字符串中的某个字符,index表示字符的位置        if ((index < 0) || (index >= value.length)) {            throw new StringIndexOutOfBoundsException(index);        }        return value[index];    }public byte[] getBytes() {//获取字节数组        return StringCoding.encode(value, 0, value.length);    }public boolean equals(Object anObject) {//字符串比较,我们知道基本类型的比较都是通过==来做比较的,//但是字符串需要使用此方法来做比较的

我们主要来验证一下==和equals方法

package me.javen.oop;public class StringDemo {public static void main(String[] args) {String str1 = "hello" ;// 直接赋值String str2 = new String("hello") ;// 通过new赋值String str3 = str2 ;// 传递引用System.out.println("str1 == str2 --> " + (str1==str2)) ;// falseSystem.out.println("str1 == str3 --> " + (str1==str3)) ;// falseSystem.out.println("str2 == str3 --> " + (str2==str3)) ;// true//以下通过equals方法System.out.println("str1 equals str2 --> " + (str1.equals(str2))) ;// trueSystem.out.println("str1 equals str3 --> " + (str1.equals(str3))) ;// trueSystem.out.println("str2 equals str3 --> " + (str2.equals(str3))) ;// true}}
此外还有一个比较方法也用得比较多:

public boolean equalsIgnoreCase(String anotherString) {//不分大小写比较

public boolean startsWith(String prefix) {//判断字符串是不是以prefix开头public boolean endsWith(String suffix) {//判断字符串是不是以suffix结尾public int hashCode() {//获取字符串的hash值public int indexOf(String str) {//获取字符str的起始位置,-1表示没有这个字符        return indexOf(str, 0);    }public String substring(int beginIndex, int endIndex) {//截取字符串beginIndex表示起始位置,endIndex表示结束位置public String replaceAll(String regex, String replacement) {//字符串替换replacement替换regexpublic String[] split(String regex) {//分隔字符串,regex表示分隔符public String toLowerCase() {//将字符串全部转换为小写public String toUpperCase() {//将字符串全部转换为大写public String trim() {//去掉首尾空格,字符中间的空格不能去掉public static String valueOf(Object obj) {//将obj转换成字符串,这个可以传递任意类型,比如数字,字符,浮点数等等

此外还有其他的很多方法,这边就不列举出了,学习者可以通过代码的方式去使用这些个方法,列举出来的表示开发中常用的方法~

1 0