内部类与常用类

内部类

  • 在类中再定义一个类。
    演示的代码如下:

    class OuterClass{		// 外部类
        // 属性
        // 方法
        // 构造方法
        class InnerClass{  // 内部类
            
        }
    }
    

    内部类也会生成独立的.class文件命名方式为外部类$内部类.class。

1 成员内部类

1.1定义方式
  • 定义位置:类以内方法以外。
    演示的代码如下:

    class OuterClass{							// 外部类
        class InnerClass{						// 成员内部类
            
        }
    }
    
1.2 创建成员内部类对象
  • 成员内部类对象必须依赖外部类对象,先创建外部类对象再创建成员内部类对象。
    演示的代码如下:
package com.txw.test;

public class TestMemberClass {
    public static void main(String[] args) {
        OuterClass oc = new OuterClass();		// 创建外部类对象
        OuterClass.InnerClass ic = oc.new InnerClass();		// 创建内部类对象
    }
}
// 外部类
class OuterClass{
	// 成员内部类
    class InnerClass{

    }
}

2 静态内部类

2.1 定义方式
  • 定义位置:类以内方法以外。
    演示的代码如下:
    class OuterClass{		// 外部类
        
        static class InnerClass{	// 静态内部类
            
        }
        
    }
    
2.2 创建静态内部类对象
  • 创建静态内部类对象不依赖外部类对象。
    演示的代码如下:
package com.txw.test;;

public class TestStaticClass {
    public static void main(String[] args) {
        // 创建静态内部类对象
        OuterClass.InnerClass oi = new OuterClass.InnerClass();
    }
}
class OuterClass{		// 外部类

    static class InnerClass{		// 静态内部类

    }
}

3 局部内部类

3.1 定义方式
  • 定义位置:方法以内。
    演示的代码如下:

    class OuterClass{		// 外部类
        public void method(){        
            class InnerClass{ // 局部内部类
                
            }        
        }
    }
    
3.2 创建局部内部类对象
  • 局部内部类对象只能在当前方法中使用。
    演示的代码如下:
package com.txw.test;;

public class TestLocalClass {
    public static void main(String[] args) {

    }
}
class OuterClass{ // 外部类
    public void method(){

        class InnerClass{ // 局部内部类
        }
        InnerClass ic = new InnerClass();
    }
}

4 匿名内部类

4.1 定义方式
  • 定义位置:与局部一致,需要定义在方法中。
    演示的代码如下:
    class Super{}
    class Sub extends Super{}
    
    class OuterClass{
     	public void method(){
    		// 匿名内部类必须以子类的形式出现      
            Super sup = new Super(){
                // 匿名内部类,属于Super的子类
                
            };
        }   
    }
    
4.2 创建匿名内部类对象
  • 匿名内部类对象必须作为子类出现只有{}表示,创建对象与定义类同时执行。
    演示的代码如下:
    interface IA{
        public void m1();
    }
    
    class OuterClass{
        public void method(){
            IA a;
            a = new IA(){
                // 匿名内部类
            }
        }
    }
    
    匿名内部类是学习Lamdba表达式与流式编程的重要前提。
    演示的代码如下:
package com.txw.test;

public class TestAnonymityClass {
    public static void main(String[] args) {
        new OuterClass().method();
    }
}
class OuterClass{

    public void method(){

        MyInterface mi;
        mi = new MyInterface(){
            public void m1(int n){
                System.out.println(n);
            }
        };

        MyInterface mi2;
        mi2 = System.err::print; // Lambda表达式
        mi2.m1(1200);
        // method2(mi);
    }
    public void method2(MyInterface mi){

    }
}
interface MyInterface {
    public void m1(int n);
}

API(Application Programming Interface)

  • 用户编程接口。

