String类

目录

API(Application Programming  Interface):应用程序编程接口

API(应用程序编程接口):Java写好的程序,我们不需要自己编写,直接调用即可。

​编辑

 ​编辑​编辑1.String类概述

String是不可变字符串的原因?

String为什么要设计成不可变的?

2.String类的常用方法,字符串内容比较

1.如果是字符串比较应该使用什么方式进行比较,为什么?

2. 开发中什么时候用==比较数据

3.String类常用API-遍历、截取、替换、分割

4.String类开发验证码功能

 5.模拟用户登录功能

 6.手机号码屏蔽

 案例:键盘录入一个字符串,统计该字符串大写字母字符,小写字母字符,数字字符                出现的次数

案例:拼接字符串

​编辑 

 案例:字符串反转

7.String类创建对象的两种方式

区别:

 8.String类笔试题


API(Application Programming  Interface):应用程序编程接口

API(应用程序编程接口):Java写好的程序,我们不需要自己编写,直接调用即可。

 1.String类概述

  • String类定义的变量可以用于指向字符串对象,然后操作该字符串。
  • Java中所有的字符串文字都为此类的对象。
  • String类的特点:String被称为不可变字符串类型,它的对象在创建后不能被更改。
  • 字符串的内容是不会发生改变的,它的对象在创建后不能被更改。
  • 以“”给出的字符串对象,在字符串常量池中存储,且相同内容只会存储1份。
  • 只要用双引号引起来的就是字符串,并且用字符串跟任意的数据类型进行相加,那它们做的都是拼接操作,并产生了一个新的字符串。
  • 为了方便使用,Java中的lang包是默认导入的,因此在使用其中的类时不需要显式导入该包。这些类包括Object、String、Integer等常用类。这样做可以减少代码量,提高代码的可读性和可维护性。如果您需要使用其他包中的类,则需要显式导入该包。
  • java.lang包是Java的核心包 / 是Java默认的包,在使用时候不需要导包。

String是不可变字符串的原因?

  • String变量的每次修改都是产生并指向了新的字符串对象。
  • 原来的字符串对象都是没有改变的,所以称为不可变字符串。

String为什么要设计成不可变的?

  1. 便于实现字符串池:开发中会大量的使用字符串String,如果每次声明一个String字符串就创建一个对象,造成极大的空间资源的浪费,因此Java提出了Stringpool的概念,StringPool字符串池就是解决这个问题的,在堆中开辟一块存储空间Stringpool,当初始化一个String变量时,如果该字符串已经存在了,就不会去创建一个新的字符串变量,而是会返回已有该字符串的引用。如果字符串是可变的,某一个字符串变量改变了其值,那么其指向的变量的值也会改变,StringPool将不能够实现。
  2. 使多线程安全:在并发场景下,多个线程同时读一个资源,是线程安全的,不会引发竞争,但对资源进行写操作时是不安全的,不可变对象不能被写,所以保证了多线程的安全。
  3. 加快字符串处理速度:因为String字符串对象在创建时会计算并缓存其哈希值,String字符串对象不可变保证了hashcode唯一性,所以在创建对象时其hashCode就可以放心的缓存了,不需要重新计算,如果String对象是可变的,那么每次修改字符串内容都要重新计算哈希值,影响性能,这也是Map喜欢将String作为Key的原因,处理速度要快过其它的键对象,所以HashMap中的额键往往都使用String。

2.String类的常用方法,字符串内容比较

1.如果是字符串比较应该使用什么方式进行比较,为什么?

  • 使用String提供的equals方法
  • 只关心内容一样就返回true

2. 开发中什么时候用==比较数据

  • 基本数据类型比较时使用==
  • ==号比基本数据类型比较的是数据值
  • ==号比引用数据类型比较的是地址值


import java.util.Scanner;

