20.Java String 类详解/String类的常量池(了解)/String 类常用方法(掌握)/内部类(了解)

String 类详解

重点是练方法的使用,不用去深究方法的实现。

简述

String 类又称作不可变字符序列。
String 位于 java.lang 包中,Java 程序默认导入 java.lang 包下的所有类。
Java 字符串是 Unicode 字符序列,例如:"Java" 即是 4 个 Unicode 字符 ‘J’、‘a’、‘v’、‘a’ 组成的。
Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个预定义的类 String,每个用双引号括起来的字符串都是 String 类的一个实例。

代码示例

(1)String 类的简单使用

String e = "";//空字符串
String greeting = "helloworld!"; 

(2)字符串连接

String s1 = "Hello!";
String s2 = "World!";
String s = s1 + "," + s2;  

注意点

Java 允许使用符号 "+",把两个字符串连接起来。
在 "+" 运算符两侧的操作数中,只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串,然后再进行连接。

字符串相等判断

用双引号包裹起来的字符串, 比如 "abcdefg",都是在方法区的常量值位置存放。
符号 “==” :用于比较是否是同一个对象,如果不是,则值为 false
equals() 方法:比较两个字符串对象包含的字符是否一样,用 equals() 方法

代码示例:测试字符串相等判断

package cn.jungle.test.String;

// 测试字符串相等判断
public class Test01 {
    public static void main(String[] args) {
        String str1 = new String("abcdefg");
        String str2 = "abcdefg";
        // == 符号用于比较两个对象是否相等,下方的 str1 和 str2 内存地址不相等,所以 false
        System.out.println(str1 == str2);       // false
        System.out.println(str1);               // abcdefg
        System.out.println(str2);               // abcdefg
        // 涉及字符串比较的时候,都用 equals 方法:比较两个字符串对象包含的字符是否一样
        System.out.println(str1.equals(str2));  // true
    }
}

String类的常量池(了解)

  1. 全局字符串常量池(String Pool)

全局字符串常量池中存放的内容是在类加载完成后存到 String Pool 中的,在每个 VM 中只有一份,存放的是字符串常量的引用值(在堆中生成字符串对象实例)。

  1. class 文件常量池(Class Constant Pool)

class 常量池在编译时每个 class 都会有,在编译阶段,存放的是常量(文本字符串、final 常量等)和符号引用。

  1. 运行时常量池(Runtime Constant Pool)

运行时常量池是在类加载完成之后,将每个 class 常量池中的符号引用值转存到运行时常量池中,也就是说,每个 class 都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。

String 类常用方法(掌握)

charAt(int index)

返回值类型为 char
返回字符串中第 index 个字符 。

length()

返回类型为 int
返回字符串的长度。

equals(String other)

返回值类型为 boolean
如果字符串与 other 相等,则返回 true,否则返回 false。

equalsIgnoreCase(String other)

返回值类型为 boolean
如果字符串与 other 相等(忽略大小写),则返回 true;否则返回 false。

indexOf(String str)

返回值类型为 int
返回从头开始查找第一个子字符串 str 在字符串中的索引位置。
如果未找到子字符串 str,则返回 -1

lastIndexOf()

返回值类型为 int
返回从末尾开始查找第一个子字符串 str 在字符串中的索引位置。
如果未找到子字符串 str,则返回 -1

replace(char oldChar,char newChar)

返回一个新字符串,它通过用 newChar 替换此字符串中出现的所有 odlChar 而生成。
可以替换一个字符,也可以替换一堆字符。

startsWith(String prefix)

返回值类型为 boolean
如果字符串以 prefix 开头,则返回 true。

endsWith(String prefix)

返回值类型为 boolean
如果字符串以 prefix 结尾,则返回 true。

substring(int beginIndex)

返回值类型为 String
返回一个新字符串,该串包含从原始字符串 beginIndex 索引位置到串尾。

substring(int beginIndex,int endIndex)

返回值类型为 String
返回一个新字符串,该串包含从原始字符串 beginIndex 索引位置到串尾或者到 endIndex-1 索引位置的所有字符串。

toLowerCase()

返回值类型为 String
返回一个新字符串,该串将原始字符串中所有的大写字母改为小写字母。

toUpperCase()

返回值类型为 String
返回一个新字符串,该串将原始字符串中的所有小写字母改成大写字母。

trim()

返回值类型为 String
返回一个新字符串,该串删除了原始字符串头部和尾部的空格。

代码示例:String 类常用方法

package cn.jungle.test.String;