Object类(对象)

  • Java是一门纯面向对象的语言。
    万物皆对象,万物 is a Object
    
  • 特点:
    1. Object类是所有类的父类,所有类默认继承Object
    2. Object类型的引用可以存储任何对象,Object作为参数可以接收任何类型的数据,作为返回值可以返回任何类型的数据
    3. Object是所有类的父类,Object中定义的方法是所有类都具备的方法
    

常用方法

1 getClass()
  • 作用:返回引用中存储的对象类型,通常用于类型判断。
    演示的代码如下:
    class Animal{}
    class Dog extends Animal{}
    
    // 判断b引用中存储的对象是否为Animal类型
    // 只获取Animal类型的对象
    System.out.println(b instanceof Animal);		// true instanceof具有多态性
    // 使用getClass()进行判断
    System.out.println( a.getClass() );
    System.out.println( b.getClass() );
    // 类型一致返回true
    System.out.println(a.getClass() == b.getClass());	// false 两种类型不一致
    
    演示的代码如下:
package com.txw.test;

public class TestObject {
    public static void main(String[] args) {
       Animal a = new Animal();
       Animal b = new Dog();
        // 判断b引用中存储的对象是否为Animal类型
        // 只获取Animal类型的对象
        System.out.println(b instanceof Animal);
        // 使用getClass()进行判断
        System.out.println( a.getClass() );
        System.out.println( b.getClass() );
        // 类型一致返回true
        System.out.println(a.getClass() == b.getClass());
    }
}
// class Worker extends Object{}
// class Worker{}
// class Student{}
class Animal{}
class Dog extends Animal{}
2 toString()
  • 作用:将对象转换为一个可读性较强的字符串并返回Object类中的默认实现:类名+@+十六进制的hash编码。
    缺点:可读性差,无法表达对象的特点。
  • 当父类的方法不再适用于子类时,覆盖toString方法。
    演示的代码如下:
    class Student{
        String name;
        int age;
        double score;
    
        public Student(String name, int age, double score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
    
        @Override  // 可以检查注解下的方法是否满足覆盖的语法要求
        public String toString(){
            return "Student[ name = "+name+" , age = "+age+" , score ="+score+" ] ";
        }
    }
    
    注意:当使用System.out.println打印语句输出对象时,会自动调用对象中的toString方法打印该方法的返回值。
    演示的代码如下:
package com.txw.test;;

public class TestToString {
    public static void main(String[] args) {
        Student stu1 = new Student("阿森",18,3D);
        Student stu2 = new Student("wangyx",16,100D);
        System.out.println( stu1.toString() );
        // 如果直接打印对象 自动调用对象中的toString方法打印返回值
        System.out.println( stu2 );
    }
}
class Student{
    String name;
    int age;
    double score;

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    
    @Override  // 可以检查注解下的方法是否满足覆盖的语法要求
    public String toString(){
        return "Student[ name = "+name+" , age = "+age+" , score ="+score+" ] ";
    }
}

写好一个类时添加toString方法是一种编程习惯。

3 equals()
  • 作用:判断两个对象中的内容是否相同。
    使用 == 判断只能判断对象的地址是否相同,而地址不同属性相同也应该视为相同的对象。
    所以在引用类型的判断中使用 == 是不准确的。
    演示的代码如下:
    // 内容(属性的值)一样则会视为相同的对象
    Student stu1 = new Student("阿森",18,3D);
    Student stu2 = new Student("阿森",18,3D);
    System.out.println( stu1 == stu2 ); 		// 判断引用类型中的地址是否一致
    
  • Object中的equals方法默认实现与 == 判断一致,依然是根据地址判断两个对象是否相同。
    public boolean equals(Object obj) {
        return (this == obj);
    }
    
  • 父类的equals不再适用于子类,无法对属性进行判断无法区分对象是否重复。
    覆盖父类的equals方法。
    演示的代码如下:
    class Student{
        String name;
        int age;
        double score;
    
        @Override
        public boolean equals(Object obj) {
            // 如果地址相同,对象内容一定相同
            if(this==obj)return true;
            // 如果传入的obj为null直接返回false因为没有可比较的对象
            if(obj==null) return false;
            // 验证两个对象的类型是否一致
            if(getClass() != obj.getClass() ) return false;
            // 验证两个对象的属性值是否一致
            Student other = (Student)obj;		// 向下转型
            if(age == other.age && score == other.score && name.equals(other.name) )
                return true;
    
            return false;
        }
    
    equals方法作为验证对象是否相同的重要方法,为类添加equals方法是一种编程习惯。
    演示的代码如下:
package com.txw.test;;

import java.util.Scanner;
public class TestEquals {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String input = sc.next();
        // String str = "ABC";
        // System.out.println("input = " + input);
        System.out.println( input == "ABC" );
        System.out.println( input.equals("ABC") );
        // 内容(属性的值)一样则会视为相同的对象
        Student stu1 = new Student("阿森",18,3D);
        Student stu2 = new Student("阿森",18,3D);
        Student stu3 = stu2;
        /*Teacher t1 = null;
        System.out.println( stu1 == stu2 ); // 判断引用类型中的地址是否一致
        System.out.println( stu1.equals(stu2) );
        System.out.println( stu1.equals(t1) );
*/
        System.out.println(stu2);
        System.out.println(stu3);
        System.out.println( stu2 == stu3 );
    }
}
class Teacher{}
class Student{
    String name;
    int age;
    double score;

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    // stu1.equals( stu2 );
    // this = stu1
    // obj = stu2
    // this == obj  stu1 == stu2
   /* @Override
    public boolean equals(Object obj) {
        // 如果地址相同,对象内容一定相同
        if(this==obj)return true;
        // 如果传入的obj为null直接返回false因为没有可比较的对象
        if(obj==null) return false;
        // 验证两个对象的类型是否一致
        if(getClass() != obj.getClass() ) return false;
        // 验证两个对象的属性值是否一致
        Student other = (Student)obj;	// 向下转型
        if(age == other.age && score == other.score && name.equals(other.name) )
            return true;

        return false;
    }*/

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Double.compare(student.score, score) == 0 && name.equals(student.name);
    }
    /* @Override  // 可以检查注解下的方法是否满足覆盖的语法要求
    public String toString(){
        return "Student[ name = "+name+" , age = "+age+" , score ="+score+" ] ";
    }*/

  /*  @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }*/
}
4 finalize()
  • 作用:JVM垃圾回收器(GC)回收对象释放内存前调用finalze()方法。
    Java官方并不推荐程序员覆盖此方法以改变原有的垃圾回收策略。
    垃圾对象:零引用对象
    演示的代码如下:
    Student stu = new Student();
    stu = null;
    
    JVM会适时回收没有引用指向的对象。

