⭐ 字符串 String 类详解
String 是最常用的类,要掌握 String 类常见的方法,它底层实现也需要掌握好,不然在工作开发中很容易犯错。
🐟 String 类又称作不可变字符序列。
🐟 String 位于 java.lang 包中,Java 程序默认导入 java.lang 包下的所有类。
🐟 Java 字符串就是 Unicode 字符序列,例如字符串“Java”就是 4 个 Unicode 字符’J’、’a’、’v’、’a’组成的。
🐟 Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是 String 类的一个实例。
【eg】String 类的简单使用
String e = "" ; // 空字符串
String greeting = " Hello World ";
【eg】"+"连接符
int age = 18;
String str = "age is" + age; //str 赋值为"age is 18"
//这种特性通常被用在输出语句中:
System.out.println("age is" + age);
String 类和常量池
Java 内存分析中,我们会经常听到关于“常量池”的描述,实际上常量池也分了以下三种:全局字符串常量池、class 文件常量池、运行时常量池(Runtime Constant Pool)。
我们只关注运行时常量池即可。
【eg】字符串相等判断(以后一般判断字符串值是否相等,使用 equals())
String g1 = "北京";
String g2 = "北京";
String g3 = new String("北京");
System.out.println(g1 == g2); // true
System.out.println(g1 == g3); // false
System.out.println(g1.equals(g3)); //true
⭐ 阅读 API 文档
🐟 如何下载 API 文档
下载地址,点击进入:
https://www.oracle.com/java/technologies/javase-jdk8-doc-downloads.html
🐟 查看 API 文档
下载成功后,解压下载的压缩文件,点击进入 docs/api 下的 index.html 文件即可。
🐟 API 文档如何阅读
⭐ String 类常用的方法
String 类是我们最常使用的类。以下是常用的方法。
方法 | 解释说明 |
---|---|
char charAt(int index) | 返回字符串中第 index 个字符 |
boolean equals(String other) | 如果字符串与 other 相等,返回 true;否则,返回 false。 |
boolean equalsIgnoreCase(String other) | 如果字符串与 other 相等(忽略大小写),则返回 true;否则,返回 false。 |
int indexOf(String str) | 返回从头开始查找第一个子字符串 str 在字符串中的索引位置。如果未找到子字符串 str,则返回-1。 |
lastIndexOf() | 返回从末尾开始查找第一个子字符串 str 在字符串中的索引位置。如果未找到子字符串 str,则返回-1。 |
int length() | 返回字符串的长度。 |
String replace(char oldChar,char newChar) | 返回一个新串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 而生成的。 |
boolean startsWith(String prefix) | 如果字符串以 prefix 开始,则返回 true。 |
boolean endsWith(String prefix) | 如果字符串以 prefix 结尾,则返回 true。 |
String substring(int beginIndex) | 返回一个新字符串,该串包含从原始字符串 beginIndex 到串尾。 |
String substring(int beginIndex,int endIndex) | 返回一个新字符串,该串包含从原始字符串 beginIndex 到串尾或 endIndex-1 的所有字符。 |
String toLowerCase() | 返回一个新字符串,该串将原始字符串中的所有大写字母改成小写字母。 |
String toUpperCase() | 返回一个新字符串,该串将原始字符串中的所有小写字母改成大写字母。 |
String trim() | 返回一个新字符串,该串删除了原始字符串头部和尾部的空格。 |
【eg】String 类常用方法一
public class StringTest1 {
public static void main(String[ ] args) {
String s1 = "core Java";
String s2 = "Core Java";
System.out.println(s1.charAt(3));//提取下标为 3 的字符
System.out.println(s2.length());//字符串的长度
System.out.println(s1.equals(s2));//比较两个字符串是否相等
System.out.println(s1.equalsIgnoreCase(s2));//比较两个字符串(忽略大小写)
System.out.println(s1.indexOf("Java"));//字符串 s1 中是否包含 Java
System.out.println(s1.indexOf("apple"));//字符串 s1 中是否包含 apple
String s = s1.replace(' ', '&');//将 s1 中的空格替换成&
System.out.println("result is :" + s);
}
}
执行结果如下所示:
【eg】String 类常用方法二
public class StringTest2 {
public static void main(String[ ] args) {
String s = "";
String s1 = "How are you?";
System.out.println(s1.startsWith("How"));//是否以 How 开头
System.out.println(s1.endsWith("you"));//是否以 you 结尾
s = s1.substring(4);//提取子字符串:从下标为 4 的开始到字符串结尾为止
System.out.println(s);
s = s1.substring(4, 7);//提取子字符串:下标[4, 7) 不包括 7
System.out.println(s);
s = s1.toLowerCase();//转小写
System.out.println(s);
s = s1.toUpperCase();//转大写
System.out.println(s);
String s2 = " How old are you!! ";
s = s2.trim();//去除字符串首尾的空格。注意:中间的空格不能去除
System.out.println(s);
System.out.println(s2);//因为 String 是不可变字符串,所以 s2 不变
}
}
执行结果如下所示:
⭐ 字符串相等的判断
🐟 equals 方法用来检测两个字符串内容是否相等。如果字符串 s 和 t 内容相等,则s.equals(t)返回 true,否则返回 false。
🐟 要测试两个字符串除了大小写区别外是否是相等的,需要使用 equalsIgnoreCase方法。
🐟 判断字符串是否相等不要使用"=="。
【eg】忽略大小写的字符串比较
"Hello".equalsIgnoreCase("hellO");//true
【eg】字符串的比较:"= ="与 equals()方法
public static void main(String[ ] args) {
String g1 = "北京";
String g2 = "北京";
String g3 = new String("北京");
System.out.println(g1 == g2); // true 指向同样的字符串常量对象
System.out.println(g1 == g3); // false g3 是新创建的对象
System.out.println(g1.equals(g3)); // true g1 和 g3 里面的字符串内容是一样的
}
}
执行结果如下所示:
⭐ 内部类
我们把一个类放在另一个类的内部定义,称为内部类(inner class)。
内部类的两个要点:
⭐ 内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。
⭐ 内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。但外部类不能访问内部类的内部属性。
注意
内部类只是一个编译时概念,一旦我们编译成功,就会成为完全不同的两个类。对于一个名为 Outer 的外部类和其内部定义的名为 Inner 的内部类。编译完成后会出现 Outer.class和 Outer$Inner.class 两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类的相同。
【eg】内部类的定义和使用
/**外部类 Outer*/
class Outer {
private int age = 10;
public void show(){
System.out.println(age);//10
}
/**内部类 Inner*/
public class Inner {
//内部类中可以声明与外部类同名的属性与方法
private int age = 20;
public void show(){
System.out.println(age);//20
}
}
}
编译后会产生两个不同的字节码文件,如图所示:
内部类的分类
非静态内部类
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
🐟 非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
🐟 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类
成员。
🐟 非静态内部类不能有静态方法、静态属性和静态初始化块。
🐟 成员变量访问要点:
⭐ 内部类属性:this.变量名。
⭐ 外部类属性:外部类名.this.变量名。
【eg】内部类中访问成员变量
/**外部类 Outer1*/
class Outer1 {
private int age = 10;
public void show(){
System.out.println(age);//10
}
/**内部类 Inner*/
public class Inner1 {
//内部类中可以声明与外部类同名的属性与方法
private int age = 20;
public void show(){
System.out.println(age);//20
System.out.println(Outer1.this.age); //10 访问外部类的普通属性
}
}
}
静态内部类
定义方式:
static class ClassName {
//类体
}
使用要点:
⭐ 静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员。
⭐ 静态内部类看做外部类的一个静态成员。
【eg】静态内部类的访问
/*
测试静态内部类
*/
class Outer2{
private int a = 10;
private static int b = 20;
//相当于外部类的一个静态成员
static class Inner2{
public void test(){
// System.out.println(a); //静态内部类不能访问外部类的普通属性
System.out.println(b); //静态内部类可以访问外部类的静态属性
}
}
}
public class TestStaticInnerClass {
public static void main(String[ ] args) {
//通过 new 外部类名.内部类名() 来创建内部类对象
Outer2.Inner2 inner =new Outer2.Inner2();
inner.test();
}
}
匿名内部类
适合那种只需要使用一次的类。比如:键盘监听操作等等。在安卓开发、awt、swing开发中常见。
语法:
new 父类构造器(实参类表) \实现接口 () {
//匿名内部类类体!
}
【eg】匿名内部类的使用
/**
* 测试匿名内部类
*/
public class TestAnonymousInnerClass {
public void test1(A a) {
a.run();
}
public static void main(String[] args) {
TestAnonymousInnerClass tac = new
TestAnonymousInnerClass();
tac.test1(new A() {
@Override
public void run() {
System.out.println("匿名内部类测试! 我是新定义的第一个匿名内部类!");
}
});
tac.test1(new A() {
@Override
public void run() {
System.out.println("我是新定义的第二个匿名内部类");
}
});
}
}
interface A {
void run();
}
注意
⭐ 匿名内部类没有访问修饰符。
⭐ 匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。
局部内部类
定义在方法内部的,作用域只限于本方法,称为局部内部类。
局部内部类在实际开发中应用很少。
【eg】方法中的内部类
/**
* 测试局部内部类
*/
public class TestLocalInnerClass {
public void show() {
//作用域仅限于该方法
class Inner3 {
public void fun() {
System.out.println("helloworld");
}
}
new Inner3().fun();
}
public static void main(String[ ] args) {
new TestLocalInnerClass().show();
}
}