看java String类里的substring()方法的实现产生的疑问,高手赐教。。。

danceinstyle 2014-09-13 09:26:58
substring()的实现代码:
 
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

其中的value是什么?在看到在String类里面倒是有声明一个char[] value数组,并且有一个构造函数:

public String(String original) {
this.value = original.value;
this.hash = original.hash;
}

但是想了很久,还是不明白这个char[] value和substring之间的关系
...全文
218 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
姜小白- 2014-09-13
  • 打赏
  • 举报
回复
引用 7 楼 danceinstyle 的回复:
还是没找到啊!count的声明也找不到

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

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];

    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = new char[0];
    }

    /**
     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.
     *
     * @param  original
     *         A {@code String}
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    /**
     * Allocates a new {@code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification of
     * the character array does not affect the newly created string.
     *
     * @param  value
     *         The initial value of the string
     */
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

    /**
     * Allocates a new {@code String} that contains characters from a subarray
     * of the character array argument. The {@code offset} argument is the
     * index of the first character of the subarray and the {@code count}
     * argument specifies the length of the subarray. The contents of the
     * subarray are copied; subsequent modification of the character array does
     * not affect the newly created string.
     *
     * @param  value
     *         Array that is the source of characters
     *
     * @param  offset
     *         The initial offset
     *
     * @param  count
     *         The length
     *
     * @throws  IndexOutOfBoundsException
     *          If the {@code offset} and {@code count} arguments index
     *          characters outside the bounds of the {@code value} array
     */
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
我在家的源码看的也是这个,刚才我贴的应该是1.6的源码,你贴的是1.7的源码 jdk也在进步,一些不用的东西也会慢慢改进,删掉的 重点理解思想就可以了,不用太过纠结这个太过具体的东西
scott_129 2014-09-13
  • 打赏
  • 举报
回复

 public String(String original) {
	int size = original.count;
	char[] originalValue = original.value;
	char[] v;
  	if (originalValue.length > size) {
 	    // The array representing the String is bigger than the new
 	    // String itself.  Perhaps this constructor is being called
 	    // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
 	} else {
 	    // The array representing the String is the same
 	    // size as the String, so no point in making a copy.
	    v = originalValue;
 	}
	this.offset = 0;
	this.count = size;
	this.value = v;
    }
是不是你的jdk源码版本问题,或者是源码有问题哦
danceinstyle 2014-09-13
  • 打赏
  • 举报
回复
引用 6 楼 magi1201 的回复:
[quote=引用 5 楼 danceinstyle 的回复:] String在初始化的时候,JVM也自动地新建了一个char[] value,value的所有字符与String的分别一一对应,在执行String的substring操作的时候,就用这个char[] value来新建一个String再返回。这样解释合理! 现在我郁闷的是,我的JDK里的String的源代码跟你的是不同的。。。我的没有声明private final int count, 还有我的这个构造函数跟你的不一样。。。不知道是什么问题

  public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

你的这个构造方法我见到过,我家里的源码好像就是你的那个 把你的jdk种String 源码中上面的那一块贴出来,上面应该是有的 部分细微的差别可能是jdk版本不一致导致的,但大的应该是大差不差的。[/quote] 还是没找到啊!count的声明也找不到

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

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];

    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = new char[0];
    }

    /**
     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.
     *
     * @param  original
     *         A {@code String}
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    /**
     * Allocates a new {@code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification of
     * the character array does not affect the newly created string.
     *
     * @param  value
     *         The initial value of the string
     */
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

    /**
     * Allocates a new {@code String} that contains characters from a subarray
     * of the character array argument. The {@code offset} argument is the
     * index of the first character of the subarray and the {@code count}
     * argument specifies the length of the subarray. The contents of the
     * subarray are copied; subsequent modification of the character array does
     * not affect the newly created string.
     *
     * @param  value
     *         Array that is the source of characters
     *
     * @param  offset
     *         The initial offset
     *
     * @param  count
     *         The length
     *
     * @throws  IndexOutOfBoundsException
     *          If the {@code offset} and {@code count} arguments index
     *          characters outside the bounds of the {@code value} array
     */
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
姜小白- 2014-09-13
  • 打赏
  • 举报
回复
引用 5 楼 danceinstyle 的回复:
String在初始化的时候,JVM也自动地新建了一个char[] value,value的所有字符与String的分别一一对应,在执行String的substring操作的时候,就用这个char[] value来新建一个String再返回。这样解释合理! 现在我郁闷的是,我的JDK里的String的源代码跟你的是不同的。。。我的没有声明private final int count, 还有我的这个构造函数跟你的不一样。。。不知道是什么问题

  public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