public class StringAPIEqualsDemo4 {
    public static void main(String[] args) {
        // 1.正确登录名和密码 变量指向字符串常量池
        String sysLoginName = "itheima";
        String sysLoginPassword = "123456";

        // 2.请您输入登录名称和密码  变量指向堆内存
        Scanner sc = new Scanner(System.in);
        System.out.println("登录名称:");
        String userName = sc.next();
        System.out.println("登录密码:");
        String userPassword = sc.next();

        // 3.判断用户输入的登录名称和密码与正确的内容是否相等
        // 等等号==比较的是字符串地址而不是字符串的内容
        // 指向字符串常量池   指向堆内存 为false
      //  if(sysLoginName == userName && sysLoginPassword == userPassword){
        if(sysLoginName.equals(userName) && sysLoginPassword.equals(userPassword)){
            System.out.println("登录成功!");
        }else{
            System.out.println("您输入的用户名或密码有误!");
        }

        // 4.忽略大小写比较内容的API:一般用于比较验证码这样的业务逻辑(验证码不在乎大小写)
         String sysCode = "23AdFh";
         String code = "23aDfH";
        System.out.println(sysCode.equals(code)); // false
        System.out.println(sysCode.equalsIgnoreCase(code)); //true
    }
}

3.String类常用API-遍历、截取、替换、分割

 

  • 数组的长度length它是一个属性,而字符串的长度length它是一个方法 
package com.api.string;

/**
    目标:掌握String常用的其他API
 */
public class StringAPiOtherDemo5 {
    public static void main(String[] args) {
        String name = "我爱你中国love";

        // 1.public int length(): 获取字符串的长度
        System.out.println(name.length()); // 9

        // 2.public char charAt(int index): 获取某个索引位置处的字符
        char c = name.charAt(1);
        System.out.println(c); //爱
        System.out.println("----------------------遍历字符串中的每个字符-----------------------");
        for(int i = 0;i < name.length();i++){
          char ch = name.charAt(i);
            System.out.print(ch); // 我爱你中国love
        }
        System.out.println();

        // 3.public char[] toCharArray(): 把字符串转换成字符数组
        char[] chars = name.toCharArray();
        for(int i = 0;i < chars.length;i++){
            char ch = chars[i];
            System.out.print(ch); // 我爱你中国love
        }
        System.out.println();

        // 4.public String substring(int beginIndex,int endIndex): 截取内容,(包前不包后的) substring:截取
        String name2 = "Java是最厉害的编程语言!";
        //              0123456789
        String rs = name2.substring(0,9);
        System.out.println(rs); // Java是最厉害的
        String rs2 = name2.substring(4,9);
        System.out.println(rs2); // 是最厉害的

        // 5.public String substring(int beginIndex):从当前索引一直截取到末尾
        String rs3 = name2.substring(4);
        System.out.println(rs3); // 是最厉害的编程语言!

        // 6.public String replace(CharSequence target,CharSequence replacement):作敏感词替换
        //           CharSequence:理解成字符串,就是String的意思  target:目标,对象   replacement:更换
        String name3 = "金三胖是最厉害的80后,金三胖棒棒的!我好爱金三胖";
        String rs4 = name3.replace("金三胖","***");
        System.out.println(rs4); //***是最厉害的80后,***棒棒的!我好爱***


        // 7.public boolean contains(CharSequence s)  看是否包含xxx
        System.out.println(name3.contains("金三胖")); // true
        System.out.println(name3.contains("金二胖")); // false

        // 8.public boolean startsWiths(String prefix)  判断是否以xxx开始
        System.out.println(name3.startsWith("金三胖")); // true
        System.out.println(name3.startsWith("金三胖是最厉害的")); // true
        System.out.println(name3.startsWith("金三胖是最厉害的2")); // false

        // 9.public String[] split(String s):按照某个内容把字符串分割成字符串数组返回。
        String name4 = "王宝强,贾乃亮,陈羽凡";
        String[] str = name4.split(",");
        for (int i = 0; i < str.length; i++) {
            System.out.println("选择了:"+str[i]); 
        }

    }
}

4.String类开发验证码功能

需求:随机产生一个5位的验证码,每位可能是数字,大写字母,小写字母

分析:

  • 定义一个String类型的变量存储a-z,A-Z,0-9之间的全部字符
  • 循环5次,随机一个范围内的索引,获取对应字符连接起来即可

import java.util.Random;

/**
    练习题:使用String完成随机5位的验证码
 */
public class StringExec6 {
    public static void main(String[] args) {
       // 1.定义可能出现的字符信息
        String datas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        // 2.循环5次,每次生成一个随机的索引,提取对应的字符连接起来即可
        String code = "";
        Random r = new Random();
        for (int i = 0; i < 5; i++) {
            // 随机一个索引
            int index = r.nextInt(datas.length());
            char ch = datas.charAt(index);
            code += ch;
        }
        // 3.输出字符串变量即可
        System.out.println(code);
    }
}