习题

  1. (内部类)Java 中内部类包括(ABCD)
    A. 成员内部类。
    B. 静态内部类。
    C. 局部内部类。
    D. 匿名内部类。
    E. 公开内部类 。
    F. 抽象内部类 。
  2. (内部类)关于 Java 中的内部说法正确的是(ABC)。
    A. 成员内部类中可以访问外部类的所有属性或是方法 。
    B. 静态内部类中可以访问外部类的所有的属性或是方法 。
    C. 局部内部类只能在当前类中创建对象 。
    D. 局部内部类可以访问所在方法中的常亮 。
    原因:局部内部类创建对象只能在当前方法中。
  3. (内部类)仔细阅读以下代码,下面哪些选项放在 //1 处可以编译通过(ABD)
    在这里插入图片描述

A. System.out.println(value1);
B. System.out.println(value2);
C. System.out.println(value3);
D. System.out.println(value4);
原因:
I. 局部内部类可以访问外部类的属性(A)以及静态属性(B)。
II. 局部内部类可以访问局部变量,但是要求局部变量必须是 final 的。
III. C 和 D 选项都是局部变量,但是 C 错误,因为 value3 没有被声明为final的。
4. (内部类)编程:已知 Light 接口如下,根据下面要求完成代码。
在这里插入图片描述
把 TestLamp 类补充完整,要求:
(1) 在//1 处使用局部内部类技术,调用 lamp 的 on 方法要求输出”shine in red”
(2) 在//2 处使用匿名内部类技术,调用 lamp 的 on 方法要求输出”shine in yellow”。
答:
代码如下:

package com.txw.test;

interface Light{
    void shine();
}

class Lamp{
    public void on (Light light){
        light.shine();
    }
}
class RedLight implements Light{
    @Override
    public void shine() {
        System.out.println("“shine in red");
    }
}
class YellowLight implements Light{
    @Override
    public void shine() {
        System.out.println("shine in yellow");
    }
}
public class TestLamp{

    public static void main(String[] args) {
        Lamp lamp = new Lamp();
        lamp.on(new RedLight());
        lamp.on(new YellowLight());
    }
}
  1. (Object 类)仔细阅读以下代码,写出程序运行的结果。
    在这里插入图片描述
    在这里插入图片描述
    答:输出结果:null 0 Tom 18
    打印一个对象,相当于打印该对象的字符串表现形式,即:toString 方 法返回值。 Student 类覆盖了toString 方法,返回 Student 类的name和age属性。由于stu1对象的name属性和age属性没有被初始化, 因此其值为默认值。
  2. (Object 类)仔细阅读以下代码,写出程序运行的结果;并简述 == 和 equals 的区别。
    在这里插入图片描述
    答: 输出结果:true、false
    第一个比较使用 equals,比较的是对象的值。
    第二个比较使用==,比较的是对象的地址。
  3. (Object 类)仔细阅读以下代码,写出程序运行的结果。
    在这里插入图片描述
    答:输出结果:true、false
    第一个比较,判断的是 a1 引用所指向的对象,是否是 Animal 类型或 者其子类。由于 a1 指向的对象是Dog 类 型,是 Animal 类型的子类, 因此比较结果为 true 。
    第二个比较,比较的是 a1 所指向的对象的实 际类型,和 a2 所指向对象的实际类型是否相同。由于 a1 所指向的对 象为 Dog 类型,而 a2 所指向的对象为 Animal 类型,因此这个比较 返回值为 false。
  4. (Object 类)仔细阅读以下代码,//1 处填入哪些代码可以编译通过(ABC)。
    在这里插入图片描述

A. stu1 + “ ” + 100
B. 100 + “ ” + stu1
C. “ ” + 100 + stu1
D. stu1 + 100 + “ ”
原因:
I. 当一个对象与一个字符串相加时,会自动调用对象的 toString 方法, 从而把该对象转化为字符串,再进 行字符串的连接。
II. A/B/C 三个选项,最终都会成为“字符串+对象”的形式,因此编译 都能通过。
III. D 选项错误,因为 stu+100 做的是对象和一个整数的加法,这种 运算没有定义,因此编译不通过。
9. (Object 类)在 Object 类中,定义的 finalize 方法在被垃圾回收时调用;toString 方法返回值表示对象的字符串 表现形式; equals 方法的作用 为判断两个对象值是否相同; getClass 方法作用为获得对象的实际类型。
10. (Object 类)编程:定义一个用户类(User 类),属性有用户名、用户密码 password、电话(tel), 要求如下:
(1) 对类进行封装,提供 get/set 方法;同时提供无参数、有参数的构造方法。
(2) 覆盖 toString 方法,要求格式为: username:一如既往,password:123456,tel:13051800681。
(3) 覆盖 equals 方法,要求:只要用户名相同则为相同对象 (4) 写一个测试类,利用键盘分别输入两个用户信息并存储 Use 对象中,判断两个对象是否相同。
演示的代码如下:

package com.txw.test;

import java.util.Scanner;
public class TestLamp{
    public static void main(String[] args) { 
        User[] users = new User[2]; int index = 0; 
        Scanner sc = new Scanner(System.in); 
        for (int i = 1; i <= 2; i++) { 
            System.out.println("请输入用户名:");
            String username = sc.next(); 
            System.out.println("请输入密码: "); 
            String password = sc.next();
            System.out.println("请输入手机号:");
            String tel = sc.next();
            User u = new User(username, password, tel); 
            users[index] = u; 
            index++; 
        }
        System.out.println(users[0].equals(users[1])); } 
}
// 用户类 
class User { 
    // 属性私有提供set/get方法 
    private String username;
    private String password;
    private String tel;
    
    public String getUsername() { 
        return username; 
    }
    
    public void setUsername(String username) { 
        this.username = username; 
    }
    
    public String getPassword() {
        return password; 
    }
    
    public void setPassword(String password) {
        this.password = password; 
    }
    
    public String getTel() { 
        return tel;
    }
    
    public void setTel(String tel) {
        this.tel = tel;
    }
    
    public User() { 
        
    }
    
    public User(String username, String password, String tel) { 
        this.username = username; 
        this.password = password;
        this.tel = tel; 
    }
    
    //覆盖toString()
    @Override 
    public String toString() { 
        return "username: " + username + ", password:" + password + ", tel:" + tel; 
    }
    
    // 覆盖equals(),要求只要用户名相同则表示同一个对象 
    @Override 
    public boolean equals(Object obj) { 
        if (this == obj) 
            return true;
        if (obj == null) 
            return false;
        if (getClass() != obj.getClass())
            return false; 
        User other = (User) obj;
        //只判断有户名 
        if (this.username.equals(other.username)) {
            return true;
        } else { 
            return false;
        }
    }
}
  1. (包装类)以下包装类的类名正确的是(ABDEFH) 。
    A. Byte
    B. Short
    C. Int
    D. Long
    E. Float
    F. Double
    G. Char
    H. Boolean
  2. (包装类)下面关于数据类型之间的转换正确的是(ABD) 。
    A. Integer i = 5 ;
    B. int a = new Integer(12);
    C. Integer i2 = 20 + “”;
    D. String s = true+””;
    原因:Intege - int之间能够自动拆箱/装箱。
    C错误,因为20+“ ”最终结果是个字符串,字符串无法自动转成Integer。
  3. (包装类)仔细阅读以下代码,写出程序运行打印输出的结果;并解释每个结果的原因。 在这里插入图片描述
    答: true false false
    第一个为true是因为两个Intger对象都自动拆箱为int类型,int类型用 == 比较,比较的是具体的数值,都是128。 剩下两个都为false,是因为每个对象都是通过new关键字创建的,== 比较地址所以为false。
  4. (String 类)仔细阅读以下代码段: String s = “hello”; String t=“hello”; char[] c = {‘h’,‘e’,‘l’,‘l’,‘o’}; 下列选项输出结果为 false 的语句是(B)。
    A. System.out.println( s.euqals( t ) );
    B. System.out.println( t.equals( c ) );
    C. System.out.println( s==t );
    D. System.out.println( t.equals( new String© ) );
    E. System.out.println( t.equals( new String(“hello”)) );
  5. (String 类)关于 java.lang.String 类,以下描述正确的一项是(A)。
    A. String 类是 final 类故不可以继承。
    B. String 类是 final 类故可以继承。
    C. String 类不是 final 类故不可以继承。
    D. String 类不是 final 类故可以继承。
  6. (String 类)应用程序的 main 方法中有以下语句,则输出的结果是(A)。 在这里插入图片描述
    A. false
    B. true
    C. 1
    D. 0
  7. (String 类)已知 String 对象 s=”abcdefg”,则 s.substring(2,5)的返回值为( B)。
    A.”bcde”
    B.”cde”
    C.”cdef”
    D.”def”
    原因:截取方法包括开始的数值,不包括结束的数值。
  8. (String 类)已知 s 为一个 String 对象,s=”abcdefg”,则 s.charAt(1)的返回值为(B)。
    A.a
    B.b
    C.f
    D.g
    原因:根据下标获取字符。
  9. (String 类)仔细阅读以下代码,关于程序描述正确的是(B)。
    在这里插入图片描述
    A、编译错误,String 类没有 replace 方法。
    B、运行后输出的结果是 abcde
    C、运行后输出的结果是 abxde
    D、编译成功,运行时抛出异常,提示 String 类的内容是不可变的。
    原因:使用替换方法,替换后得到的字符串并没有接收,而是打印原有字符串, 所以内容不变。
  10. (String 类)仔细阅读以下代码,执行后的结果是(C )。
    在这里插入图片描述
    A. aceg
    B. abc
    C. bdf
    D. abcdefg
    原因:打印字符循环下标从1开始,每次i+2,打印的下标依次是1,3,5。
  11. (String 类)请解释 Sting 和 StingBuilder 操作字符串时的区别。
    答: String一旦创建内容和长度不可变。
    StringBuilder内容和长度可变。
  12. (String 类)编程:任意输入一个字符串,统计字符串中字母的个数。
    演示的代码如下:
package com.txw.test;

public class Test{
   public static void main(String[] args) {
       String s = "123baizhi,.BAIZHI";
       int count = 0;
       // 统计字符串中字母的个数 
       for (int i = 0; i < s.length(); i++) {
           // 循环得到字符串中每一个字符
           char ch = s.charAt(i);
           // 如果当前字符在a~z或者A~Z之间统计变量++ 
           if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
               count++;
           }
       }
       // 循环结束字母个数统计完毕 
       System.out.println(count);
   }
}
  1. (String 类)编程:给定一个邮箱“zhangmj@zparkhr.com”,根据下面要求完成程序代码:
    (1) 获取邮箱中的用户名:zhangmj。
    (2) 验证邮箱“zhangmj@zparkhr.com”是否是一个合法的邮箱格式。 提示:① 邮箱必须包含“@”和“ . ” ② 最后一个“ . ”的位置必须大于“@”的位置。
    演示的代码如下:
package com.txw.test;

public class Test{
    public static void main(String[] args) {
        String email = "zhengcg@zparkhr.com"; 
        String userName = email.substring(0, email.indexOf('@'));
        if(email.indexOf('@') != -1 && email.lastIndexOf('.') != -1){ 
            if(email.indexOf('@') < email.lastIndexOf('.')){ 
                System.out.println("邮箱合法");
            }
        }
    }
}
  1. (String 类)编程:编写一个方法,功能是实现判断某字符串数组中是否有重复元素。 请自行拟定合适的方法名称,实现方法自行选择,可实现要求即可; 例如:public boolean 方法名(String[] strArray){…}。
    演示的代码如下:
package com.txw.test;

public class Test {
    public static void main(String[] args) {
        String[] str = { "hello", "hello", "world", "java", "android" };
        System.out.println(check(str));
    }
    // 判断字符串中是否包含重复元素 、
    public static boolean check(String[] strArray) { 
 /*定义一个标记值,如果有重复flag设置为true。
 使用选择排序的思想,拿固定值和之后的每一个值作比较equals,
 如果遇到内容相同的flag设置为true。 
 最终判断flag的值,false表示无重复,true表示有重复。
 */
        boolean flag = false;
        m:for (int i = 0; i < strArray.length; i++) {
            for (int j = i+1; j < strArray.length; j++) {
                if (strArray[i].equals(strArray[j])) {
                    flag = true;
                    break m;
                }
            }
        }
        return flag;
    }
}
  1. (String 类)编程:在给定的字符串“ABCDEFGhijklmn1234567”中获取随机的 4 个字符,并使用 StringBuilder 拼接成字符串。(随机获取到的 4 个字符中可以出现重复字符) 提示:创建随机数对象 java.util.Random。 java.util.Random random = new java.util.Random(); random.nextInt(100); //可以获取到 0~99 中任意一个随机数 。
    演示的代码如下:
package com.txw.test;

import java.util.Random;
public class Test {
   public static void main(String[] args) {
       String str = "ABCDEFGhijklmn1234567"; 
       Random random = new java.util.Random(); 
       StringBuilder sb = new StringBuilder(); 
       //随机获取字符串中四个字符,使用StringBuilder拼接 
       for (int i = 0; i < 4; i++) { 
           int index = random.nextInt(str.length()); 
           char ch = str.charAt(index); 
           sb.append(ch); 
       }
       System.out.println(sb);
   }
}
  1. (String 类)编程:将给定的字符串进行反转,并打印输出反转之后的字符串。 例如:给定的字符串为 “hello” 反转的字符串为 “olleh” 。
    演示的代码如下:
package com.txw.test;

public class Test {
    public static void main(String[] args) {
        // 字符串反转打印反转之后的内容 
        String s = "hello"; 
        StringBuilder sb = new StringBuilder(s);
        System.out.println(sb.reverse());
    }
}
  1. (String 类)编程:给定一个由数字组成的字符串,如:“1239586838923173478943890234092”;统 计出每个数字出现的次数。
    演示的代码如下:
package com.txw.test;

public class Test {
    public static void main(String[] args) {
        // 统计字符串中每个数字出现的次数
        // 方式1: 
        String str = "1239586838923173478943890234092";
        // 数组长度为10,第一个空间记录的是0字符出现的次数,以此类推
        int[] c = new int[10];
        // 循环得到字符串中每一个字符
        for(int i = 0 ; i < str.length(); i++){
            char ch = str.charAt(i);
            // 0字符对应的int值是48,1对应49以此类推 。
            // 当前字符-48的值可以作为下标对应空间进行++。
            int a = ch-48;
            c[a]++;
        }
        for(int i : c){
            System.out.println(i);
        }
        // 方式2: 
        // 循环,i从48开始到56结束,使用i变量表示字符0~9对应的整数。
        for(int i = 48; i <=56; i++){
            System.out.println(i - 48 + "出现:");
            // 第一次内层循环判断字符0有几个,第二次判断字符1有几个。
            int count = 0;
            for(int j = 0; j<str.length() ;j++){
                if(i == str.charAt(j) ){
                    count++;
                }
            }
            System.out.println(count+"次");
        }
    }
}

总结

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Java中的单例模式是一种设计模式它确保一个只有一个实例,并提供一个全局访问点访问该实例。静态内部类是一种常用的实现单例模式的方式。 在使用静态内部类实现单例模式时,我们将单例的构造方法私有化,以防止外部直接创建实例。然后,我们在单例定义一个静态内部类,该内部类持有一个单例实例,并在静态代码块中初始化该实例。通过静态内部类的方式,我们可以保证在需要使用单例实例时才会创建它,而且只会创建一次。 以下是使用静态内部类实现单例模式的示例代码: ```java public class Singleton { private Singleton() { // 私有化构造方法 } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } ``` 在上面的代码中,Singleton的构造方法被私有化,确保外部无法直接创建实例。SingletonHolder是一个静态内部类,它持有一个Singleton实例,并在静态代码块中初始化该实例。getInstance()方法返回SingletonHolder中的实例,保证了单例的唯一性。 使用静态内部类实现单例模式的优点是延迟加载和线程安全。由于静态内部类的特性,只有在第一次调用getInstance()方法时才会加载SingletonHolder,从而创建单例实例。同时,由于加载是线程安全的,所以静态内部类实现的单例模式也是线程安全的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学无止路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值