文章目录
13.字符串 String 类详解
String:就是把一堆字符串起来,统一使用。
- String 类又称作不可变字符序列。
- String 位于 java.lang 包中,Java 程序默认导入 java.lang 包下的所有类。
- java 字符串就是 Unicode 字符序列,例如字符串“Java”就是 4 个 Unicode 字符’J’、’a’、’v’、’a’组成的。
- Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是 String 类的一个实例。
String类的本质,JDK源码解读
Ctrl+鼠标左键 Alt+7
public class TestString {
public static void main(String[] args) {
String s0=null;
String s1="";
String s2="java";
String s3=new String("java");
String s4=new String(); //源码中:this.value = "".value; 初始化新创建的String对象,使其表示空字符序列。
System.out.println(s1.length());
System.out.println(s2.length());
// System.out.println(s0.length); //会报:空指针异常
System.out.println(s3);
System.out.println(s4);
}
}
String 类和常量池
【示例】字符串相等判断(以后一般判断字符串值是否相等,使用 equals())
String g1 = "北京尚学堂";
String g2 = "北京尚学堂";
String g3 = new String("北京尚学堂");
System.out.println(g1 == g2); // true
System.out.println(g1 == g3); // false
System.out.println(g2.toString()); // 北京尚学堂
System.out.println(g3.toString()); // 北京尚学堂
System.out.println(g1.equals(g3)); //true
toString内部源码:
public String toString() {
return this;
}
String类常用的方法
String类的常用方法列表
方法 | 解释说明 |
---|---|
char charAt(int index) | 返回字符串中第index个字符 |
boolean equals(String other) | 如果字符与other相等,返回true,否则,返回false |
boolean equalslgnoreCase(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) | 返回一个新字符串,该串包含从原始字符串behinIndex到串尾 |
String substring(int beginIndex,int endIndex) | 返回一个新字符串,该串包含从原始字符串beginIndex到串尾或endIndex-1的所有字符串 |
String toLowerCase() | 返回一个新字符串,该串将原始字符串中的所有大写字母改成小写字母 |
String to UpperCase() | 返回一个新字符串,该串将原始字符串中的所有小写字母变成大写字母 |
String trim() | 返回一个新字符串,该串删除了原始字符串头部和尾部的空格 |
代码测试:
package opp;
public class TestString1 {
public static void main(String[] args) {
String s1="core java";
String s2="Core java";
System.out.println(s1.charAt(3)); //提取下标为 3 的字符 e
System.out.println(s2.length()); //字符串的长度 9
System.out.println(s1.equals(s2)); //比较两个字符串是否相等 false
System.out.println(s1.equalsIgnoreCase(s2)); //比较两个字符串(忽略大小写) true
System.out.println(s1.indexOf("Java")); //字符串 s1 中是否包含 Java 否:-1
System.out.println(s1.indexOf("java")); //有:5
String s3="i love java,java is the best!";
System.out.println(s3.indexOf("java")); // 7
System.out.println(s3.lastIndexOf("java")); //12
// 从末尾开始查找第一个子字符串 str在字符串中的索引位置第一个子字符串 str 在字符串中的索引位置
String s=s1.replace(" ","&"); //将 s1 中的空格替换成&
System.out.println("result is:"+s); //result is:core&java
System.out.println(s1.length()); //字符串的长度 9
}
}
package opp;
import java.util.Locale;
public class TestString2 {
public static void main(String[] args) {
String s="";
String s1="How are you?";
System.out.println(s1.startsWith("How")); //是否以How开头 true
System.out.println(s1.endsWith("you")); //是否以you结尾 false
s=s1.substring(4); //提取子字符串:从下角标为4的开始到字符串结尾为止
System.out.println(s); //are you?
s=s1.substring(4,7); //提取子字符串:下标[4,7)不包括7
System.out.println(s); //are
s=s1.toLowerCase(); //转小写
System.out.println(s); //how are you?
s=s1.toUpperCase(); //转大写
System.out.println(s); //HOW ARE YOU?
String s2=" How old are you!!";
s=s2.trim(); //去除字符串首尾的空格。注意:中间的空格不能去除
System.out.println(s); //HOW ARE YOU?
System.out.println(s2); //因为String是不可变字符串,所以s2不变 // How old are you!!
}
}
14.内部类的分类
非静态内部类
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
-
非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
-
非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
-
非静态内部类不能有静态方法、静态属性和静态初始化块。
-
成员变量访问要点:
1.内部类属性:this.变量名。
2.外部类属性:外部类名.this.变量名。
3.创建的是一个没有名字的A 的实现类(只用一次,没名字没法用第二次)
内部类的访问:
1.外部类中定义内部类:new Inner()。
2.外部类以外的地方使用非静态内部类:
Outer.Inner varname = new Outer().new Inner()。
【示例】内部类的访问
package opp.innerClass;
//测试内部类的用法
public class Outer {
private int age=10;
public void show(){
System.out.println("Outer.show");
System.out.println(age);//10
}
/**内部类 Inner*/
public class Inner{
//内部类中可以声明与外部类同名的属性与方法
int age=20;
public void show(){
System.out.println("Inner.show");
System.out.println(age);//20
//10 访问外部类的普通属性
System.out.println(Outer.this.age);
Outer.this.show();
}
}
}
package opp.innerClass;
/**
* 测试非静态内部类
*/
public class TestInner {
public static void main(String[] args) {
Outer.Inner inner=new Outer().new Inner();
inner.show();
}
}
静态内部类
定义方式:
static class ClassName {
//类体
}
使用要点:
- 静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员。
- 静态内部类看做外部类的一个静态成员。
【示例】静态内部类的访问
package opp.innerClass;
/**
* 测试静态内部类
*/
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(); //对比非静态内部类 直接new
inner.test();
}
}
匿名内部类
没有名字
适合那种只需要使用一次的类。比如:键盘监听操作等等。在安卓开发、awt、swing开发中常见。
语法:
new 父类构造器(实参类表) \实现接口 () {
//匿名内部类类体!
}
【示例】匿名内部类的使用
package opp.innerClass;
/**
* 测试匿名内部类
*/
public class TestAnonymousInnerClass {
public void test1(A a){
a.run();
}
public static void main(String[] args) {
TestAnonymousInnerClass t=new TestAnonymousInnerClass();
// t.test1(new AImpl()); 非匿名内部类的做法
t.test1(new A() { //new的不是接口,创建的是一个没有名字的A的实现类
@Override //这个类只用一次,没有名字
public void run() {
System.out.println("第一个匿名内部类");
}
});
t.test1(new A() { //新的匿名内部类
@Override
public void run() {
System.out.println("第二个匿名内部类");
}
});
}
}
interface A{
void run();
}
//非匿名内部类的做法
//class AImpl implements A{
//
// @Override
// public void run() {
// System.out.println("AImpl.run");
// }
//}
注意:
- 匿名内部类没有访问修饰符。
- 匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。
局部内部类
定义在方法内部的,作用域只限于本方法,称为局部内部类。
局部内部类在实际开发中应用很少。
package opp.innerClass;
/**
* 测试局部内部类
*/
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();
}
}
//通过 new 外部类名
Outer2.Inner2 inner=new Outer2.Inner2(); //对比非静态内部类 直接new
inner.test();
}
}
### 匿名内部类
没有名字
适合那种只需要使用一次的类。比如:键盘监听操作等等。在安卓开发、awt、swing开发中常见。
**语法:**
```java
new 父类构造器(实参类表) \实现接口 () {
//匿名内部类类体!
}
【示例】匿名内部类的使用
package opp.innerClass;
/**
* 测试匿名内部类
*/
public class TestAnonymousInnerClass {
public void test1(A a){
a.run();
}
public static void main(String[] args) {
TestAnonymousInnerClass t=new TestAnonymousInnerClass();
// t.test1(new AImpl()); 非匿名内部类的做法
t.test1(new A() { //new的不是接口,创建的是一个没有名字的A的实现类
@Override //这个类只用一次,没有名字
public void run() {
System.out.println("第一个匿名内部类");
}
});
t.test1(new A() { //新的匿名内部类
@Override
public void run() {
System.out.println("第二个匿名内部类");
}
});
}
}
interface A{
void run();
}
//非匿名内部类的做法
//class AImpl implements A{
//
// @Override
// public void run() {
// System.out.println("AImpl.run");
// }
//}
注意:
- 匿名内部类没有访问修饰符。
- 匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。
局部内部类
定义在方法内部的,作用域只限于本方法,称为局部内部类。
局部内部类在实际开发中应用很少。
【示例】方法中的内部类
package opp.innerClass;
/**
* 测试局部内部类
*/
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();
}
}