package com.API20221226;

import java.util.Random;

/**
    目标:用String类开发验证码
 */
public class StringTest1 {
    public static void main(String[] args) {
        String datas = "abcdefghijklmnopqrstovwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String code = createCode(datas,5);
        System.out.println(code);

    }

    /**
        要求用户输入验证码的位数,随机一个验证码出来
     */
    public static String createCode(String datas,int n){
        Random r = new Random();
        String code = "";
        for (int i = 1;i <= n;i++) {
            // 1.随机一个索引出来
            int index = r.nextInt(datas.length());
            // 2.获取索引位置处的字符并连接起来
            char ch =  datas.charAt(index);
            code += ch;
        }
       return  code;
    }
}

 5.模拟用户登录功能

需求:模拟用户登录功能,最多给三次机会

分析:

  • 系统后台定义好正确的登录名称和密码
  • 使用循环控制三次,让用户输入登录名和密码,判断是否登陆成功
  • 登陆成功则不再进行登录,登陆失败给出提示,让用户继续登录

import java.util.Scanner;

/**
    练习题:模拟用户登录
 */
public class StringExec7 {
    public static void main(String[] args) {
        // 1.定义正确的登录名和密码
        String okLoginName = "admin";
        String okPassword = "it";

        // 2.定义一个循环,循环3次,让用户登录
        Scanner sc = new Scanner(System.in);
        for (int i = 1; i <= 3; i++) {
            System.out.println("请您输入登录名称:");
            String loginName = sc.next();
            System.out.println("请您输入登录密码:");
            String password = sc.next();

            // 3.判断登录是否成功
            if(okLoginName.equals(loginName)){
                if(okPassword.equals(password)){
                    System.out.println("登陆成功!欢迎进入系统随意浏览~~~");
                    break; // 登陆成功,跳出并结束当前for循环
                }else{
                    // 密码错误了
                    System.out.println("您的密码不正确,您还剩余" + (3-i) + "次机会登录~~~");
                }
            }else{
                // 登录名错误了
                System.out.println("您的登录名称不正确,您还剩余" + (3-i) + "次机会登录~~~");
            }
        }
    }
}

 6.手机号码屏蔽

需求:键盘录入一个手机号,将中间4位号码屏蔽。

 分析:

  1. 键盘录入一个字符串
  2. 调用字符串对象的截取API,截取字符串前三位,后四位
  3. 将前三位,连接“****”然后继续连接后四位,输出最后结果即可

import java.util.Scanner;

/**
    练习题:手机号码屏蔽
 */
public class StringExec8 {
    public static void main(String[] args) {
        // 1.键盘录入一个手机号码  012 3456 789
        System.out.println("请您输入手机号码:");
        Scanner sc = new Scanner(System.in);
        String tel = sc.next();
        
        // 方案:截取号码的前三位,后四位  012 3456 789
        String before = tel.substring(0,3); // 0 1 2
        String after = tel.substring(7); // 从索引7开始截取到手机号码的末尾
        String s = before + "****" + after;
        System.out.println(s);
    }
}

 案例:键盘录入一个字符串,统计该字符串大写字母字符,小写字母字符,数字字符                出现的次数

package com.string.api;

import java.util.Scanner;

/**
   键盘录入一个字符串,统计该字符串大写字母字符,小写字母字符,数字字符出现的次数
 */
public class StringDemo2 {
    public static void main(String[] args) {
        // 1.键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = sc.next();
        
        // 2.统计 --- 计数器思想
        // 定义三个计数器
        int bigCount = 0; // 记录大写字母
        int smallCount = 0; // 记录小写字母
        int numberCount = 0; // 记录数字
        for (int i = 0; i < str.length(); i++) {
            // i依次表示字符串中的每一个索引
            char c = str.charAt(i);
            if(c >= 'a' && c <= 'z'){
                // char类型变量在参与计算的时候自动类型提升为int 查询ASCII表
                smallCount++;
            } else if (c >= 'A' && c <= 'z') {
                bigCount++;
            }else if(c >= '0' && c <= '9'){
                numberCount++;
            }
        }

        // 3.输出打印
        System.out.println("大写字母有:" + bigCount + "个");
        System.out.println("小写字母有:" + smallCount + "个");
        System.out.println("数字字符有:" + numberCount + "个");
    }
}

