04-API

API

概述
  • 全称叫Application Programming Interface, 应用程序编程接口, 其实就是JDK提供的具有各种功能的类和接口.
名词解释:
  1. API的本意指的是: JDK提供的类和接口
  2. 我们常说的"打开API"其实指的是"打开API的帮助文档"
  3. 关于API的学习, 前期你不需要关心这些类和接口的底层是怎么写的, 只要会用就行, 用的多了, 我们才会逐渐去看源码.
API查找步骤:
  1. 找到你要查找的类

  2. 看下类所在的包

    java.lang包下的类可以直接使用, 无需导包

    ​ 其它包下的类用之前必须先导包

  3. 大概的看下类的结构, 知道它有哪些父类, 父接口, 子类等

  4. 大概的看下类的说明, 知道这个类是干嘛的即可

  5. 看下该类有无构造方法

    ​ 有: 说明该类的方法大多数都是非静态的, 需要通过 对象名. 的方式调用.
    ​ 例如: Object, String

    ​ 无: 说明该类的成员大多数都是静态的, 需要通过 类名. 的方式调用.
    ​ 例如: Math, Arrays

  6. 调用指定的方法即可

    ​ 步骤: 写 方法名(); 传参, 接收返回值

通过查看 API帮助文档 我们发现, Scanner中的如下两个方法是和接收 用户录入的字符串相关的, 于是我们拷贝源码如下:

public String next();      接受用户录入的字符串, 结束标记是: \r\n, 会获取: 空格以前的内容.
public String nextLine();   接受用户录入的字符串, 结束标记是: \r\n, 会获取: 除了换行以外所有的内容.
补充关于Scanner的小细节问题
  • 问题描述:
    • 先用Scanner类中的nextInt()方法接收整数, 再用nextLine()接收字符串, 会导致字符串无法录入的情况.
  • 产生原因
      1. nextInt() 和 nextLine() 方法的结束标记都是: \r\n
      2. nextInt()方法只接收用户录入的整数, 不接收最后的: \r\n
      3. 遗留下来的\r\n被nextLine()方法识别了, 它直接结束
  • 解决方案
    • 先 nextLine() 接收字符串, 然后 nexLine() 接收整数
    • 重新调用一次 Scanner#nextLine()
    • 重新new一个Scanner对象
    • 通过next()方法接收字符串.
    • 实际开发做法: 都用字符串接收, 然后把字符串形式的整数转成int类型即可
  int a = Integer.parseInt("123");        //相当于: int a = 123;

Object类

概述

  • 它是所有类的父类, 所有的类都直接或者间接继承自Object类.
构造方法
  • public Object();   Object类中只有一个空参构造.
    
成员方法
toString()、equals()
  • public String toString();
    • 返回该对象的地址值, 无意义, 建议子类都重写该方法, 用来打印 对象的各个属性值
      快捷键生成
  • public boolean equals(Object obj);
    • 比较两个对象是否相同, 默认比较地址值, 无意义, 建议子类都重写该方法, 改为比较对象的各个属性值
      快捷键生成

结论:

  • 实际开发中, 我们认为, 如果同一个类的两个对象 各个属性值都相同, 那么它们就是同一个对象.
Student s1 = new Student("刘亦菲", 33);
Student s2 = new Student("刘亦菲", 33);

虽然它们的地址值不同, 但是它们的属性值相同, 且是同一个类的对象, 实际开发中, 我们就认为它们就是同一个对象.

  • Object#equals() 方法默认比较地址值, 无意义, 建议子类都重写该方法, 改为比较: 对象的各个属性值.

案例:测试 toString()、equals() 方法

  • JavaBean类
package com.itheima.demo02_object;

//JavaBean类, 表示学生.
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //重写Object类的equals()方法, 比较对象的属性值是否相同。
    @Override
    public boolean equals(Object obj) {       //s1.equals(s2)
        /*
            s1: this
            s2: obj     student
         */
        //1. 提高效率, 有可能要比较的两个对象是同一个类型的对象.
        if (this == obj)	//比较:地址值
            return true;

        //2. 提高健壮性, 有可能要比较 的两个对象不是同一个类型的对象.
        if (obj == null || this.getClass() != obj.getClass()) return false;

        //3. 向下转型
        Student student = (Student) obj;
        //4. 比较两个对象的年龄是否相同.
        if (this.age != student.age) return false;
        //5. 比较两个对象的姓名是否相同.
        //这里的equals()指的是:   String类中的equals()方法
        return this.name != null ? this.name.equals(student.name) : student.name == null;
    }


    //重写Object#toString()方法
    //快捷键生成
    @Override
    public String toString() {
        /*return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';*/
        //自定义toString()方法的内容
        return name + "..." + age;
    }
}

  • 测试类
package com.ithiema.api.demo;

import com.ithiema.api.pojo.Student;

public class Demo02 {
    public static void main(String[] args) {
        Student s = new Student("刘亦菲", 33);
        System.out.println(s.toString());
        System.out.println(s);

        Student s1 = new Student("刘亦菲", 33);
        Student s2 = new Student("刘亦菲", 33);

        //比较: 引用类型.
        System.out.println(s1 == s2);               //false,  比较地址值.
        System.out.println(s1.equals(s2));          //true,   重写后, 比较的是: 对象的属性值.
        System.out.println("-----------------");


        //比较: 基本类型
        System.out.println(10 == 20);               //比较的是: 数值
        //System.out.println(10.equals(10));        //这样写会报错.
    }
}
补充案例: == 和 equals()的区别是什么?
  1. 作用范围不同

    ==: 既可以用于比较基本类型, 也可以用来比较引用类型

    equals(): 只能用于比较引用类型

  2. 作用不同

    ==: 比较基本类型比较的是 数值, 比较引用类型比较的是 地址值

    equals(): Object#equals()默认比较地址值, 无意义, 建议子类都重写它

  3. 本质不同

    ==: 是运算符

    equals(): 是方法

String类

概述

  • 它表示字符串, 所有的字符串实例都是它的对象, 且字符串一旦初始化 其值就不能发生改变.
  • 它的本质(底层)就是一个 字符数组, 字符串每个元素(字符)也是有编号的, 编号从 0 开始.

特点

  1. 字符串值是一个常量, 如果是免new创建则在常量池, 如果是new创建则在 堆区.
  2. 字符串值是一个常量, 其值一旦初始化就不能改变.
  3. 字符串中每一个字符都是有索引的, 且索引是从 0 开始数的.
构造方法
public String();
public String(String s);
public String(char[] chs);
public String(char[] chs,int start,int len); start:表示起始索引,len:表示个数
public String(byte[] bys);
public String(byte[] bys,int start,int len); start:表示起始索引,len:表示个数

