Java的学习 11.24

本文主要探讨了Java中String类的使用,包括API文档的查阅、实战练习、底层实现原理的解析,以及常出现在面试中的相关问题。同时,还特别关注了String的不可变性特点。
摘要由CSDN通过智能技术生成

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(", ");
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值