你的这个构造方法我见到过,我家里的源码好像就是你的那个 把你的jdk种String 源码中上面的那一块贴出来,上面应该是有的 部分细微的差别可能是jdk版本不一致导致的,但大的应该是大差不差的。
danceinstyle 2014-09-13
  • 打赏
  • 举报
回复
引用 4 楼 magi1201 的回复:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];

    /** The offset is the first index of the storage that is used. */
    private final int offset;

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

   public String(String original) {
	int size = original.count;
	char[] originalValue = original.value;
	char[] v;
  	if (originalValue.length > size) {
 	    // The array representing the String is bigger than the new
 	    // String itself.  Perhaps this constructor is being called
 	    // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
 	} else {
 	    // The array representing the String is the same
 	    // size as the String, so no point in making a copy.
	    v = originalValue;
 	}
	this.offset = 0;
	this.count = size;
	this.value = v;
    }
String 的value数组是私有的,应该初始化的时候,JVM就将string 直接拆为一对char了 subString 的时候,再由当前的value去构造新的String
谢谢你的回答!String在初始化的时候,JVM也自动地新建了一个char[] value,value的所有字符与String的分别一一对应,在执行String的substring操作的时候,就用这个char[] value来新建一个String再返回。这样解释合理! 现在我郁闷的是,我的JDK里的String的源代码跟你的是不同的。。。我的没有声明private final int count, 还有我的这个构造函数跟你的不一样。。。不知道是什么问题

  public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

姜小白- 2014-09-13
  • 打赏
  • 举报
回复

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];

    /** The offset is the first index of the storage that is used. */
    private final int offset;

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

   public String(String original) {
	int size = original.count;
	char[] originalValue = original.value;
	char[] v;
  	if (originalValue.length > size) {
 	    // The array representing the String is bigger than the new
 	    // String itself.  Perhaps this constructor is being called
 	    // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
 	} else {
 	    // The array representing the String is the same
 	    // size as the String, so no point in making a copy.
	    v = originalValue;
 	}
	this.offset = 0;
	this.count = size;
	this.value = v;
    }
String 的value数组是私有的,应该初始化的时候,JVM就将string 直接拆为一对char了 subString 的时候,再由当前的value去构造新的String
danceinstyle 2014-09-13
  • 打赏
  • 举报
回复
引用 1 楼 a12939026 的回复:
value就是一个char的数组啊 string的本质其实就是一个char数组,substring就是从数组中取出几个char来组成新的一个char数组也就是新的string
我没有看到那个将String转化成char[]的代码,难道是自动进行的?substring函数一开始就value.length了。。。那个value代表的是什么?
danceinstyle 2014-09-13
  • 打赏
  • 举报
回复
我没有看到那个将String转化成char[]的代码,难道是自动进行的?substring函数一开始就value.length了。。。那个value代表的是什么?
a12939026 2014-09-13
  • 打赏
  • 举报
回复
value就是一个char的数组啊 string的本质其实就是一个char数组,substring就是从数组中取出几个char来组成新的一个char数组也就是新的string
danceinstyle 2014-09-13
  • 打赏
  • 举报
回复
引用 9 楼 magi1201 的回复:
[quote=引用 7 楼 danceinstyle 的回复:] 还是没找到啊!count的声明也找不到

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

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];

    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = new char[0];
    }

    /**
     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.
     *
     * @param  original
     *         A {@code String}
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    /**
     * Allocates a new {@code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification of
     * the character array does not affect the newly created string.
     *
     * @param  value
     *         The initial value of the string
     */
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

    /**
     * Allocates a new {@code String} that contains characters from a subarray
     * of the character array argument. The {@code offset} argument is the
     * index of the first character of the subarray and the {@code count}
     * argument specifies the length of the subarray. The contents of the
     * subarray are copied; subsequent modification of the character array does
     * not affect the newly created string.
     *
     * @param  value
     *         Array that is the source of characters
     *
     * @param  offset
     *         The initial offset
     *
     * @param  count
     *         The length
     *
     * @throws  IndexOutOfBoundsException
     *          If the {@code offset} and {@code count} arguments index
     *          characters outside the bounds of the {@code value} array
     */
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
我在家的源码看的也是这个,刚才我贴的应该是1.6的源码,你贴的是1.7的源码 jdk也在进步,一些不用的东西也会慢慢改进,删掉的 重点理解思想就可以了,不用太过纠结这个太过具体的东西[/quote]

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