案例:拼接字符串

 

package com.string.api;

public class StringDemo3 {
    public static void main(String[] args) {
       // 动态初始化数组
       int[] arr = {1, 2, 3, 4, 9, 0};
       String rs = arrToString(arr);
       System.out.println(rs); // [1, 2, 3, 4, 9, 0]
    }

    // 1.我要干嘛? ---- 遍历数组并把数组拼接成一个字符串
    // 2.我干这件事情需要什么才能完成? --- 数组
    // 3.我干完了是否需要把结果返回给调用处 --- 返回一个拼接之后的字符串
    // 如果调用处需要继续使用,那么必须返回
    // 如果调用处不需要继续使用,那么可以返回也可以不返回
    public static String arrToString(int[] arr){
        if(arr == null){
            return "";
        }

        if(arr.length == 0){
            return "[]";
        }

        // 当代码执行到这里,表示当前数组不为null,长度也不为0
        String rs = "";
        System.out.print("[");
        for (int i = 0; i < arr.length; i++) {
            // i--->索引  arr[i]--->元素
//            result += arr[i];
            System.out.print(i == arr.length - 1 ? arr[i] : arr[i] + ", ");
        }
        System.out.print(rs + "]");
        return rs;
    }
}

 案例:字符串反转

定义一个方法,实现字符串反转。

键盘录入一个字符串,调用该方法后,在控制台输出结果

例如,键盘录入abc,输出结果cba

package com.string.api;

/**
   字符串的反转
 */
public class StringDemo4 {
    public static void main(String[] args) {
        System.out.println(reverse("7897912315213")); // 312513219798
    }

    // 1.我要干嘛? --- 字符串的反转
    // 2.我干这件事情,需要什么才能完成? --- 需要一个字符串
    // 3.调用处是否需要继续使用方法的结果呢? --- 需要结果进行输出
    public static String reverse(String str){
        // forr:倒着遍历
        String rs = "";
        for (int i = str.length() - 1; i > 0; i--) {
            rs += str.charAt(i);
        }
        return rs;
    }
}

7.String类创建对象的两种方式

  1. 方式一:直接使用“ ”定义
  2. 方式二:通过String类的构造器创建对象

package com.api.string;

/**
    目标:String类创建字符串对象的两种方式
 */
public class StringDemo2 {
    public static void main(String[] args) {
          // 方式一:直接使用双引号得到字符串对象
        String name = "我爱你中国!";
        System.out.println(name); // 根据地址找到这个内容,作了一层特殊优化

        // 方式二:通过String类提供的构造器来创建字符串对象
        // 1.public String():创建一个空白字符串对象,不含有任何内容(几乎不用)
        String s1 = new String(); // s1 = "" ,s1指向了一个空字符串
        System.out.println(s1);

        // 2.public String(String):根据传入的字符串内容,来创建字符串对象(几乎不用)
        String s2 = new String("我是中国人");
        System.out.println(s2);

        // 3.public String(char[] c):根据字符数组的内容,来创建字符串对象
        // 传递一个字符数组,根据字符数组的内容再创建一个新的字符串对象
        // 需求:我要修改字符串的内容。 abc ===> Qbc
        // abc ===> {'a', 'b', 'c'} ===> {'Q' , 'b' , 'c'} ===> "Qbc"
        char[] chars = {'a','b','中','国'};
        String s3 = new String(chars); // 内部会自动的把每个字符连在一起,相当于这个构造器会遍历每个字符,遍历完把它拼接成字符串再返回给你
        System.out.println(s3); // 把字符数组转成字符串

        // 4.public String (byte[] b):根据字节数组的内容,来创建字符串对象 
        // byte范围:-128-127
        // 传递后一个字节数组,根据字节数组的内容再创建一个新的字符串对象
        // 应用场景:以后在网络当中传输的数据其实都是字节信息
        // 我们一般要把字节信息进行转换,转成字符串,此时就要用到这个构造了。
        byte[] bytes = {97, 98, 99, 65, 66, 67};
        String s4 = new String(bytes); //它会把字节数组里面的整数全部转成字符串的字符
        System.out.println(s4); // abcABC

        System.out.println("------------------------------------");
        String ss1 = "abc";
        String ss2 = "abc";   // true  两个变量指向了同一个字符串对象
        System.out.println(ss1 == ss2); // 比较的是两个字符串变量里面存储的地址

        char[] chars1 = {'a','b','c'};
        String ss3 = new String(chars1);
        String ss4 = new String(chars1); // 两个变量指向的是不同的对象
        System.out.println(ss3 == ss4); // fasle
    }
}
  • 栈内存:方法运行的时候进栈,执行完毕出栈
  • 堆内存:new出来的对象都在这里
  • 方法区:加载字节码文件到方法区单中临时存储
  • String Table(串池):就是字符串常量池。JDK7以前,字符串常量池在方法区里面,从JDK7版本开始,字符串常量池从方法区挪到了堆内存。

  • 当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在。
  • 不存在:创建新的
  • 存在:复用
  • 以双引号方式给出的字符串对象,在字符串常量池中存储。字符串常量池就在堆内存里面。
  • 字符串变量指向字符串对象,字符串变量里面存的是字符串对象的地址,但是变量输出的时候为啥不是地址呢?是根据地址把这个内容给输出的。(与继承有关,因为String类重写了toString方法)。String变量是根据地址找到这个内容。
  • 新运算出来的字符串对象是运算出来的,是放在堆内存里面。
  • String常被称为不可变字符串类型,它的对象在创建后不能被更改。
  • 创建出来的字符串对象没有改变,还是在字符串常量池中。只不过每次字符串变量指向了新的字符串对象。
  • String是字符串类,他可以定义字符串变量指向字符串对象。
  • String是不可变字符串的原因?
  • String变量每次的修改都是产生并指向了新的字符串对象。原来的字符串对象还是在字符串常量池中是没有改变的,所以称String为不可变字符串。
  • 以“”方式给出的字符串对象,在字符串常量池中存储,而且相同内容只会在其中存储一份。为了节省内存资源。

