面向对象(八)——String类和内部类

发布于:2024-12-07 ⋅ 阅读:(23) ⋅ 点赞:(0)

一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出来的和他们不一样

g1String 类型,因此调用的是 String 类的 equals 方法(比较两个字符串是否相等)。

Object 类的 equals 方法默认是比较对象的内存地址,也就是比较两个对象引用是否指向堆中的同一个对象实例

String a = "程序员";
String b = new String("程序员");

Java中,使用双引号创建的字符串字面量,会被存储在字符串常量池中。因此,String a = "程序员";这行代码中的a指向的是字符串常量池中的一个对象。而String b = new String("程序员");这行代码通过new关键字创建了一个新的String对象,这个对象位于堆内存中。因此,ab指向的是不同的对象。

字符串相等的判断

  • equals方法用来检测两个字符串内容是否相等。如果字符串s和t内容相等,则s.equals(t)返回true,否则返回false。
  • 要测试两个字符串除了大小写区别外是否是相等的,需要使用equalsIgnoreCase方法。
  • 判断字符串是否相等不要使用==

【示例】忽略大小写的字符串比较

"Hello".equalsIgnoreCase("hellO");//true

(*)阅读API文档

· 如何下载API文档

  1. 下载地址,点击进入:

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 非静态内部类

非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)

  1. 非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。

  2. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。

  3. 非静态内部类不能有静态方法、静态属性和静态初始化块。

  4. 成员变量访问要点:

    • 内部类属性: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  访问外部类的普通属性
    }
  }
}

内部类的访问:

  1. 外部类中定义内部类:new Inner()。

  2. 外部类以外的地方使用非静态内部类:

    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 {
//类体
}

使用要点:

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

【示例】静态内部类的访问

/*
测试静态内部类
 */

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();
   }
}

网站公告

今日签到

点亮在社区的每一天
去签到