实际开发中, 我们最常用的创建字符串的格式如下:
String str = “abc”; //语法糖.

public class StringDemo01 {
    public static void main(String[] args) {
        //1. 演示 public String();  通过空参构造, 创建字符串对象.
        String s1 = new String();
        System.out.println("s1: " + s1);    //输出的不是地址值, 说明String重写了Object#toString().
        System.out.println("-------------------");

        //2. 演示  public String(String s);  通过带参构造, 创建字符串对象.
        String s2 = new String("abc");
        System.out.println("s2: " + s2);
        System.out.println("-------------------");

        //3. 演示  public String(char[] chs);  把接收到的字符数组, 转成其对应的字符串形式.
        char[] chs = {'h', 'e', '黑','马','程','序','员', 'l', 'l', 'o'};
        String s3 = new String(chs);
        System.out.println("s3: " + s3);
        System.out.println("-------------------");

        //4. 演示public String(char[] chs, int index, int count);    把接收到的字符数组的一部分, 转成其对应的字符串形式.
        String s4 = new String(chs, 2, 5);
        System.out.println("s4: " + s4);
        System.out.println("-------------------");

        //5. 演示public String(byte[] bys);  把接收到的字节数组, 转成其对应的字符串形式.
        byte[] bys = {97, 98, 99, 65, 66};
        String s5 = new String(bys);
        System.out.println("s5: " + s5);        //abcAB
        System.out.println("-------------------");

        //6. 演示public String(byte[] bys, int index, int count);    把接收到的字节数组的一部分, 转成其对应的字符串形式.
        String s6 = new String(bys, 1, 2);
        System.out.println("s6: " + s6);
        System.out.println("-------------------");

        //7. 实际开发写法
        String s7 = "abc";      //语法糖.
        System.out.println("s7: " + s7);
    }
}
成员方法
equals();
equalsIgnoreCase();
length();
charAt();
toString();
toCharArray();
Java中的常量优化机制
  • 针对于byte类型:

    • 如果是变量相加:会提升类型,然后再运算
      • 类型提升顺序:byte, short, char -> int -> long -> float -> double
    • 如果是常量相加:会直接运算,然后看结果在不在左边的数据范围内,在不报错,不在就报错。
  • 针对于String类型:

    • 如果是变量拼接:会直接拼接, 不会在(堆区)开辟新空间
    • 如果是常量拼接:会在堆区开辟新空间
public class StringDemo04 {
    public static void main(String[] args) {
        byte b1 = 3;
        byte b2 = 4;
        byte b3 = 3 + 4;
        //byte b4 = b1 + b2;            //这行代码会报错, 因为提升数据类型了.
        System.out.println("-------------------------------");

        String s1 = "abc";
        String s2 = "ab";
        String s3 = "c";


		//System.out.println(s1 == (new StringBuilder()).append(s2).append(s3).toString());
        System.out.println(s1 == s2 + s3);          //false
		//System.out.println(s1 == (new StringBuilder()).append(s2).append("c").toString());
        System.out.println(s1 == s2 + "c");        //false
		//System.out.println(s1 == "abc")
        System.out.println(s1 == "ab" + "c");       //true
    }
}
equals()、equalsIgnoreCase()

equals(Object obj): 比较两个字符串是否相等, 比较的是内容, 区分大小写

equalsIgnoreCase(String s): 比较两个字符串是否相等, 比较的是内容, 不区分大小写

package com.itheima.demo03_string;

//案例: 演示字符串的比较
public class StringDemo03 {
    public static void main(String[] args) {
        
        //1.定义字符数组chs, 初始化值为: 'a, 'b', 'c', 这三个字符 .
        char[] chs = {'a', 'b', 'c'};
        
        //2.将其分别封装成s1, s2这两个字符串对象.
        String s1 = new String(chs);
        String s2 = new String(chs);
        
        //3.直接通过""的方式创建两个字符串对象s3和s4.
        String s3 = "abc";
        String s4 = "aBc";
        
        //4.通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
        System.out.println(s1 == s2);           //false
        System.out.println(s2 == s3);           //false
        System.out.println(s3 == s4);           //false
        System.out.println("-------------------");
        
        //5.通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
        System.out.println(s1.equals(s2));      //true
        System.out.println(s1.equals(s3));      //true
        System.out.println(s3.equals(s4));      //false
        System.out.println("-------------------");
        
        //6.通过equalsIgnoreCase()判断字符串abc和ABC是否相同.
        System.out.println(s3.equalsIgnoreCase("ABC"));     //true
    }
}

案例:模拟用户登录, Scanner, String, if.else <=> 三元, for循环
package com.itheima.demo04_exercise;

//但凡是写到这个包下的类, 都是你今天晚上要敲的代码, 每个至少3遍.

import java.util.Scanner;

//案例: 模拟用户登录, Scanner, String, if.else <=> 三元, for循环
public class Demo01 {
    public static void main(String[] args) {
        /*
            需求:
                1.模拟用户登录, 只给3次机会, 登录成功则提示"欢迎您, ***".
                2.登录失败则判断是否还有登录机会, 有则提示剩余登录次数, 没有则提示"您的账号已被锁定".
                3.假设初始化账号和密码分别为: "传智播客", "黑马程序员".
         */
        //1. 创建键盘录入对象.
        Scanner sc = new Scanner(System.in);
        //2. 设定初始账号和密码.
        String username = "传智播客";
        String password = "黑马程序员";

        //3. 因为只给3次机会, 所以用for循环.
        for (int i = 0; i < 3; i++) {
            //4. 提示用户录入账号和密码, 并接收.
            System.out.println("请录入您的账号: ");
            String uname = sc.nextLine();
            System.out.println("请录入您的密码: ");
            String pw = sc.nextLine();

            //5. 判断用户录入的账号和密码是否正确.
            //5.1 如果正确, 提示登录成功, 然后循环结束.
            if (username.equals(uname) && password.equals(pw)) {
                //System.out.println("登陆成功!");
                System.out.println("欢迎您, " + uname);
                break;      //细节.
            } else {
                //5.2 如果错误, 判断是否还有登陆机会.
                //5.2.1 如果有, 则提示: 登陆失败, 你还有*次机会.
                if (i != 2) {
                    System.out.println("登陆失败, 你还有" + (2 - i) + "次机会.");
                } else {
                    //5.2.2 如果没有, 提示: 账号锁定.
                    System.out.println("账号被锁定, 请于管理员联系 110");
                }
            }
        }
    }
}