区别:

  • 以双引号给出的字符串对象,在字符串常量池中存储,且相同内容只会存储1份
  • 通过构造器new对象,每new一次就会产生一个新对象,在堆内存中分开存储

 8.String类笔试题

public class Test2 {
    public static void main(String[] args) {
        // 1.下面这行代码总共产生了几个对象?
        // 答:这行代码实际上创建了两个对象,双引号的abc要出现在字符串常量池中,而new出来的对象要放在堆内存中
        String s2 = new String("abc"); //定义了一个String类型的变量s2指向了new出来的String对象

        // 2.下面这行代码没有创建对象,因为常量池中已经有字符串abc,不用再创建了
        String s1 = "abc"; //比较的是地址,s1指向了常量池中的abc,而s2指向了new出来的这个对象,所以结果是false
        System.out.println(s1 == s2);
    }
}


public class Test3 {
    public static void main(String[] args) {
        String s1 = "abc"; //s1指向的字符串对象是指向常量池中的abc
        String s2 = "ab";
        // "abc" s3是通过变量s2运算出来的结果,运算出来的结果它不是双引号直接给出来的,它是放在堆内存里面的
        // 所以s3会指向堆内存中的abc
        String s3 = s2 + "c";
        System.out.println(s1 == s3); // fasle
    }
}

public class Test4 {
    public static void main(String[] args) {
        // 1.什么是编译? 把代码翻译成class文件
        // Java存在编译优化机制,程序在编译时,"a" + "b" + "c"会直接转成"abc"
        // 有什么好处? 极大的节省内存空间,提高效率,提高性能
        // 对变量没有进行编译优化机制,只有对字面量才有编译优化机制,
        // 因为变量到底最终指向谁只有运行起来才知道
        String s1 = "abc";
        String s2 = "a" + "b" + "c";
        //两个变量都指向了常量池中的abc,所以结果为true
        System.out.println(s1 == s2);
    }
}
  • sc.next( )源码底层它是new出来一个字符串 
  • 键盘录入得到的字符串是new出来的

package com.string.api;

import java.util.Scanner;

/**
 * @author A.G.H
 */
public class StringDemo {
    public static void main(String[] args) {
        // 1.假设我现在键盘录入一个abc
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str1 = sc.next(); // 键盘录入得到的字符串是new出来的
        // 2.代码中再定义一个字符串abc
        String str2 = "abc";
        // 3.用==号比较,这两者能一样吗?
        System.out.println(str1 == str2); // false
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Surpass余sheng军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值