Java学习 11.24

Java学习 String类

1.1 API文档的使用

我们java是开源的,所以又很多类看不懂可以看底层代码。例如:
@Test
   public void test1(){

       String  str = "asdfasdf";
       char a = str.charAt(6);
       System.out.println(a);
       
  }    
   
此时我们charAt究竟作用是什么,参数代表什么意思 返回值代表什么意思我们无从得之,所以可以ctrl+左键查看代码  

/**
    * Returns the {@code char} value at the
    * specified index. An index ranges from {@code 0} to
    * {@code length() - 1}. The first {@code char} value of the sequence
    * is at index {@code 0}, the next at index {@code 1},
    * and so on, as for array indexing.
    *
    * <p>If the {@code char} value specified by the index is a
    * <a href="Character.html#unicode">surrogate</a>, the surrogate
    * value is returned.
    *
    * @param     index   the index of the {@code char} value.
    * @return     the {@code char} value at the specified index of this string.
    *             The first {@code char} value is at index {@code 0}.
    * @exception IndexOutOfBoundsException if the {@code index}
    *             argument is negative or not less than the length of this
    *             string.
    */
   public char charAt(int index) {
       if ((index < 0) || (index >= value.length)) {
           throw new StringIndexOutOfBoundsException(index);
      }
       return value[index];
  }

这个方法很慢,所以就有了API(Application Programming Interface,应用程序接口)文档,他有中文版 而且所有类都包含了,我们看起来就方便了
   
首先打开文档    
   
我们发现其将java所有的类都罗列出来了
java中的常用包:  lang java的语言核心包    io java的输入输出流  math 数学工具包
                net  java的网络包       sql java中数据库操作相关的包   util java的工具包
   
   
 我们要使用得类是String  所以通过索引搜索String
   
A 继承关系
public final class String
extends Object
implements Serializable, Comparable<String>, CharSequence

B String的简介
C 构造方法    
D 静态方法
E 接口方法
   
所以实现某个功能可以去百度    

1.2 String练习题


1  有一个字符串 "hello world" ,请获取其第三个子字符
2  有一个字符串 "hello world" ,请判断 lo首次出现的索引位置
3  有一个字符串 " hello world   " ,请去处其空格
4  有一个字符串 "hello world" 请将 world 换成 java
5  有一个字符串 "hello world" 是否包含 ld ?
6  有一个字符串 "hello world" 请将其转换成全大写
7  有一个字符串 "hello world" 请获取字符串整体的长度
8  有一个字符串 "hello world" 判断是否为空
9  有一个字符串 "123,356,5873245" 从其中将 356 提出出来
10 有一个字符串 "hello world" 请和两一个字符串比较是否完全一致 "hello worLD"
11 有一个 整数20 ,请将其转换成 String类型
12 有一个字符串 "666" 请将其转换成 int类型

public class JavaTest {

   @Test
   public void test1(){

       String  str = "hello world";

       /*获取指定范围内的子字符 前闭后开*/
       String  a1 = str.substring(3,4);
       System.out.println(a1);

       /*获取指定索引位置的子字符 */
       char a2 = str.charAt(3);
       System.out.println(a2);
  }
   @Test
   public void test2(){

       String  str = "hello world";
       /*判断某个字符串在 指定字符串中首次出现索引位置 如果没有则返回-1*/
       int   index  = str.indexOf("lo");
       System.out.println(index);

  }

   @Test
   public void test3(){

       String  str = "   hello world   ";
       /*去掉首尾空格 返回一个新字符串 老字符串没变*/
       String  a3 =  str.trim();
       System.out.println(a3);
       System.out.println(str);
  }
   @Test
   public void test4(){

       String  str = "   hello world   ";
       String  a4 = str.replace("world","java");
       System.out.println(a4);

  }

   @Test
   public void test5(){

       String  str = "   hello world   ";
       boolean a5 =  str.contains("dl");
       System.out.println(a5);
  }
   @Test
   public void test6(){

       String  str = "   hello nihao shijie   ";
       String  a6 =  str.toUpperCase();
       System.out.println(a6);
  }
   @Test
   public void test7(){

       String  str = "   hello nihao shijie   ";
       int  a6 =  str.length();
       System.out.println(a6);
  }
   @Test
   public void test8(){

       String  str = "";
       boolean a6 =  str.isEmpty();
       System.out.println(a6);
  }
   @Test
   public void test9(){

       String  str = "123,356,5873245";
       // [123, 356, 5873245]
       String[]  arr =  str.split("5");

       System.out.println(Arrays.toString(arr));
  }
   @Test
   public void test10(){

       String  str = "123,356,5873245";
       String  str1 = "hello world";

       boolean a6 =  str.equals(str1);
       System.out.println(a6);
  }
   @Test
   public void test11(){

       int  a = 20;
       /* "20" */
       String  b = String.valueOf(a);
       System.out.println(b);

  }

   @Test
   public void test12(){

       String str = "666";
       int  a = Integer.parseInt(str);
       System.out.println(a);

  }

}

1.3 String底层原理


要想看清楚一个类的底层原理 就要从他的构造函数开始看起。
   String  str = new String();
查看其底层  
/**
    * 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 = "".value;
  }
所以我们就得到了一个结论 当前类有一个 value的成员变量。所以我们就继续查看value 的真是面貌
  /** The value is used for character storage. */
   private final char value[];  
所以我们得到一个结论:  String 的底层就是一个char数组
例如:
我们写代码的时候   String  str  = "hello";
底层相当于这样写的  char[]  value  = {'h' , 'e' , 'l' ,'l' , 'o'};