length(),charAt()
  • public int length(); 获取字符串的长度
  • public char charAt(int index) 根据索引, 获取其对应的字符.
  • 小细节:
    字符串的底层其实就是一个字符数组, 所以字符串中每个元素都是由编号的, 编号是从0开始的.
public class Demo02 {
    public static void main(String[] args) {
        String str = "abc";
        //1. 演示length方法
        System.out.println("length方法: " + str.length());            //3
        //2. 演示charAt()方法.
        System.out.println("charAt方法: " + str.charAt(2));           //c

        //StringIndexOutOfBoundsException:  字符串索引越界异常.
        //System.out.println("charAt方法: " + str.charAt(20));           //报错

        //需求: 键盘录入一个字符串, 使用程序实现在控制台遍历打印该字符串.
        //1. 创建键盘录入对象.
        Scanner sc = new Scanner(System.in);
        //2. 提示用户录入并接收字符串.
        System.out.println("请录入一个字符串: ");
        String s = sc.nextLine();
        //3. 通过for循环, 遍历字符串, 获取字符串中的每一个索引值.
        for (int i = 0; i < s.length(); i++) {
            //i就是字符串中, 每个字符的索引
            //4. 根据索引, 获取到字符串中的每一个字符.
            char ch = s.charAt(i);
            //5. 打印结果.
            System.out.println(ch);
        }
    }
}

案例: 统计各类型字符的次数

package com.itheima.demo04_exercise;

import java.util.Scanner;

//案例: 统计各类型字符的次数
public class Demo03 {
    public static void main(String[] args) {
        /*
            需求:
                键盘录入一个字符串, 统计该字符串中大写字母字符, 小写字母字符, 数字字符出现的次数.
                注意: 不考虑其他字符, 例如@, !, \, /等
         */
        //1. 提示用户录入并接收.
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入一个字符串: ");
        String str = sc.nextLine();
        //2. 定义三个int类型的变量, 分别表示: 大写字母字符, 小写字母字符, 以及数字字符的次数.
        int bigCount = 0, smallCount = 0, numberCount = 0;
        //3. 通过for循环, 遍历字符串, 获取到每一个字符.
        for (int i = 0; i < str.length(); i++) {
            //获取到每一个字符
            char ch = str.charAt(i);
            //4. 判断当前遍历到的字符属于哪种字符, 是哪种, 对应的计数器就++
            if (ch >= 'A' && ch <= 'Z') {
                //大写字母字符
                bigCount++;
            } else if(ch >= 'a' && ch <= 'z') {
                //小写字母字符
                smallCount++;
            } else if(ch >= '0' && ch <= '9') {
                //数字字符
                numberCount++;
            }
        }

        //5. 循环结束后, 打印各个计数器的值即可.
        System.out.println("大写字母字符的个数: " + bigCount);
        System.out.println("小写字母字符的个数: " + smallCount);
        System.out.println("数字字符的个数: " + numberCount);
    }
}

案例: 演示字符串拼接

package com.itheima.demo04_exercise;

//案例: 演示字符串拼接.
/*
    涉及到的字符串中的方法:
        public String concat(String str);       拼接字符串, 返回新串.
 */
public class Demo04 {
    public static void main(String[] args) {
        //演示concat()方法,   了解即可, 实际开发写的比较少.
        String s1 = "ab";
        String s2 = "c";
        String s3 = s1 + s2;        //s3 = "abc", 会开辟空间(堆)
        String s4 = s1.concat(s2);  //s4 = "abc", 不会开辟堆空间.
        System.out.println("s3: " + s3);
        System.out.println("s4: " + s4);
        System.out.println("--------------------");

        /*
            需求:
                1.定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
                2.在main方法中, 调用上述的方法.
                3.例如: 数组为int[] arr = {1, 2, 3}, 则拼接后, 结果为: [1, 2, 3]
         */
        //2. 调用方法
        //int[] arr = {1, 2, 3};
        int[] arr = null;
        System.out.println(array2String(arr));
    }

    //1. 定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
    //定义为static是因为尚明main方法调用时,静态只能访问静态。
	public static String array2String(int[] arr) {
        //先做越界处理.
        if (arr == null || arr.length == 0)
            return "[]";
        //正常的拼接逻辑.
        String s = "[";
        for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1)
                s += (arr[i] + "]");
            else
                s += (arr[i] + ", ");

            //通过三元优化,自己写.
        }
        return s;
    }
}

案例: 演示字符串反转

package com.itheima.demo04_exercise;

import java.util.Scanner;

//案例: 演示字符串反转.
public class Demo05 {
    public static void main(String[] args) {
        /*
            需求:
                1.定义方法reverse(), 实现字符串的反转.
                2.在main方法中键盘录入一个字符串, 调用上述的方法后, 在控制台输出结果.
                3.例如: 键盘录入abc, 输出结果cba.
         */
        //2. 提示用户录入字符串, 并接收.
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入一个字符串: ");
        String str = sc.nextLine();
        //3. 调用方法.
        System.out.println(reverse(str));
    }

    //1. 定义方法reverse(), 实现字符串的反转.     思路: 就是倒序输出字符串, 然后拼接即可.
    public static String reverse(String s) {
        //1.1 定义字符串, 记录反转后的结果.
        String newStr = "";
        //1.2 遍历原始字符串, 然后倒序输出.
        for (int i = s.length() - 1; i >= 0; i--) {
            //1.3 拼接结果.
            newStr += s.charAt(i);
        }
        //1.4 返回具体的结果.
        return newStr;
    }
}

String类中的常用方法演示:
  • 判断功能: (返回值:Boolean)//首尾中空加判断
startsWith();
endsWIth();
isEmpty();
equals();
equalsIgnoreCase();
  • 获取功能: //截长取位取元素
subString();	//2个重载
length();
indexOf();		//2个重载
lastIndexOf();	//2个重载
charAt();
  • 转换功能 //大小拼串转数组
toUpperCase();
toLowerCase();
concat();
toCharArray();
getBytes();		//2个重载
  • 其他功能 //除空切换字典排
trim();
split();
replace();
replaceAll();
compareTo();
startWith(),contains()
需求:已知有1, 2, 3, 4 这四个数字, 问它们能组合成的四位数字形式有哪些, 并将结果打印到控制台上.
要求:该四位数字必须包含1, 2, 3, 4 这四个数字.

需求:数字4不能开头,数字1和3不能挨着,按照5个一行顺序打印
package com.ithiema.api.demo;

import java.util.Scanner;

