自助网站建设怎么建设,wordpress 外链搜索框,个人网站可以做企业网站吗,昆明做网站建设多少钱简述字符串广泛应用 在 Java 编程中#xff0c;在 Java 中字符串属于对象#xff0c;Java 提供了String 类来创建和操作字符串。字符串缓冲区支持可变字符串。因为String对象是不可变的#xff0c;因此可以共享它们。String类代表字符串#xff0c;Java程序中的所有字符串字…简述字符串广泛应用 在 Java 编程中在 Java 中字符串属于对象Java 提供了String 类来创建和操作字符串。字符串缓冲区支持可变字符串。因为String对象是不可变的因此可以共享它们。String类代表字符串Java程序中的所有字符串字面值如abc都是这个类的实例对象。String 类是不可改变的所以你一旦创建了 String 对象那它的值就无法改变了。如果需要对字符串做很多修改那么应该选择使用StringBuilder或者StringBuffer。最简单的创建字符串的方式String qc qiu chan编译器会使用该值创建一个 对象。我们也可以使用关键字New创建String对象。String类型的常量池比较特殊。它的主要使用方法有两种直接使用双引号声明出来的String对象会直接存储在常量池中。如果不是用双引号声明的String对象可以使用String提供的intern方法。intern 方法会从字符串常量池中查询当前字符串是否存在若不存在就会将当前字符串放入常量池中。继承/实现关系public final class String implements java.io.Serializable, Comparable, CharSequence { // 省略} String是final修饰的不能够被继承和修改。源码String的底层使用的是char数组用于存储。private final char value[];缓存字符串的哈希码默认值为0private int hash;无参数构造函数public String() { this.value .value;}解析初始化一个新创建的String对象使其代表一个空字符序列。 注意由于String是不可变的所以不需要使用这个构造函数。参数为字符串的构造函数public String(String original) { this.value original.value; this.hash original.hash;}解析初始化一个新创建的String对象使其代表与参数相同的字符序列。换句话说新创建的字符串是参数字符串的副本。除非需要参数字符串的显式拷贝否则不需要使用这个构造函数因为String是不可变的。参数为char数组的构造函数public String(char value[]) { this.value Arrays.copyOf(value, value.length);}解析分配一个新的String使其代表当前字符数组参数中包含的字符序列。使用Arrays.copyOf方法进行字符数组的内容被复制。字符数组的后续修改不会影响新创建的字符串。参数为char数组并且带有偏移量的构造方法// value[]作为字符源的数组,offset偏移量、下标从0开始并且包括offset,count从数组中取到的元素的个数。public String(char value[], int offset, int count) { // 如果偏移量小于0抛出IndexOutOfBoundsException异常 if (offset 0) { throw new StringIndexOutOfBoundsException(offset); } // 判断要取的元素的个数是否小于等于0 if (count 0) { // 要取的元素的个数小于0抛出IndexOutOfBoundsException异常 if (count 0) { throw new StringIndexOutOfBoundsException(count); } // 在要取的元素的个数等于0的情况下判断偏移量是否小于等于数组的长度 if (offset value.length) { // 偏移量小于等于数组的长度返回一个空字符串数组的形式 this.value .value; return; } } // 如果偏移量的值大于数组的长度减去取元素的个数抛出IndexOutOfBoundsException异常 if (offset value.length - count) { throw new StringIndexOutOfBoundsException(offset count); } // 复制元素 this.value Arrays.copyOfRange(value, offset, offsetcount);}解析分配一个新的Sting来源于给定的char数组中的字符。offset参数是子数组中第一个字符的索引count参数指定子数组的长度。子数组被被复制以后对字符数组的修改不会影响新创建的字符串。参数为StringBuffer的构造方法public String(StringBuffer buffer) { // 这里对StringBuffer进行了加锁然后再进行拷贝操作。这里对其进行加锁正是为了保证在多线程环境下只能有一个线程去操作StringBuffer对象。 synchronized(buffer) { this.value Arrays.copyOf(buffer.getValue(), buffer.length()); }}解析分配一个新的字符串该字符串包含当前字符串缓冲区参数中包含的字符序列。Arrays.copyOf方法进行字符串缓冲区中内容的复制。这里对StringBuffer进行了加锁然后再进行拷贝操作。这里对其进行加锁正是为了保证在多线程环境下只能有一个线程去操作StringBuffer对象。参数为StringBuilder的构造方法public String(StringBuilder builder) { this.value Arrays.copyOf(builder.getValue(), builder.length());}解析参数是StringBuilder这个是线程不安全的但是性能相对于StringBuffer有很大的提升源码的注释中说通过toString方法从字符串构建器中获取字符串可能会运行得更快通常是首选。length方法public int length() { // 查看源码发现这个value是一个char数组本质获取的是字符串对应的char数组的长度。 return value.length; }解析返回此字符串的长度。查看源码发现这个value是一个char数组本质获取的是字符串对应的char数组的长度。isEmpty方法public boolean isEmpty() { // 底层的char数组的长度是否为0进行判断 return value.length 0;}//举例Testpublic void test_string_isEmpty(){ System.out.println( .isEmpty());// true System.out.println(.isEmpty());// false}解析判断给定的字符串是否为空底层实现是根据char数组的长度是否为0进行判断。charAt方法public char charAt(int index) { // 给定的索引小于0或者给定的索引大于这个字符串对应的char数组的长度抛出角标越界异常 if ((index 0) || (index value.length)) { throw new StringIndexOutOfBoundsException(index); } // 获取当前的指定位置的char字符 return value[index];}解析根据给定的索引获取当前的指定位置的char字符。如果给定的索引否小于0或者给定的索引是大于这个字符串对应的char数组的长度抛出角标越界异常。index是从0开始到length-1结束。序列的第一个char值在索引0处下一个在索引1处依此类推与数组索引一样。getChars方法// srcBegin要复制的字符串中第一个字符的索引【包含】。srcEnd要复制的字符串中最后一个字符之后的索引【不包含】。dst[]目标数组。dstBegin目标数组中的起始偏移量。public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { // 校验起始索引小于0抛出角标越界异常 if (srcBegin 0) { throw new StringIndexOutOfBoundsException(srcBegin); } // 校验结束索引大于原始字符串的长度抛出角标越界异常 if (srcEnd value.length) { throw new StringIndexOutOfBoundsException(srcEnd); } // 校验结束索引大于起始索引抛出角标越界异常 if (srcBegin srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } // 数组的拷贝 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);}// 案例Testpublic void test_string_codePointAt(){ // 原始字符串 String h ahelloworld; // 目标char数组 char[] data new char[4]; // 执行拷贝 h.getChars(2, 6, data, 0); System.out.println(data);}解析将字符串中的字符复制到目标字符数组中。索引包含srcBegin不包含srcEnd。equals方法// anObject与此String进行比较的对象。public boolean equals(Object anObject) { // 引用相同直接返回true if (this anObject) { return true; } // 判断给定的对象是否是String类型的 if (anObject instanceof String) { // 给定的对象是字符串类型的转换为字符串类型 String anotherString (String)anObject; // 获取当前字符串的长度 int n value.length; // 判断给定字符串的长度是否等于当前字符串的长度 if (n anotherString.value.length) { // v1[]代表当前字符串对应的char数组 char v1[] value; // v2[]代表给定的字符串对应的char数组 char v2[] anotherString.value; // 遍历原始char数组并且与给定的字符串对应的数组进行比较 int i 0; while (n-- ! 0) { if (v1[i] ! v2[i]) // 任意一个位置上不相等返回false return false; i; } // 都相等返回true return true; } } // 不是String类型或者长度不一致返回false return false;}解析这个方法重写了Object中的equals方法。方法中的将此字符串与指定对象进行比较。接下来附赠一个手写的String字符串equals方法。手写equals方法private boolean mineEquals(String srcObject, Object anObject){ // 比较引用是否相同 if (srcObject anObject){ return true; } // 引用不相同比较内容 if (anObject instanceof String){ String ans (String) anObject; char[] srcChar srcObject.toCharArray(); char[] anChar ans.toCharArray(); int n srcChar.length; if (n anChar.length){ int i 0; while (n-- ! 0){ if (srcChar[i] ! anChar[i]) return false; i; } return true; } } return false;}// 测试我们自己写的equals方法 Test public void test_string_mine(){ String s new String(aaa); // 走的是引用的比较 System.out.println(s.equals(s));// true boolean b mineEquals(s, s); System.out.println(b);// true }equalsIgnoreCase方法public boolean equalsIgnoreCase(String anotherString) { // 引用相同返回true。引用不相同进行长度、各个位置上的char是否相同 return (this anotherString) ? true : (anotherString ! null) (anotherString.value.length value.length) regionMatches(true, 0, anotherString, 0, value.length);}解析将此字符串与另一个字符串进行比较而忽略大小写注意事项。regionMatches方法的源码很有趣的源码里面有一个while循环先进行未忽略大小的判断然后进行忽略大小的判断在忽略大小的判断中先进行的是大写的转换进行比较但是可能会失败【这种字体Georgian alphabet】。所以在大写转换以后的比较失败进行一次小写的转换比较。startsWith方法// 判断是否以指定的前缀开头public boolean startsWith(String prefix) { // 0代表从开头进行寻找 return startsWith(prefix, 0);}endsWith方法// 判断是否以指定的前缀结尾public boolean endsWith(String suffix) { // 从【value.length - suffix.value.length】开始寻找这个方法调用的还是startsWith方法 return startsWith(suffix, value.length - suffix.value.length);}startsWith和endsWith最终的实现方法// prefix: 测试此字符串是否以指定的前缀开头。toffset: 从哪里开始寻找这个字符串。public boolean startsWith(String prefix, int toffset) { // 原始的字符串对应的char[] char ta[] value; // 开始寻找的位置 int to toffset; // 获取指定的字符串对应的char[] char pa[] prefix.value; int po 0; // 获取指定的字符串对应的char[]长度 int pc prefix.value.length; // 开始寻找的位置小于0或者起始位置大于要查找的长度【value.length - pc】返回false。 if ((toffset 0) || (toffset value.length - pc)) { return false; } // 比较给定的字符串的char[]里的每个元素是否跟原始的字符串对应的char数组的元素相同 while (--pc 0) { if (ta[to] ! pa[po]) { // 有一个char不相同返回false return false; } } // 相同返回true return true;}substring方法// 返回一个字符串该字符串是该字符串的子字符串。beginIndex开始截取的索引【包含】。public String substring(int beginIndex) { // 校验指定的索引小于0抛出角标越界 if (beginIndex 0) { throw new StringIndexOutOfBoundsException(beginIndex); } // 子字符串的长度 int subLen value.length - beginIndex; // 子字符串的长度小于0抛出角标越界 if (subLen 0) { throw new StringIndexOutOfBoundsException(subLen); } // 开始位置为0返回当前字符串不为0创建一个新的子字符串对象并返回 return (beginIndex 0) ? this : new String(value, beginIndex, subLen);}解析返回一个字符串该字符串是该字符串的子字符串。子字符串以指定索引处的字符开头【包含】并且扩展到该字符串的末尾。substring方法// beginIndex开始位置【包含】。 endIndex结束位置【不包含】。public String substring(int beginIndex, int endIndex) { // 校验指定的开始索引小于0抛出角标越界 if (beginIndex 0) { throw new StringIndexOutOfBoundsException(beginIndex); } // 校验指定的结束索引大于给定的字符串的char数组的长度抛出角标越界 if (endIndex value.length) { throw new StringIndexOutOfBoundsException(endIndex); } // 要截取的长度 int subLen endIndex - beginIndex; // 要截取的长度小于0抛出角标越界 if (subLen 0) { throw new StringIndexOutOfBoundsException(subLen); } // 截取字符串 return ((beginIndex 0) (endIndex value.length)) ? this : new String(value, beginIndex, subLen);}解析返回一个字符串该字符串是该字符串的子字符串。子字符串从指定的beginIndex开始【包含】并且扩展到索引endIndex-1处的字符【不包含】。concat方法public String concat(String str) { // 获取给定的字符串的长度 int otherLen str.length(); // 长度为0直接返回当前的字符串 if (otherLen 0) { return this; } // 获取当前字符串的长度 int len value.length; // 构建一个新的长度为len otherLen的字符数组并且将原始的数据放到这个数组 char buf[] Arrays.copyOf(value, len otherLen); // 这个底层调用是System.arraycopy这个方法的处理是使用c语言写的 str.getChars(buf, len); return new String(buf, true);}将指定的字符串连接到该字符串的末尾。字符串拼接。format方法// 使用指定的格式字符串和参数返回格式化的字符串。public static String format(String format, Object... args) { return new Formatter().format(format, args).toString();}// 案例这里是使用%s替换后面的如-a-Testpublic void test_start(){ System.out.println(String.format(ha %s hh %s a %s h, -a-, -b-, -c-));}trim方法public String trim() { // 指定字符串的长度 int len value.length; // 定义一个开始位置的索引0 int st 0; // 定义一个char[] val用于避免使用getfiled操作码这个可以写段代码反编译一下看看 char[] val value; // 对于字符串的开头进行去除空格并记录这个索引 while ((st len) (val[st] )) { st; } // 对于字符串的尾部进行去除空格也记录这个索引这个索引就是去除尾部空格后的索引 while ((st len) (val[len - 1] )) { len--; } // 根据上面记录的长度判断是否要截取字符串 return ((st 0) || (len value.length)) ? substring(st, len) : this;}返回一个字符串其值就是这个字符串并去掉任何首部和尾部的空白。join方法// 返回一个新的String该字符串由给定的分隔符和要连接的元素组成。delimiter分隔每个元素的分隔符。elements连接在一起的元素。public static String join(CharSequence delimiter, CharSequence... elements) { // delimiter和elements为空抛出空指针异常,null会被拦截不会被拦截 Objects.requireNonNull(delimiter); Objects.requireNonNull(elements); // StringJoiner joiner new StringJoiner(delimiter); // 遍历给定的要拼接的元素拼接的元素允许为null for (CharSequence cs: elements) { // 执行拼接方法 joiner.add(cs); } return joiner.toString();}// 拼接方法public StringJoiner add(CharSequence newElement) { // prepareBuilder()方法首次调用会创建StringBuilder对象后面再调用会执行拼接分隔符 prepareBuilder().append(newElement); return this;}// 未进行拼接创建StringBuilder对象已经拼接以后value ! null执行拼接分隔符private StringBuilder prepareBuilder() { // 判断拼接的value是否为空 if (value ! null) { // 不为空执行拼接分隔符 value.append(delimiter); } else { // 最开始使用拼接的时候调用这个方法创建一个空的StringBuilder对象只调一次 value new StringBuilder().append(prefix); } return value;}// 上面是调用的这个拼接元素方法Overridepublic StringBuilder append(CharSequence s) { // 这里啥都没处理调用的是父类的append方法设计模式为建造者模式 super.append(s); return this;}// 上面的prepareBuilder方法是拼接分隔符这个方法是将分隔符和给定的元素拼接的方法Overridepublic AbstractStringBuilder append(CharSequence s) { // 以下3个判断根据类型和是否为空进行区别拼接 if (s null) return appendNull(); if (s instanceof String) return this.append((String)s); if (s instanceof AbstractStringBuilder) return this.append((AbstractStringBuilder)s); // 拼接 return this.append(s, 0, s.length());}将给定的字符串以给定的分割符分割并返回分隔后的字符串。replace方法// target要被替换的目标字符串。 replacement替换的字符串public String replace(CharSequence target, CharSequence replacement) { return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString()));}解析用指定的字符串替换这个字符串中与之匹配的每个子字符串。替换从字符串的开头到结尾例如在字符串 aaa 中用 b 替换 aa 将导致 ba 而不是 ab。replaceAll方法// regex这个支持正则表达式也可以是要被替换的目标字符串。public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement);}问题replace和replaceAll方法的区别是啥replaceAll支持正则表达式。针对char的replace方法// oldChar要被替换的字符newChar替换的字符public String replace(char oldChar, char newChar) { // oldChar不等于newChar if (oldChar ! newChar) { // 当前字符串的长度 int len value.length; // 这个用于下面的while循环里的条件比较val[i]中的i是从0开始的 int i -1; // 定义一个char[] val用于避免使用getfiled操作码这个可以写段代码反编译一下看看 char[] val value; /* avoid getfield opcode */ // 这个用于记录这个i的值并且判断是否有要替换的这个循环有利于性能的提升 while (i len) { // val[i]中的i是从0开始的 if (val[i] oldChar) { // 有要替换的直接跳出循环 break; } } // 上面的while循环中如果有要替换的i肯定小于len如果没有下面这个判断就不会执行 if (i len) { // 能进到这个循环肯定是有要替换的创建一个长度为len的char数组 char buf[] new char[len]; // 上面的i是记录第一个可以替换的char的索引下面这个循环是将这个i索引前的不需要被替换的填充到buf[]数组中 for (int j 0; j i; j) { // 填充buf[]数组 buf[j] val[j]; } // 从可以替换的索引i开始将剩余的字符一个一个填充到 buf[]中 while (i len) { // 获取要被替换的字符 char c val[i]; // 判断这个字符是否真的需要替换c oldChar成立就替换否则不替换 buf[i] (c oldChar) ? newChar : c; i; } // 返回替换后的字符串 return new String(buf, true); } } // oldChar等于newChar直接返回当前字符串 return this;}案例Testpublic void test_matches(){ String a adddfdefe; System.out.println(a.replace(d, b));// abbbfbefe}仿写replace方法参数针对char仿写// 和源码给的唯一不同的是参数传递,其他的都和源码一样自己写一遍可以加深记忆和借鉴编程思public String replace(String source, char oldChar, char newChar) { char[] value source.toCharArray(); if (oldChar ! newChar) { int len value.length; int i -1; char[] val value; /* avoid getfield opcode */ while (i len) { if (val[i] oldChar) { break; } } if (i len) { char buf[] new char[len]; for (int j 0; j i; j) { buf[j] val[j]; } while (i len) { char c val[i]; buf[i] (c oldChar) ? newChar : c; i; } return new String(buf); } } return new String(value);}intern方法public native String intern();这是一个native方法。调用String#intern方法时如果池中已经包含一个由equals方法确定的等于此String对象的字符串则返回来自池的字符串。否则将此String对象添加到池中并返回这个String的引用。分享上面是本人在学习路上整理的一些比较干货的java资料如果有需要的兄弟可以先关注我私信我回复【资料】即可。