1 当我们调用  char  a1 = str.charAt(3);获取指定索引位置的子字符 其实在底层就是 从数组中获取指定索引位置的子字符

  public char charAt(int index) {
       if ((index < 0) || (index >= value.length)) {
           throw new StringIndexOutOfBoundsException(index);
      }
       return value[index];
  }

2 当我们调用 int len = str.length();获取字符串的长度   其实在底层就是 返回value数组的长度
   
  public int length() {
       return value.length;
  }
3 当我们调用 boolean  a2  =  str.isEmpty(); 判断字符串是否为kong  其实底层就是 判断数组的长度是否为0
 public boolean isEmpty() {
       return value.length == 0;
  }
4 当我们调用 boolean a4 =  str.equals("asd"); 判断俩字符串是否一样  其实底层就是 判断倆数组是否完全一样
 public boolean equals(Object anObject) {
       // 判断引用地址是否一样 如果一样 则证明就是同一个对象 直接返回true
       if (this == anObject) {
           return true;
      }
       // 判断 参数是不是字符串类型 如果不是字符串 返回 false  
       if (anObject instanceof String) {
           String anotherString = (String)anObject;
           int n = value.length;
           // 判断两个数组的长度是否一致 如果不一致则返回false  
           if (n == anotherString.value.length) {
               char v1[] = value;
               char v2[] = anotherString.value;
               int i = 0;
               while (n-- != 0) {
                   // 判断每个索引位置的子字符是否一致 如果不一致则返回false
                   if (v1[i] != v2[i])
                       return false;
                   i++;
              }
               // 如果循环结束还没有return 证明都一样 则返回true
               return true;
          }
      }
   
       return false;
  }  

1.4 String的面试题


1 String能否被继承?为什么?
2 String有么有length属性?数组有没有length属性?
 String只有  length() 函数,数组没有length函数但是有 length属性 arr.length
   
3 以下代码输出什么?
   
       String temp = "hello";
       String  a1 = "helloworld";
       String  a2 = "hello" + "world";
       String  a3 = temp+"world";

       System.out.println(a1 == a2); // true
       System.out.println(a1 == a3); // false

底层是这个样子的:
   a1 "helloworld";  a2 "helloworld"; 因为a2的源码是 "hello" + "world"; 编译的时候 编译器一看"hello" + "world"; 那不就是"helloworld"; 所以 a2编译成字节码之后 直接就是 "helloworld";  所以 a1 == a2 就是 true

   a3是temp+"world"; 编译之后 变成了这个样子  
       String temp = "hello";
String a1 = "helloworld";
String a2 = "helloworld";
String a3 = (new StringBuilder()).append(temp).append("world").toString();
System.out.println(a1 == a2);
System.out.println(a1 == a3);

   所以 a1的引用是 helloworld的内存地址  a3的引用是StringBuilder对象的地址  所以  a1 == a3 是false

4 以下代码输出什么?  == equals的 区别?
       String str1 = new String("123");
       String str2 = new String("123");

       System.out.println(str1 == str2);
       System.out.println(str1.equals(str2));

  == 判断的是引用地址是否相同, equals的情况就不确定了 得看当前类是否重写了equals。如果没有重写 则调用父类Object的equals
  public boolean equals(Object obj) {
       return (this == obj);
  }
   Object的equals底层还是用 == 进行判断。但是当前str1 是String类型 String重写了父类的equals 变成了判断内容是否相同
   public boolean equals(Object anObject) {
       if (this == anObject) {
           return true;
      }
       if (anObject instanceof String) {
           String anotherString = (String)anObject;
           int n = value.length;
           if (n == anotherString.value.length) {
               char v1[] = value;
               char v2[] = anotherString.value;
               int i = 0;
               while (n-- != 0) {
                   if (v1[i] != v2[i])
                       return false;
                   i++;
              }
               return true;
          }
      }
       return false;
  }

5 请问以下代码分别创建了几个对象
       String  a1 = "123";
       String  a2 = new String("445");
 a1 创建了 1 个或 0
     因为 a1的形式子字符常量,所以首先先要去常量池中找是否有 123 ,如果有则直接引用,就是创建了0个。如果没有则创建并引用 所以是一个    
 a2 创建了 1 个或 2
     因为 a2 是引用堆区的对象  ,new String 肯定要在堆区造一个String对象,再看 445 在常量池中有没有

1.5 可变字符串


String 是一个 不可变字符串,例如  "a"+"b" 需要在内存中创建一个 a 在创建一个 b 再创建一个 ab
所以String在拼接的时候特别耗性能
例如:
public static String toMyString(int[] arr){

       String  str = "[";
       for (int i = 0; i < arr.length; i++) {
           str += arr[i];
           if(i == arr.length-1){
               str += "]";
          }else{
               str += ",";
          }
      }

       return str;
  }
所以我们在拼接的时候需要使用可变字符串
       StringBuilder  sb = new StringBuilder();
       sb.append("123").append("465");
       
       StringBuffer  sb = new StringBuffer();
       sb.append("123").append("456");
所以Arrays 底层就是用 StringBuilder 拼接
   public static String toString(long[] a) {
       if (a == null)
           return "null";
       int iMax = a.length - 1;
       if (iMax == -1)
           return "[]";

       StringBuilder b = new StringBuilder();
       b.append('[');
       for (int i = 0; ; i++) {
           b.append(a[i]);
           if (i == iMax)
               return b.append(']').toString();
           b.append(", ");
      }
  }

 

posted @ 2021-11-29 20:56  吴光熠  阅读(37)  评论(0)    收藏  举报