public class Demo09 {
    public static void main(String[] args) {
        for (int i = 1234, count = 0; i <= 4321; i++) {
            //核心思路:把i(int) -> 字符串,然后通过String类中的方法做校验
            String s = "" + i;
            if (s.contains("1") && s.contains("2") && s.contains("3")
                    && s.contains("4") && !s.startsWith("4")
                    && !s.contains("13") && !s.contains("31")) {
                System.out.print(++count % 5 == 0 ? s + "\r\n" : s + "\t");
            }
        }
    }
}

StringBuilder类

概述:
  • 它是java.lang包下的类,可以直接使用,无需导包
  • 它表示可变的字符串序列,即:它的内容是可变的,所以该类也叫:字符串缓冲序列

作用:

  • 一般应用于大量的字符串拼接操作,因为不会频繁的开辟空间,而是在对象内部直接做拼接,所以效率相对较高
构造方法
public StringBulider();		创建字符串缓冲区类对象,封装:空参
public StringBulider(String s);		创建字符串缓冲区,封装:指定的字符串内容。
成员方法
public StringBuilder append(Object obj);  添加元素到StringBuilder, 返回该对象本身.
public StringBuilder reverse();		反转内容, 返回该对象本身.
演示StringBuilder中的方法
package com.itheima.demo05_stringbuilder;

public class Demo02 {
    public static void main(String[] args) {
        //1.通过空参构造创建StringBuilder类的对象sb.
        StringBuilder sb = new StringBuilder();
		
        //2.通过append()方法, 往sb对象中添加"hello",然后用sb2对象接收.
        StringBuilder sb2 = sb.append("hello");
	
        //3.打印对象sb和sb2的结果, 并观察.
        System.out.println("sb: " + sb);        //sb:  hello
        System.out.println("sb2: " + sb2);      //sb2: hello
        System.out.println(sb == sb2);          //比较的是地址值, true

        //实际开发中, append()方法的调用写法.
        //如果是单个添加
        sb.append("world");
        //如果是添加多个, 用链式思想实现.
        //复杂写法
       /* sb.append("传智播客");
        sb.append("黑马程序员");
        sb.append("夯哥");*/

       //链式编程解释: 如果一个方法的返回值还是对象, 我们可以在后边接着 .方法(), 这种写法就叫链式编程.
        sb.append("传智播客").append("黑马程序员").append("夯哥");
        System.out.println("sb: " + sb);        //sb:  helloworld
        System.out.println("---------------------------");

        //4.通过reverse()方法, 来反转上述的内容.
        StringBuilder sb3 = sb2.reverse();
        System.out.println("sb: " + sb);
        System.out.println("sb2: " + sb2);
        System.out.println("sb3: " + sb3);
        System.out.println(sb2 == sb3);
    }
}

链式编程解释:如果一个方法的返回值还是对象, 我们可以在后边接着 .方法(), 这种写法就叫链式编程.
sb.append(“传智播客”).append(“黑马程序员”).append(“夯哥”);

演示StringBuilder和String之间的相互转换
    String 对象  ->  StringBuilder 对象
        public StringBuilder(String str);       带参构造, 创建 StringBuilder 对象.

    StringBuilder 对象  ->  String 对象
        StringBuilder 类中的 toString()方法
            public String toString();          返回该对象的字符串形式.
package com.itheima.demo05_stringbuilder;

public class Demo03 {
    public static void main(String[] args) {
        //1.定义空参不可变StringBuilder对象, 往里边添加完"hello"字符串后, 再将其转成String类型的对象.
        StringBuilder sb = new StringBuilder();
        sb.append("hello");
        String s1 = sb.toString();          // StringBuilder对象  ->  String对象
        System.out.println("s1: " + s1);
        System.out.println("--------------------");

        //2.将String字符串转成StringBuilder对象, 然后打印.
        String s2 = "传智播客";
        StringBuilder sb2 = new StringBuilder(s2);      //String对象  ->  StringBuilder对象
        System.out.println("sb2: " + sb2);
    }
}

案例: 拼接字符串,StringBuilder(), append(), toString()

package com.itheima.demo04_exercise;

//案例: 拼接字符串.
public class Demo06 {
    public static void main(String[] args) {
        //1.定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
        //2.在main方法中, 调用上述的方法.
        //3.例如: 数组为int[] arr = {1, 2, 3}, 则拼接后, 结果为: [1, 2, 3]
        //int[] arr = null;
        int[] arr = {1, 2, 3};
        System.out.println(array2String(arr));
    }

    //1. 定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
    public static String array2String(int[] arr) {
        //1. 非法值校验.
        if (arr == null || arr.length == 0)
            return "[]";

        //2. 创建StringBuilder对象.
        StringBuilder sb = new StringBuilder("[");
        //3. 正常的拼接, 用if.else实现.
       /* for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1)    //最后一个元素
                sb.append(arr[i]).append("]");
            else
                sb.append(arr[i]).append(", ");
        }*/

       //3. 正常的拼接, 用三元实现
        for (int i = 0; i < arr.length; i++)
            sb.append(arr[i]).append(i == arr.length - 1 ? "]" : ", ");
        return sb.toString();
    }
}

案例: StringBuilder案例, 反转字符串

思路: String对象 -> StringBuilder对象 -> 调用StringBuilder对象的reverse()方法 -> 重新换成String对象.

package com.itheima.demo04_exercise;

import java.util.Scanner;

public class Demo07 {
    public static void main(String[] args) {
        //2.在main方法中键盘录入一个字符串, 调用上述的方法后, 在控制台输出结果.
        //3.例如: 键盘录入abc, 输出结果cba.
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入一个字符串: ");
        String str = sc.nextLine();
        //方式一: 调用自定义方法
        System.out.println(reverse(str));
        System.out.println("------------------------");

        //方式二: 链式编程.
        //思路:  String对象 -> StringBuilder对象 -> 调用StringBuilder对象的reverse()方法 -> 重新换成String对象.
        String reverseStr = new StringBuilder(str).reverse().toString();
        System.out.println(reverseStr);
    }

    //1.定义方法reverse(), 实现字符串的反转.
    public static String reverse(String s1) {
        //1. 把String -> StringBuilder对象.
        StringBuilder sb = new StringBuilder(s1);
        //2. 调用StringBuilder#reverse(), 反转内容.
        sb.reverse();
        //3. 把StringBuilder -> String, 然后返回.
        return sb.toString();
    }
}
StringBuilder 和 StringBuffer之间的区别:
1. String和其他两个类型的区别:
		String: 长度固定.
		其他两个类型: 长度可变. 
	