// 测试 String 类的常用方法
public class Test02 {
    public static void main(String[] args) {
        String str1 = "阿jun修炼手册";
        String str2 = "阿jun";
        String str3 = "阿jUN";  // 用于与 str2 比较
        String str4 = "阿jun没对象!";
        // charAt(int index) 方法:找到并输出对应索引的字符,索引从 0 开始
        System.out.println(str1.charAt(0)); // 阿
        System.out.println(str1.charAt(6)); // 手
        // length() 方法:输出字符串的长度
        System.out.println(str1.length());  // 8
        // 取字符串的最后一个字符
        System.out.println(str1.charAt(str1.length()-1)); // 册
        // equals(String other) :比较两个字符串对象的字符串内容是否相等
        System.out.println(str1.equals(str2));  // false
        // equalsgnoreCase(String other):比较两个字符串对象的字符串是否相等,忽略大小写
        System.out.println(str2.equalsIgnoreCase(str3));  // true
        // indexOf(String str):返回从头开始查找第一个子字符串 str 在字符串中的索引位置。如果未找到子字符串 str,则返回 -1
        System.out.println(str1.indexOf("u"));    // 2
        System.out.println(str1.indexOf("UN"));   // -1
        System.out.println(str1.indexOf("jun"));  // 1
        // lastIndexOf():返回从末尾开始查找第一个子字符串 str 在字符串中的索引位置。如果未找到子字符串 str,则返回 -1
        System.out.println(str1.lastIndexOf("u"));     // 2
        System.out.println(str1.lastIndexOf("手"));    // 6
        System.out.println(str1.lastIndexOf("U"));    // -1
        // replace(char oldChar,char newChar):返回一个新字符串,它通过用 newChar 替换此字符串中出现的所有 odlChar 而生成。可以替换一个字符,也可以替换一堆字符。
        System.out.println(str4.replace("没对象!","修炼手册"));  // 阿jun修炼手册 ,其中可以替换一个字符,也可以替换一堆字符。
        // 可以替换一个字符,也可以替换一堆字符。
        System.out.println(str4.replace("!",",他应该快有对象了吧!,现在是2021年11月24日22:21"));
        // startsWith(String prefix):如果字符串以 prefix 开头,则返回 true
        System.out.println(str1.startsWith("阿jun"));  // true
        System.out.println(str1.startsWith("jun"));   // false
        // endsWith(String prefix):如果字符串以 prefix 结尾,则返回 true
        System.out.println(str1.endsWith("手册"));     // true
        System.out.println(str1.endsWith("有手就行!")); // false
        System.out.println("有手就行!".endsWith("行不行")); // false ,也可以直接使用字符串去调用 String 类方法
        // substring(int beginIndex):返回一个新字符串,该串包含从原始字符串 beginIndex 索引位置到串尾。
        System.out.println(str1.substring(4));  // 修炼手册
        System.out.println(str1.substring(0));  // 阿jun修炼手册
        // substring(int beginIndex,int endIndex):返回一个新字符串,该串包含从原始字符串 beginIndex 索引位置到串尾或者 endIndex-1 索引位置的所有字符串。
        System.out.println(str1.substring(0,4));// 阿jun
        System.out.println(str1.substring(4,str1.length()));// 修炼手册
        // toLowerCase():返回一个新字符串,该串将原始字符串中所有的大写字母改为小写字母。
        System.out.println("阿JUN".toLowerCase());  // 阿jun
        // toUpperCase():返回一个新字符串,该串将原始字符串中的所有小写字母改成大写字母。
        System.out.println("阿jun".toUpperCase());  // 阿JUN
        // trim():返回一个新字符串,该串删除了原始字符串头部和尾部的空格。
        String str5 = " 阿 jun 修炼手册 ";
        System.out.println(str5.trim()); // 阿 jun 修炼手册
        // 去除所有空格,trim() 方法和 replace() 方法搭配着来
        System.out.println(str5.trim().replace(" ","")); // 阿jun修炼手册
    }
}

内部类(了解语法即可)

简述

内部类是一类特殊的类,指的是定义在一个类内部的类
把一个类放在另一个类的内部定义,称为内部类
内部类可以用 public、default、protected、private 以及 static 修饰。
而外部顶级类只能使用 public 和 default 修饰。

注意点:

内部类只是一个编译时概念,一旦编译成功后,就会成为完全不同的两个类。
内部类是相对独立的一种存在,其成员变量/方法名可以和外部类相同

内部类的概念

内部类的分类

  1. 成员内部类,又分为非静态内部类和静态内部类
  2. 匿名内部类
  3. 局部内部类

内部类可以用 public、default、protected、private 以及 static 修饰。
而外部顶级类只能使用 public 和 default 修饰。

代码示例

package cn.jungle.test.Class;

// 外部类
public class Cuter1 {
    private int age = 10;
    private void show(){
        System.out.println("我是阿jun呀!");
    }
    
    // 内部类
    public class Inner1{
        private String str1 = "这里是内部类定义的私有字符串";
        private int age = 20;

