一String类
1 字符串String类
String是最常用的类,要掌握String类常见的方法,它底层实现也需要掌握好,不然在工作开发中很容易犯错。
- String类又称作不可变字符序列。
- String位于java.lang包中,Java程序默认导入java.lang包下的所有类。
- Java字符串就是Unicode字符序列,例如字符串“Java”就是4个Unicode字符’J’、’a’、’v’、’a’组成的。
- Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是String类的一个实例。
【示例】String类的简单使用
String e = "" ; // 空字符串
String greeting = " Hello World ";
【示例】"+"连接符
int age = 18;
String str = "age is" + age; //str赋值为"age is 18"
//这种特性通常被用在输出语句中:
System.out.println("age is" + age);
2 String类和常量池
g1和g2是同一个对象,但g3是新new出来的和他们不一样
g1
是 String
类型,因此调用的是 String
类的 equals
方法(比较两个字符串是否相等)。
Object
类的 equals
方法默认是比较对象的内存地址,也就是比较两个对象引用是否指向堆中的同一个对象实例
String a = "程序员";
String b = new String("程序员");
Java中,使用双引号创建的字符串字面量,会被存储在字符串常量池中。因此,String a = "程序员";
这行代码中的a
指向的是字符串常量池中的一个对象。而String b = new String("程序员");
这行代码通过new
关键字创建了一个新的String
对象,这个对象位于堆内存中。因此,a
和b
指向的是不同的对象。
字符串相等的判断
- equals方法用来检测两个字符串内容是否相等。如果字符串s和t内容相等,则s.equals(t)返回true,否则返回false。
- 要测试两个字符串除了大小写区别外是否是相等的,需要使用equalsIgnoreCase方法。
- 判断字符串是否相等不要使用
==
。
【示例】忽略大小写的字符串比较
"Hello".equalsIgnoreCase("hellO");//true
(*)阅读API文档
· 如何下载API文档
- 下载地址,点击进入:
https://www.oracle.com/java/technologies/javase-jdk8-doc-downloads.html
· 查看API文档
下载成功后,解压下载的压缩文件,点击进入docs/api下的index.html文件即可。
· API文档如何阅读
String类常用的方法
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() | 返回一个新字符串,该串删除了原始字符串头部和尾部的空格。 |
【示例】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);
}
}
执行结果如图所示:
【示例】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不变
}
}
执行结果如图所示:
二 内部类
1 内部类的概念和用法
我们把一个类放在另一个类的内部定义,称为内部类(inner class)。
内部类的两个要点:
- 内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。
- 内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。但外部类不能访问内部类的内部属性。
注意
内部类只是一个编译时概念,一旦我们编译成功,就会成为完全不同的两个类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后会出现Outer.class和Outer$Inner.class两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类的相同。
【示例】内部类的定义和使用
/**外部类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
}
}
}
2 四种内部类
1 非静态内部类
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
非静态内部类不能有静态方法、静态属性和静态初始化块。
成员变量访问要点:
内部类属性:this.变量名。
外部类属性:外部类名.this.变量名。
【示例】内部类中访问成员变量
/**外部类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 访问外部类的普通属性
}
}
}
内部类的访问:
外部类中定义内部类:new Inner()。
外部类以外的地方使用非静态内部类:
Outer.Inner varname = new Outer().new Inner()。//要先创建外部类
【示例】内部类的访问
/**
* 测试非静态内部类
*/
public class TestInnerClass1 {
public static void main(String[ ] args) {
//先创建外部类实例,然后使用该外部类实例创建内部类实例
Outer1.Inner1 inner = new Outer1().new Inner1();
inner.show();
}
}
2 静态内部类
定义方式:
static class ClassName {
//类体
}
使用要点:
- 静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员。
- 静态内部类看做外部类的一个静态成员。
【示例】静态内部类的访问
/*
测试静态内部类
*/
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();
}
}
3 匿名内部类
适合那种只需要使用一次的类。比如:键盘监听操作等等。在安卓开发、awt、swing开发中常见。
没有名字,只在这一个地方用一次,别的地方就不用了
语法:
new 父类构造器(实参类表) \实现接口 () {
//匿名内部类类体!
}
【示例】匿名内部类的使用
/**
* 测试匿名内部类
*/
public class TestAnonymousInnerClass {
public void test1(A a) {
a.run();
}
public static void main(String[] args) {
TestAnonymousInnerClass tac = new TestAnonymousInnerClass();
tac.test1(new A() {//接口不能new,表示new了一个没有名字的实现类A,只用这么一次(自带重写)
@Override
public void run() {
System.out.println("匿名内部类测试! 我是新定义的第一个匿名内部类!");
}
});
tac.test1(new A() {
@Override
public void run() {
System.out.println("我是新定义的第二个匿名内部类");
}
});
}
}
//定义一个接口,以前要写一个类实现接口,然后new一个对象,调用方法。
//匿名内部类,就用一次,也没必要再声明一次
interface A {
void run();
}
- 匿名内部类没有访问修饰符。
- 匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。
4 局部内部类
定义在方法内部的,作用域只限于本方法,称为局部内部类。
局部内部类在实际开发中应用很少。
【示例】方法中的内部类
/**
* 测试局部内部类
*/
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();
}
}