2. StringBuilderStringBuffer之间的区别:
		StringBuilder: JDK1.5出来的, 它里边的方法都是线程不安全(线程不同步), 效率稍高.
		StringBuffer: JDK1.0出来的,  它里边的方法都是线程安全(线程同步), 效率稍低.
冒泡排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DiRiUZpP-1669232825706)(F:\BigData\java\图片\day09图片\01.冒泡排序原理图.png)]

原理:
相邻元素两两比较, 大的往后走, 这样的话, 第一轮比较完毕后, 最大值就在最大索引处.

package com.itheima.demo01_arrays;

//案例: 演示冒泡排序.
/*
    原理:
        相邻元素两两比较, 大的往后走, 这样的话, 第一轮比较完毕后, 最大值就在最大索引处.
 */
public class Demo01 {
    public static void main(String[] args) {
        /*
            需求:
                1.已知数组int[] arr = {25, 69, 80, 57, 13}, 请编写代码对齐进行升序排序.
                2.即: 排序后结果为: arr = {13, 25, 57, 69, 80};
         */
        //1. 定义数组, 记录要排序的元素.
        int[] arr = {25, 69, 80, 57, 13};
        //2. 通过外循环, 控制比较的轮数.
        //这里的-1是为了啥?  为了提高效率.
        for (int i = 0; i < arr.length - 1; i++) {//0, 1, 2, 3
            //3. 通过内循环, 控制每轮比较的次数.
            /*
                这里的-1是为了啥?   为了防止出现索引越界异常.
                这里的-i是为了啥?   为了提高效率.
             */
            for (int j = 0; j < arr.length - 1 - i; j++) {       //4, 3, 2, 1
                //4. 如果前一个元素比后一个元素大, 就交换它们的位置.
                //即: arr[j] 和 arr[j + 1] 比较
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        //5. for循环执行结束后, 已经排好序了, 我们直接打印数组即可.
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

Arrays工具类

概述:
  • 它是针对于数组的工具类。里面提供了大量针对于数组的操作,例如:对数组元素排序,把数组元素拼接成字符串等。
工具类介绍:
  • 成员都是静态的, 可以通过 类名. 的形式直接调用
  • 构造方法私有化
成员方法
  • public static String toString(int[] arr) 把数组转成其对应的字符串形式, 例如: [1, 3, 5, 6]
  • public static void sort(int[] arr) 对数组元素进行升序排序.
package com.itheima.demo01_arrays;

import java.util.Arrays;

//案例: 演示Arrays工具类的使用.

public class Demo02 {
    public static void main(String[] args) {
        //1.已知数组int[] arr = {25, 69, 80, 57, 13}.
        int[] arr = {25, 69, 80, 57, 13};
        //补充: 打印排序前的结果	排序前: [25, 69, 80, 57, 13]
        System.out.println("排序前: " + Arrays.toString(arr));
        
        //2.通过Arrays#sort()方法, 对其升序排列.
        Arrays.sort(arr);
        
        //3.打印排序后的结果.	排序后: [13, 25, 57, 69, 80]
        System.out.println("排序后: " + Arrays.toString(arr));
    }
}

  • 一个小问题:
    • 通过翻看API帮助文档,我们发现Arrays工具类并没有提供构造方法,这是为什么?
    • 如果我们不写构造方法,系统会默认给一个 公共的无参构造,那为什么找不到?
  • 答案:
    • 因为Arrays类中提供了一个私有的无参构造方法,所以系统就不再提供构造方法了,又因为是私有成员所以API不显示。

包装类

  • 概述:

    • 所谓的的包装类指的就是基本类型对应的引用类型,之所以有包装类,目的就是为了把基本类型封装成对象,方便我们管理。
  • 对应的关系:

    • 基本类型对应的引用类型(包装类)
      byteByte
      shortShort
      charCharacter
      intInteger
      longLong
      floatFloat
      doubleDouble
      booleanBoolean
  • 包装类的主要作用:

    • 主要用于 该类型对应的基本类型String类型的数据之间 相互转换
  • 例如:

    • Interger 主要用于把 字符串形式的数字,转换成int类型

      • int num = Integer.parseInt(“123”);
    • Double 主要用于把 字符串形式的小数,转换成double类型

      • double d = Double.parseDouble(“12.3”);
    • Boolean 主要用于把 字符串形式的布尔值,转换成boolean类型

      • boolean flag = Boolean.parse.Boolean(“false”);
Integer类
  • 概述

    • 它是基本类型int对应的 引用类型(即:包装类),主要提供了针对 intString 相互转换的一些方法
  • 构造方法

public Integer(int i);	创建Integer类型的对象,封装:整数
public Integer(String s);	创建Integer类型的对象,封装:字符串形式的整数,如果不是纯数字,会报错
package com.itheima.demo02_integer;

//案例: 演示Integer类的构造方法.

public class Demo01 {
    public static void main(String[] args) {
        //1.通过上述的两个构造方法, 分别创建Integer类型的对象.
        //1.1 演示:  public Integer(int value);
        Integer i1 = new Integer(10);
        //1.2 演示: public Integer(String value);
        Integer i2 = new Integer("123");
        //Integer i2 = new Integer("123a");  这样写会报错.

        //2.在main方法中, 打印创建好的Integer对象.
        System.out.println("i1: " + i1);
        System.out.println("i2: " + i2);
        System.out.println("----------------------------");

        //3. 演示Integer类中的两个常量
        System.out.println(Integer.MAX_VALUE);      //int类型的最大值
        System.out.println(Integer.MIN_VALUE);      //int类型的最小值

    }
}
演示int和String之间的相互转换
  • int -> String

    • int a = 10;
      String s = "" + a;		//推荐使用
      
  • String -> int

    • String s = "123";		//必须是 纯数字 形式的字符串
      int i = Integer.parseInt(s);
      
package com.itheima.demo02_integer;

//案例: 演示int和String之间的相互转换.
public class Demo02 {
    public static void main(String[] args) {
	
        //需求1: int   ->     String
        //方式一: 直接在数值后边拼接 "",        推荐使用.
        int a = 10;
        String s1 = "" + a;
        System.out.println("s1: " + s1);

        //方式二: String#valueOf()
        String s2 = String.valueOf(111);
        System.out.println("s2: " + s2);
        System.out.println("-----------------------------");

        //需求2: String   ->     int,	必须是纯数字形式的字符串
        //方式1: 转换思路 String -> Integer -> int
        String s3 = "123";
        //String -> Integer
        Integer i1 = new Integer(s3);
        //Integer -> int
        int num1 = i1.intValue();
        System.out.println("num1: " + num1);

        //方式2: 通过Integer#parseInt();方法实现,  推荐使用.
        int num2 = Integer.parseInt(s3);
        System.out.println("num2: " + num2);

    }
}

案例:字符串切割,然后排序,并拼接,然后打印

提示:

  • 通过String类的split(String regex)方法,可以按照指定字符切割字符串
    • public String[] split(String regex); 根据给定的字符串,切割字符串,获取字符串数组
    • public String subString(int start,int end); 根据索引截取指定范围的内容,包左不包右
package com.ithiema.api.demo;

import java.util.Arrays;

public class Demo14 {
    public static void main(String[] args) {
        //1.定义String s,记录要操作的字符串
        String s = "91 27 45 38 50";
        //2.对其按照 空格 进行切割,获取String[]
        String[] strArr = s.split(" ");
        //3.定义长度与其一模一样的int[] ,来存储转换后的数据。
        int[] arr = new int[strArr.length];
        //4.遍历字符串数组,获取其中的每一个字符串
        for (int i = 0; i < strArr.length; i++) {
            //5.将其转成整数后,存储到:数组中
            arr[i] = Integer.parseInt(strArr[i]);
        }
        //6.对数组元素进行排序
        Arrays.sort(arr);
        //7.将(排序后)的数组元素拼接成指定的字符串
        String str = Arrays.toString(arr);
        //思路1:截取
        String s1 = str.substring(1, str.length() - 1);
        System.out.println(s1);

        //思路2:替换
        String s2 = str.replace("[", "").replace("]", "");
        //8.打印输出
        System.out.println(s2);

    }
}
案例: 演示其他基本类型的数据 和 String之间如何相互转换
  • 包装类中都有一个方法, 叫 parseXxx(), 用于把字符串形式的 该类型数据, 转成对应的 基本类型, Character类型除外

  • Integer.parseInt("纯数字类型的字符串值");   用于把 String  ->   int
    Double.parseDouble("纯数字类型的字符串值");   用于把 String  ->   double
    Boolean.parseBoolean("字符串形式的true或者false");  用于把 String  ->   boolean
    
  • 因为字符串的本质就是一个字符数组, 所以字符和字符串之间的转换有特殊的方式

  • 场景1:  单字符 和 字符串之间相互转换.
    	char   ->     String
    		String s1 = 'a' + "";
       String  ->     char
    		char ch = "abc".charAt(1);
    
    场景2:  字符数组   -> 字符串之间相互转换.
    	char[]      ->      String
    		char[] chs = {'a', 'b', 'c'};
    		String s = new String(chs);
    
    	String      ->      char[]
    		String s = "abc";
    		char[] chs = s.toCharArray();
    
    
package com.itheima.demo02_integer;

public class Demo03 {
    public static void main(String[] args) {
        //1. 演示除Character之外的, 其他包装类的共性方法.
        //String  ->     int
        int num = Integer.parseInt("123");
        //String  ->     double
        double d = Double.parseDouble("10.3");
        //String  ->     boolean
        boolean flag = Boolean.parseBoolean("false");
        System.out.println("num: " + num);
        System.out.println("d: " + d);
        System.out.println("flag: " + flag);
        System.out.println("-------------------------------");

        //2. 演示 字符   -> 字符串之间相互转换, 略.
        //char   ->     String
        String s1 = 'a' + "";
        //String  ->     char
        char ch = "abc".charAt(1);

        //3. 演示 字符数组   -> 字符串之间相互转换,
        //String      ->      char[]
        String str = "黑马程序员";
        char[] chs = str.toCharArray();
        //System.out.println(chs);    //这里不是地址值,而是数组元素.  IO流解释.
        for (int i = 0; i < chs.length; i++) {
            char c = chs[i];
            System.out.println(c);
        }

        // char[]      ->      String
        String str2 = new String(chs);
        System.out.println("str2: " + str2);

    }
}

JDK1.5的特性 自动拆装箱
  • 装箱:指的是把基本类型的数据转成其对应的引用类型
  • 拆箱:指的是把引用类型得数据转成其对应的基本类型
package com.ithiema.api.demo;

public class Demo17 {
    public static void main(String[] args) {
        int a = 10;
        Integer i1 = new Integer(a);    //装箱
        Integer i2 = a;                 //自动装箱,JDK1.5的特性

        int b = i1.intValue();
        int c = i1;                     //自动拆箱,JDK1.5的特性

        Integer aa = 3;
        aa += 5;                //1.自动拆箱    2.做加法运算   3.自动装箱
        System.out.println(aa);

    }
}

Date类

  • 概述:
    • Date类表示特定的瞬间,精确到毫秒. 它是java.util包下的类, 用之前需要先导包.
    • 1秒 = 1000毫秒
构造方法
  • public Date();
    • 创建日期类对象,采用:系统默认时间, 单位是毫秒
  • public Date(long times);
    • 创建日期类对象,采用:指定时间,即:时间种子一样,获取的日期也是一样的,单位是毫秒

细节:

  1. 你通过Date获取的一个数值,其实就是当前时间 相对于 时间原点的 对应的 毫秒值。
  2. 标准时间原点:1970年1月1日 00:00:00
  3. 但是我们用的是北京时间,处于东八区,所以我们计算机用的时间原点是:1970年1月1日 08:00:00
package com.ithiema.api.demo;

import java.util.Date;

public class Demo18 {
    public static void main(String[] args) {
        //1. 演示 public Date();          采用当前系统默认时间, 生成Date对象.
        Date d1 = new Date();      
        System.out.println(d1);

        //2. 演示 public Date(long time); 采用指定的毫秒值, 生成对应的Date对象.
        Date d2 = new Date(1000L);  //指定时间 单位毫秒 这里为 1秒
        System.out.println(d2);

        Date d3 = new Date(0L);
        System.out.println(d2);

    }
}

成员方法
  • public long getTime(); //获取Date对象对应的 毫秒值.

    • 可以计算某段程序的执行时间.
  • public void setTime(long time); //设置当前Date对象的毫秒值为指定的值.

    • 我们在日志文件中可以记录一些当前时间的毫秒值, 用的时候把它转成时间对象即可, 方便我们存储和操作.

//案例: 演示Date类的成员方法

package com.itheima.demo04_date;

import java.util.Date;

public class Demo02 {
    public static void main(String[] args) {
        //1. 采用当前系统默认时间, 创建Date对象.
        Date d1 = new Date();
        System.out.println(d1);                 //Mon Jun 01 12:07:33 CST 2020
        //2. 获取上述时间对应的毫秒值.
        System.out.println(d1.getTime());       //1590984453616

        System.out.println("---------------------");

        //2. 采用指定的毫秒值, 生成Date对象.
        //Date d2 = new Date(1590984453616L);
        Date d2 = new Date();
        d2.setTime(1590984453616L);
        System.out.println(d2);
    }
}

扩展:Date在实际开发中的真正应用

  • 应用场景:
    • 时间对应的毫秒值可以用 日志文件中
    • 用来计算某个程序的执行时间
package com.ithiema.api.demo;

import java.util.Date;

public class Demo20 {
    public static void main(String[] args) {
        Date d1 = new Date();
        long start = d1.getTime();

        for (int i = 0; i < 10000; i++) {
            System.out.println("hello world!" + i);
        }

        Date d2 = new Date();
        long end = d2.getTime();
        System.out.println("执行时间为" + (end - start) + "毫秒");
    }
}

SimpleDateFormat类

  • 概述:
    • 它是java.text包下的类,用之前需要导包
    • 它是日期格式化类,主要用来对日期做 格式化 和 解析操作的
  • 名词解释:
    • 格式化:把Date -> String
    • 解析: 把String -> Date,必须是:符合日期格式的字符串。
构造方法
  • public SimpleDateFormat(); 采用默认模板.
  • public SimpleDateFormat(String pattern); 采用指定模板.
成员方法
  • public final String format(Date date); 日期格式化操作, 即: Date -> String

  • public Date parse(String source); 日期解析操作, 即: String -> Date

package com.ithiema.api.demo;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo21 {
    public static void main(String[] args) {
        Date d = new Date();
        System.out.println("格式化前" + d);     //Sun Nov 06 16:33:26 CST 2022

        SimpleDateFormat sdf = new SimpleDateFormat();
        String s = sdf.format(d);
        System.out.println("格式化后" + s);     //22-11-6 下午4:33

        //指定模板
		//SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");

        String s2 = sdf2.format(d);
        System.out.println(s2);
    }
}

DateUtils工具类的定义
package com.ithiema.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {
    //1.构造方法私有化
    private DateUtils() {
    }
    //2.创建私有的 静态的成员变量,用来表示:日期格式化对象
    private static SimpleDateFormat sdf;

    //3.定义方法,用来实现格式化操作
    /*
    * @param d 要被格式化的日期对象
    * @param pattern 格式化时采用的模板
    * @return 格式化后的字符串对象
    * */
    public static String date2String(Date d, String pattern){
        //1.创建SimpleDateFormat对象
        sdf = new SimpleDateFormat(pattern);
        //2.格式化操作,并返回结果
        //分解版
        /*String str = sdf.format(d);
        return str;*/
        //合并版
        return sdf.format(d);
    }
    //4. 定义方法, 用来实现:日期的解析操作.
    /*
     * @param strDate 要被解析的字符串形式的日期对象
     * @param pattern 解析时采用的模板
     * @return解析后的字符串日期对象
     */
    public static Date string2Date(String strDate,String pattern) throws ParseException {
        sdf = new SimpleDateFormat(pattern);
        //分解版
        /*Date d = sdf.parse(strDate);
        return d;*/
        //合并版
        return sdf.parse(strDate);
    }
}
DateUtils工具类的使用
package com.ithiema.api.demo;

import com.ithiema.utils.DateUtils;

import java.text.ParseException;
import java.util.Date;

public class Demo23 {
    public static void main(String[] args) throws ParseException {
        Date date = new Date();
        //需求1:通过DateUtils工具类实现 格式化操作
        //调用工具类方法,格式化
        //因为是静态的所以用 类名. 的方式调用该方法
        String result = DateUtils.date2String(date, "yyyy-MM-dd HH:mm:ss");
        System.out.println(result);

        //需求2:通过DateUtils工具类实现 解析操作
        String str = "2021年5月12日";
        //调用工具类方法,解析
        Date date2 = DateUtils.string2Date(str, "yyyy年MM月dd日");
        System.out.println(date2);

    }
}

Calendar类

  • 概述:
    • 它是 java.util 包下的类,用之前需要导包
    • 它表示日历类,里面绝大多数的功能都是用来替代 java.util.Date类的
成员常量
public static final int YEAR                    年份
public static final int MONTH                   月份,0 - 11
public static final int DATE                    年中的某一天
public static final int DAY_OF_MONTH            月中的某一天
public static final int DAY_OF_WEEK             星期中的第几天,周日:1,周一:2 ....
public static final int DAY_OF_YEAR             年中的第几天
成员方法

public static Calendar getInstance(); 获取Calendar类的子类对象,即抽象类多态
public int get(int field); 根据给定的日历字段, 获取其对应的值.
public void set(int year, int month, int day) ; 设置时间为指定的(年, 月, 日)
public void add(int field, int count); 设置指定的日历字段, 偏移指定的量.负数往前腿推,正数往后推

入门案例:

package com.ithiema.api.demo;

import java.util.Calendar;

public class Demo24 {
    public static void main(String[] args) {
        //1.创建Calendar类型的对象,确切的说:它是子类对象
        Calendar c = Calendar.getInstance();       //底层其实是:抽象类多态
        System.out.println(c);
    }
}
演示Calendar中的成员变量和成员方法

案例:Calendar类的功能获取各种日期

package com.ithiema.api.demo;

import java.util.Calendar;

public class Demo25 {
    public static void main(String[] args) {
        //1.创建Calendar类的对象
        Calendar c = Calendar.getInstance();
        //2.获取年份,并打印
        System.out.println(c.get(Calendar.YEAR));
        //3.获取月份,并打印
        System.out.println(c.get(Calendar.MONTH + 1));
        //4.获取星期中的第几天
        System.out.println(c.get(Calendar.DAY_OF_WEEK));
        //5.获取月中第几天
        System.out.println(c.get(Calendar.DAY_OF_MONTH));
        //6.获取年中第几天
        System.out.println(c.get(Calendar.DAY_OF_YEAR));
    }
}

案例:计算某年的2月有多少天
package com.ithiema.api.demo;

import java.util.Calendar;
import java.util.Scanner;

public class Demo26 {
    public static void main(String[] args) {
        //1.获取日历;类对象
        Calendar c = Calendar.getInstance();
        //2.创建键盘录入对象,提示用户录入年份,并接收
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个年份");
        int year = sc.nextInt();
        //3.设置时间为该年的3月1日
        c.set(year, 2, 1);      //月份范围:0 ~ 11,2表示3月
        //4.把时间往前推1天
        c.add(Calendar.DATE, -1);
        //5.获取该天是月中第几天,即为:我们要的结果
        int day = c.get(Calendar.DATE);
        //6.打印结果
        System.out.println(year + "年的2月份有" + day + "天");
    }
}

内部类

  • 概述
    • 类里面还有一个类,里面的叫内部类,外面的叫外部类
  • 分类
    • 成员内部类:写在成员位置的内部类
    • 局部内部类:写在局部位置的内部类
  • 作用
    • 成员内部类:一般应用于底层源代码,主要是用来对外部类的功能做扩展和补充的。(了解)
    • 局部内部类:我们用的最多的就是它的一种特殊写法,叫:匿名内部类
package com.ithiema.api.demo;

public class Demo03 {
    //成员变量
    int a = 10;

    //成员内部类
    class A {
    }

    public void show(int b) {   //b 和 c都是局部变量
        //局部变量
        int c = 20;

        //局部内部类
        class B {
        }
    }
}
匿名内部类
  • 概述

  • 指的就是没有名字的 局部内部类。 (局部位置: 方法中, 或者方法的形参列表)

  • 格式

    new 类名或者接口名() {
        //重写父类或者父接口中所有的抽象方法
    };
    
  • 本质

    • 专业版:它是一个 继承了类 或者 实现了接口的 子类的 匿名对象。
    • 大白话版: 匿名内部类的本质就是一个:子类对象。
  • 应用场景:

      1. 当对 成员方法(也叫:对象方法) 仅调用1次的时候。
      1. 匿名内部类可以作为方法的实参进行传递。(用的最多)
  • 小技巧:

    • 实际开发中,当父类或者父接口中的抽象方法只有1个的时候,我们才会考虑使用匿名内部类。
    • 目前刚接触匿名内部类,我们只要抽象方法不超过3个,就可以考虑使用匿名内部类。
匿名内部类用法1_当对成员方法仅调用1次的时候

动物类,父类

package com.itheima.demo07_inner;

//抽象类, 动物类.
public abstract class Animal {
    //抽象方法: 表示吃饭.
    public abstract void eat();
}

猫类,子类

package com.itheima.demo07_inner;

//表示猫类, 继承Animal
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼!");
    a}
}

动物类的测试类

package com.itheima.demo07_inner;

//动物类的测试类, 用来演示: 匿名内部类入门.

public class AnimalTest {
    public static void main(String[] args) {
        //需求: 调用Animal#eat()方法.
        //方式1: 传统做法, 搞一个Animal类的子类, 例如: Cat, 然后通过多态实现.
        Animal an = new Cat();          //子类名: Cat, 对象名叫: an
        an.eat();
        System.out.println("-----------------------");

        //方式2: 通过匿名对象实现.
        /*
            匿名对象解释:
                概述:
                    没有名字的对象, 就叫匿名对象.
                特点:
                    用完以后就会变成垃圾对象, 由GC在不确定的时间回收.
         */
        //new Cat(): 就是一个继承了Animal类的子类(Cat)的匿名对象.
        new Cat().eat();            //子类名: Cat, 对象名叫: ??
        System.out.println("-----------------------");

        //方式3: 通过匿名内部类实现.
        //匿名内部类的本质: 就是一个继承了Animal类的子类的匿名对象.
        new Animal() {               //子类名: ??, 对象名叫: ??
            //重写类或者接口中所有的抽象方法.
            @Override
            public void eat() {
                System.out.println("我是通过匿名内部类的形式创建的 Animal类的子类对象");
            }
        }.eat();
		
		//匿名内部类升级版:匿名内部类多态
		Animal an2 = new Animal() {               //子类名: ??, 对象名叫: ??
            //重写类或者接口中所有的抽象方法.
            @Override
            public void eat() {
                System.out.println("我是通过匿名内部类的形式创建的 Animal类的子类对象");
            }
        };
		an2.eat();
		an2.eat();
		an2.eat();
    }
}
匿名内部类用法2_作为方法的实参传递
package com.ithiema.api.demo;

import com.ithiema.api.pojo.Animal;
import com.ithiema.api.pojo.Cat;

public class Demo01 {
    public static void main(String[] args) {
        //需求:调用Animal#eat()方法
        //格式:printAnimal(Animal类型的子类对象);

        //方法1:抽象类多态
        Animal an = new Cat();
        printAnimal(an);
        System.out.println("------------------");

        //方法2:匿名对象
        printAnimal(new Cat());
        System.out.println("------------------");

        //方法3:匿名内部类
        //匿名内部类作为方法的实参传递
        printAnimal(new Animal() {      //实参

            @Override
            public void eat() {
                System.out.println("匿名内部类,动物会吃");
            }
        });

    }

    //定义方法,接收Animal,调用其eat()方法
    public static void printAnimal(Animal an) {
        an.eat();
    }
}
         用完以后就会变成垃圾对象, 由GC在不确定的时间回收.
     */
    //new Cat(): 就是一个继承了Animal类的子类(Cat)的匿名对象.
    new Cat().eat();            //子类名: Cat, 对象名叫: ??
    System.out.println("-----------------------");

    //方式3: 通过匿名内部类实现.
    //匿名内部类的本质: 就是一个继承了Animal类的子类的匿名对象.
    new Animal() {               //子类名: ??, 对象名叫: ??
        //重写类或者接口中所有的抽象方法.
        @Override
        public void eat() {
            System.out.println("我是通过匿名内部类的形式创建的 Animal类的子类对象");
        }
    }.eat();
	
	//匿名内部类升级版:匿名内部类多态
	Animal an2 = new Animal() {               //子类名: ??, 对象名叫: ??
        //重写类或者接口中所有的抽象方法.
        @Override
        public void eat() {
            System.out.println("我是通过匿名内部类的形式创建的 Animal类的子类对象");
        }
    };
	an2.eat();
	an2.eat();
	an2.eat();
}

}


##### 匿名内部类用法2_作为方法的实参传递

~~~java
package com.ithiema.api.demo;

import com.ithiema.api.pojo.Animal;
import com.ithiema.api.pojo.Cat;

public class Demo01 {
    public static void main(String[] args) {
        //需求:调用Animal#eat()方法
        //格式:printAnimal(Animal类型的子类对象);

        //方法1:抽象类多态
        Animal an = new Cat();
        printAnimal(an);
        System.out.println("------------------");

        //方法2:匿名对象
        printAnimal(new Cat());
        System.out.println("------------------");

        //方法3:匿名内部类
        //匿名内部类作为方法的实参传递
        printAnimal(new Animal() {      //实参

            @Override
            public void eat() {
                System.out.println("匿名内部类,动物会吃");
            }
        });

    }

    //定义方法,接收Animal,调用其eat()方法
    public static void printAnimal(Animal an) {
        an.eat();
    }
}
~~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值