        public void showInner(){
            System.out.println("Inner.showInner()");
            // 打印的是外部类的 age 成员变量值
            System.out.println(age);
            // 当外部类属性和内部类属性发生重名时,可以通过 Cuter1.this.成员变量 的方法来调用内部类的成员变量
            System.out.println(Cuter1.this.age);
            // 内部类可以直接使用外部类的成员!
            show();
        }
    }
    public static void main(String[] args) {
        // 给内部类定义对象
        Cuter1.Inner1 inner01 = new Cuter1().new Inner1();
        // 内部类对象调用内部类方法
        inner01.showInner();
    }
}

非静态内部类

简述

非静态内部类对象必须寄存在一个外部类对象里。
非静态内部类对象单独属于外部类的某个对象。
非静态内部类不能定义静态方法、静态属性和静态初始化。
如果有一个非静态内部类对象,那么一定存在对应的外部类对象。
非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态类成员。
成员变量访问要点:
(1)内部类里方法的局部变量 : 变量名
(2)内部类属性:this.变量名
(3)外部类属性:外部类名.this.变量名

代码示例:测试非静态内部类

package cn.jungle.test.Class;
/**
 * 测试非静态内部类
 */

// 定义外部类 Cuter2
public class Cuter2 {
    private int age = 10;
    public void show(){
        System.out.println(age); // 10
    }
    /* 定义内部类 Inner2 */
    public class Inner1{
        // 内部类中可以声明与外部类同名的属性和方法
        private int age = 20;
        public void show(){
            System.out.println(age); // 20
            // 访问外部类的普通属性
            System.out.println(Cuter2.this.age); // 10
        }
    }
}

静态内部类

定义格式

static class ClassName{
  // 类体
}

使用要点

静态内部类可看做外部类的一个静态成员。
静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员。

代码示例:测试静态内部类

package cn.jungle.test.Class;
/**
 * 测试静态内部类
 */

// 定义外部类
class Cuter3 {
    private int a = 10;
    private static int b = 20;
    // 定义静态内部类,相当于外部类的一个静态成员
    static class Inner3{
        public void test(){
//            System.out.println(a); // 这里会报错,静态内部类不能访问外部类的普通属性
            System.out.println(b); // 20 ,静态内部类可以访问外部类的静态属性
        }
    }
}

public class TestStaticInnerClass {
    public static void main(String[] args) {
        // 通过 new 外部类名.内部类名() 的形式来创建内部类对象
        Cuter3.Inner3 inner = new Cuter3.Inner3();  // 创建静态内部类对象
        inner.test();  // 20
    }
}

匿名内部类

适合只使用一次的类。
比如:键盘监听操作。

语法:

new 父类构造器(实参类表)\实现接口() {
    // 匿名内部类类体
}

代码示例:测试匿名内部类

package cn.jungle.test.Class;
/**
 * 测试匿名内部类
 */

// 定义一个 A 接口
interface A {
    void run();
}
// 有名字的类,可以反复使用
class AA implements A{

    @Override
    public void run(){
        System.out.println("AA.run");
    }
}

public class TestAnonymouseInnerClass {
    public void test(A a){
        a.run();
    }
    // 定义 main 主体方法
    public static void main(String[] args){
        TestAnonymouseInnerClass t = new TestAnonymouseInnerClass();
        t.test(new AA());
        // 定义匿名类的方法:全部内容都在 test() 中的两个括号包裹
        t.test(new A(){
            // 方法的重写(因为继承了接口 A,所以必须实现 run() 方法)
            @Override
            public void run(){
                System.out.println("定义匿名类的方法:全部内容都在 test() 中的两个括号包裹");
                System.out.println("匿名内部类用完一次就没有了,下次再调用时就需要再定义一个新的匿名内部类!");
            }
        });
        // 匿名内部类的二次调用,需要重新定义匿名内部类。
        t.test(new A(){
            // 方法的重写(因为继承了接口 A,所以必须实现 run() 方法)
            @Override
            public void run(){
                System.out.println("定义匿名类的方法:全部内容都在 test() 中的两个括号包裹");
                System.out.println("匿名内部类用完一次就没有了,下次再调用时就需要再定义一个新的匿名内部类!");
            }
        });

    }
}

局部内部类

类定义在方法的内部,作用域只限于本方法,称为局部内部类。

代码示例:测试局部内部类

package cn.jungle.test.Class;
/**
 * 测试局部内部类
 */
public class TestLocalInnerClass {
    public void show(){
        // 局部内部类作用仅限于该方法
        class Inner3{
            public void fun(){
                System.out.println("hello,阿jun!");
            }
        }
        new Inner3().fun();
    }
    public static void main(String[] args) {
        new TestLocalInnerClass().show();  // hello,阿jun!
    }
}
posted @ 2021-11-24 23:24  阿jun  阅读(174)  评论(0编辑  收藏  举报