找回密码
 立即注册
首页 业界区 安全 JavaSE-08面向对象高级二

JavaSE-08面向对象高级二

喜及眩 2025-6-23 17:29:42
JavaSE-08面向对象高级二


  • [ 任务列表 ]
  • 1.代码块
  • 2.内部类
  • 3.函数式编程
  • 3.1.Lambda表达式
  • 3.2.函数式接口
  • 3.3.方法引用
  • 4.常用API
  • 4.1.String
  • 4.2.ArrayList集合
  • 5.GUI编程
  • 6.其他
1.代码块


  • 类中的五大成分:成员变量、构造器、成员方法、代码块、内部类。
  • JDK8开始,新增的代码编程:函数式编程。
  • 代码块:是类的五大成分之一。
  • 代码块分为两种:
    ① 静态代码块
    格式:static{ }  ——属于类
    特点:类加载时自动执行,由于类只加载一次,所以静态代码块也只会执行一次。
    作用:完成类的静态资源数据初始化。静态代码块中的代码实际上是在方法区(Method Area)执行的。
    例如:对静态变量的初始化赋值。例如类的静态数组变量定义之后,可以在静态代码块中初始化。(比在main中初始化更加优雅,是最佳实践)
    ② 实例代码块:
    格式:{ } ——属于对象
    特点:每次创建对象时,执行实例代码块,并在构造器前执行。与构造器一样,实例初始化代码块也是在上执行的,因为它涉及到对实例成员的初始化。
    作用:和构造器一样,都是用来完成对象实例资源的初始化的。例如:对实例变量进行初始化赋值。
  1. public class CodeDemo1 {
  2.     public static String schoolName;
  3.     public static String [] cards = new String[5]; // 静态数组
  4.     // 静态代码块:有static修饰,属于类,与类一起优先加载,自动执行一次
  5.     // 基本作用:可以完成对类的静态资源的初始化
  6.     static{
  7.         System.out.println("静态代码块执行了");  // 先加载类,再执行main方法
  8.         schoolName = "黑马程序员";
  9.         cards[0] = "A";
  10.         cards[1] = "2";
  11.         cards[2] = "3";
  12.         cards[3] = "4";
  13.     }
  14.     public static void main(String[] args) {
  15.         // 目标:认识代码块,搞清楚代码块的基本作用。
  16.         System.out.println("main方法执行了");
  17.         System.out.println(schoolName);
  18.         System.out.println(Arrays.toString(cards));  // 返回数组内容观察
  19.     }
  20. }
复制代码
  1. 运行结果:
  2. 静态代码块执行了
  3. main方法执行了
  4. 黑马程序员
  5. [A, 2, 3, 4, null]
复制代码
  1. public class Codedemo2 {
  2.     private String name;
  3.     private String [] direction = new String[4];  // 实例变量
  4.     // 实例代码块(构造代码块):无static修饰,属于对象,每次创建对象时,都会优先执行一次
  5.     // 基本作用:初始化对象的实例资源
  6.     {
  7.         System.out.println("实例代码块执行了");
  8.         name = "张三";
  9.         direction[0] = "N";
  10.         direction[1] = "S";
  11.         direction[2] = "W";
  12.         direction[3] = "E";
  13.     }
  14.     public static void main(String[] args) {
  15.         // 目标:实例代码块
  16.         System.out.println("main方法执行了");
  17.         Codedemo2 A = new Codedemo2();
  18.         new Codedemo2();
  19.         new Codedemo2();
  20.         System.out.println(A.name);
  21.         System.out.println(Arrays.toString(A.direction));
  22.     }
  23. }
复制代码
  1. 运行结果:
  2. main方法执行了
  3. 实例代码块执行了
  4. 实例代码块执行了
  5. 实例代码块执行了
  6. 张三
  7. [N, S, W, E]
复制代码
2.内部类


  • 内部类:指定义在另一个类内部的类,即在类的内部还有类存在。
  • 场景:当一个类的内部,包含了一个完整的事物,且这个事物没必要单独设计时,就可以把这个事物设计成内部类。
    例如:汽车类内部可以定义一个完整的发动机类。
  • 分类:

    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类

  • 1、成员内部类:就是一个类是另一个类中的一个普通成员,类似前面我们学过的普通成员变量,成员方法。
    成员内部类:可以有成员变量,成员方法,构造器,getter和setter方法,可以创建对象,可以被继承,可以继承其他类……(类的对象可以干的它都可以干)。
  1. // 外部类
  2. public class Outer {
  3.     public static String schoolName = "heima程序员";
  4.     public static void test(){
  5.         System.out.println("test()");
  6.     }
  7.     private int age;
  8.     public void run(){}
  9.     // 成员内部类:无static修饰,属于外部类的对象持有的
  10.     public class Inner {
  11.         // 成员变量
  12.         private String name;
  13.         // 构造器
  14.         public Inner() {
  15.             System.out.println("Inner() name = " + name);
  16.         }
  17.         // 有参构造器
  18.         public Inner(String name) {
  19.             this.name = name;
  20.             System.out.println("Inner(String name)");
  21.         }
  22.         // 成员方法
  23.         public void show() {
  24.             System.out.println("show()");
  25.             // 成员内部类中可以直接访问外部类的静态成员
  26.             System.out.println(schoolName);
  27.             test();
  28.             // 也可以直接访问外部类的实例成员(非静态成员变量,成员方法)
  29.             System.out.println(age);
  30.             run();
  31.             System.out.println(this); // 自己的对象
  32.             System.out.println(Outer.this); // 寄身外部类的对象
  33.         }
  34.         // get方法
  35.         public String getName() {
  36.             return name;
  37.         }
  38.         // set方法
  39.         public void setName(String name) {
  40.             this.name = name;
  41.         }
  42.     }
  43. }
复制代码

  • 成员内部类访问外部类成员的特点(拓展知识):
    1、成员内部类中可以直接访问外部类的静态成员,也可以直接访问外部类的实例成员;
    2、成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象:外部类名.this;
  1. public class InnerClassDemo1 {
  2.     public static void main(String[] args) {
  3.         // 目标:搞清楚成员内部类的语法。
  4.         // 成员内部类创建对象的格式:
  5.         // 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
  6.         Outer.Inner oi = new Outer().new Inner();  // 创建成员内部类
  7.         oi.setName("小明");
  8.         oi.show();
  9.         System.out.println(oi.getName());
  10.         // 成员内部类访问外部类成员的特点(拓展知识):
  11.         System.out.println("============");
  12.         People.Heart h = new People().new Heart();
  13.         h.show();
  14.     }
  15. }
  16. class People{
  17.     private int heatBeat = 100;
  18.     public class Heart{
  19.         private int heartBeat = 80;
  20.         public void show(){
  21.             int heartBeat = 200;
  22.             System.out.println(heartBeat);  // 200
  23.             System.out.println(this.heartBeat);  // 80
  24.             System.out.println(People.this.heatBeat);  // 100
  25.         }
  26.     }
  27. }
复制代码

  • 2、静态内部类:
    有static修饰的内部类,属于外部类自己持有。
  1. public class Outer{
  2.    // 静态内部类
  3.    public static class Inner{}
  4. }
  5. // 外部类名.内部类名 对象名 = new 外部类.内部类();
  6. // Outer.Inner in = new Outer.Inner(); // 创建静态内部类对象
复制代码
1、静态内部类中可以直接访问外部类的静态成员;
2、静态内部类中不可以直接访问外部类的实例成员;
  1. public class InnerClassDemo2 {
  2.     public static void main(String[] args) {
  3.         // 目标:搞清楚静态内部类的语法。
  4.         // 创建对象:外部类名.内部类名 对象名 = new 外部类名.内部类名();
  5.         Outer.Inner oi = new Outer.Inner();
  6.         // 1、静态内部类中可以直接访问外部类的静态成员;
  7.         // 2、静态内部类中不可以直接访问外部类的实例成员;
  8.     }
  9. }
  10. public class Outer {
  11.     public static String schoolName;
  12.     private int age;
  13.     // 静态内部类:属于外部类本身持有
  14.     public static class Inner{
  15.         private String name;
  16.         public void show(){
  17.             // 静态类中可以直接访问外部类的静态成员
  18.             System.out.println(schoolName);
  19.             // 静态类中不可以直接访问外部类的实例成员
  20. //            System.out.println(age);  // 报错
  21.         }
  22.         public String getName() {
  23.             return name;
  24.         }
  25.         public void setName(String name) {
  26.             this.name = name;
  27.         }
  28.     }
  29. }
复制代码

  • 3、局部内部类:(了解)——鸡肋语法
    局部内部类是定义在方法中、代码块中、构造器等执行体中。
    局部内部类是为匿名内部类做铺垫的,没啥用。
  1. public class InnerClassDemo3 {
  2.     public static void main(String[] args) {
  3.     }
  4.     public static void go(){
  5.         // 定义在方法中的局部内部类
  6.         class A{}
  7.         abstract class B{}
  8.         interface C{}
  9.     }
  10. }
复制代码

  • 4、匿名内部类:
    认识:是一种特殊的局部内部类。
    所谓匿名:指的是程序员不需要为这个类声明名字,默认有个隐藏的名字。
    ——本质上是Animal的一个子类,可以理解为一个猫类或者是一个狗类。同时立马还是一个子类对象,可以理解为一个猫对象或者一个狗对象。
  1. //(先有一个已经存在的类或者接口,参数值通常不写)
  2. new 类或者接口(参数值...){
  3.        类体(一般是方法重写);
  4. };
  5. new Animal (){
  6.        @Override
  7.         public void cry(){
  8.         }
  9. }  
复制代码

  • 特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
    作用:用于更方便的创建一个子类对象。
    匿名内部类实际上是有名字的:外部类名.$编号.class
  • 常见使用形式:(语法)
    通常作为一个对象参数传输给方法;
  • 应用场景:
    调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用。
  1. interface Swim{
  2.     void swimming(); // 游泳方法
  3. }
  4. public class Test2 {
  5.     public static void main(String[] args) {
  6.         // 目标:搞清楚匿名内部类的使用形式(语法):通常可以作为一个对象参数传输给方法使用。
  7.         // 需求:学生、老师要参加游泳比赛
  8.         Swim s1 = new Swim() {
  9.             @Override
  10.             public void swimming() {
  11.                 System.out.println("学生蛙泳式游泳");
  12.             }
  13.         };
  14.         start(s1);  // 对象回调
  15.         System.out.println("=======================");
  16.         start(new Swim() {
  17.             @Override
  18.             public void swimming() {
  19.                 System.out.println("老师狗爬式游泳");
  20.             }
  21.         });
  22.     }
  23.     public static void start(Swim s){
  24.         System.out.println("开始游泳……");
  25.         s.swimming();
  26.         System.out.println("游泳结束……");
  27.     }
  28. }
复制代码
  1. 运行结果:
  2. 开始游泳……
  3. 学生蛙泳式游泳
  4. 游泳结束……
  5. =======================
  6. 开始游泳……
  7. 老师狗爬式游泳
  8. 游泳结束……
复制代码
3.函数式编程


  • 函数式编程:java从JDK8开始新增的一种特性
    主要有Lambda表达式,方法引用,Stream流……等
  • 什么是函数式编程?
    此函数类似于数学中的函数(强调做什么),只要输入数据一致返回的结果也是一致的。
    数学中的函数示例:2x+1
    java中的函数(Lambda表达式):(x)-> 2x+1
  • 函数式编程解决了什么问题?
    使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。
3.1.Lambda表达式


  • 1、Lambda表达式:JDK8开始新增的一种语法形式,它表示函数。
    Lambda表达式提供了一种简洁的方式来表示匿名方法(即没有名称的方法),这些方法可以作为参数传递给其他方法或者存储在变量中。
  1. (被重写方法的形参列表) -> {
  2.        被重写方法的方法体代码。
  3. }
复制代码
  1. public class LambdaDemo1 {
  2.     public static void main(String[] args) {
  3.         // 目标:认识Lambda表达式:搞清楚其基本作用。
  4.         // 1、这个是方法重写
  5.         Animal a = new Animal() {
  6.             @Override
  7.             public void cry() {
  8.                 System.out.println("猫是喵喵喵~~~~");
  9.             }
  10.         };
  11.         a.cry();
  12.         // 2、错误示范:Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
  13. //        Animal a1 = () ->{
  14. //            System.out.println("猫是喵喵喵~~~~");
  15. //        };
  16. //        a1.cry();
  17.        /* // 3、方法重写,但是可以写成Lambda简化形式
  18.                Swim s1 = new Swim() {
  19.             @Override
  20.             public void swimming() {
  21.                 System.out.println("学生游泳贼快~~~");
  22.             }
  23.         };*/
  24.         // 4、这个是Lambda表达式简化这个匿名方法
  25.         Swim s1 = () ->{
  26.             System.out.println("学生游泳贼快~~~");
  27.         };
  28.         s1.swimming();
  29.     }
  30. }
  31. // 抽象类中只含有一个抽象方法
  32. abstract class Animal{
  33.     public abstract void cry();
  34. }
  35. // 函数式接口:只有一个抽象方法的接口。
  36. @FunctionalInterface  // 声明函数式接口的注解
  37. interface Swim{
  38.     void swimming();
  39. //    void swimming2(); // 报错
  40. }
复制代码

  • Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
  • lambda实战实例,省略规则(可以参考符合函数式接口规范的接口类型)
    Lambda简化comparator,Runnable,Callable 接口的匿名内部类
    作用:进一步简化Lambda表达式的写法
  • lambda表达式省略具体规则:

    • 参数类型全部可以省略不写;
    • 如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()” ;
    • 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略“;”,
    • 如果这行代码是return语句,也必须去掉return。

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Student {
  5.     // 姓名 年龄 身高 性别
  6.     private String name;
  7.     private int age;
  8.     private double height;
  9.     private char sex;
  10. }
  11. public class LambdaDemo2 {
  12.     public static void main(String[] args) {
  13.         // 目标:Lambda表达式简化实际示例
  14.         test1();
  15.         test2();
  16.     }
  17.     public static void test1(){
  18.         Student[] stus = new Student[6];
  19.         stus[0] = new Student("殷素素", 35, 171.5, '女');
  20.         stus[1] = new Student("赵敏", 18, 168.5, '女');
  21.         stus[4] = new Student("金毛狮王", 35, 181, '男');
  22.         stus[2] = new Student("周芷若", 18, 172.5, '女');
  23.         stus[3] = new Student("张无忌", 25, 170.5, '男');
  24.         stus[5] = new Student("小昭", 19, 168.5, '女');
  25.         // 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
  26.         // 1、方法重写
  27.         /*Arrays.sort(stus, new Comparator<Student>() {
  28.             @Override
  29.             public int compare(Student o1, Student o2) {
  30.                 return o1.getAge() - o2.getAge();  // 按照年龄的升序!
  31.             }
  32.         });*/
  33.         // 2、方法重写可以写成Lambda表达式
  34. //        Arrays.sort(stus, (Student o1, Student o2) -> {
  35. //            return o1.getAge() - o2.getAge();  // 按照年龄的升序!
  36. //        });
  37.         
  38.         // 3、Lambda表达式可以进一步省略
  39.         Arrays.sort(stus, (o1, o2) -> o1.getAge() - o2.getAge() );
  40.         // 遍历数组中的学生对象并输出
  41.         for (int i = 0; i < stus.length; i++) {
  42.             Student s = stus[i];
  43.             System.out.println(s);
  44.         }
  45.     }
  46.        
  47.     // 一个登录窗口
  48.     public static void test2(){
  49.         JFrame win = new JFrame("登录窗口");
  50.         win.setSize(300, 200);  // 窗口大小
  51.         win.setLocationRelativeTo(null);  // 居中显示
  52.         win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 点击关闭按钮,程序退出
  53.         JPanel panel = new JPanel();  // 添加一个桌布(面板),可以自适应大小
  54.         win.add(panel);  // 添加到窗口中
  55.         JButton btn = new JButton("登录");  // 登录按钮
  56.         panel.add(btn);  // 添加到面板中
  57.         // java要求必须给这个按钮添加一个点击事件的监听器对象,这样就可以监听用户的点击操作,就可以做出反应
  58.         // 开发中不是我们要主动去写匿名内部类,而是用别人的功能的时候,别人可以让我们写一个匿名内部类吗,我们才会写
  59.         /*btn.addActionListener(new ActionListener() {
  60.             @Override
  61.             public void actionPerformed(ActionEvent e) {
  62.                 System.out.println("登录成功!!!");
  63.             }
  64.         });*/
  65.         
  66.         // Lambda表达式的简化的使用例子
  67.         btn.addActionListener(e -> System.out.println("登录成功!!!") );
  68.         
  69.         win.setVisible(true);  // 显示窗口
  70.     }
  71. }
复制代码
3.2.函数式接口


  • 什么是函数式接口?

    • 有且仅有一个抽象方法的接口。接口中只有一个抽象方法(可以有多个默认方法或静态方法)。
    • 可以加上 @FunctionalInterface 注解(非强制,但建议加上)。

  • 函数式接口可以通过Lambda表达式、方法引用或构造器引用来实例化。
    @FunctionalInterface 注解,用于声明一个接口为函数式接口。
  • 符合函数式接口规范的接口类型有:

    • Runnable
    • Callable
    • Comparator
    • 自定义的函数式接口
    • Java 提供的内置函数式接口(如 Function, Predicate, Consumer 等)

3.3.方法引用


  • 方法引用:本质上是简化Lambda表达式,当你要传递的方法已经存在时,可以使用方法引用来直接引用已有的方法,而不是通过 Lambda 表达式重新定义。
  • 方法引用(Method Reference)在使用时必须满足“参数一致性”要求,也就是说:
    方法引用的目标方法的参数列表和返回类型,必须与函数式接口中抽象方法的参数列表和返回类型兼容。
  • 方法引用包括:

    • 静态方法引用
    • 实例方法引用
    • 特定类型方法引用
    • 构造器引用。

  • 静态方法引用
    类名::静态方法
    使用场景:如果某个Lambda表达式只是调用一个静态方法,并且“->”前后参数的形式一致,就可以使用静态方法引用。
  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Student {
  5.     // 姓名 年龄 身高 性别
  6.     private String name;
  7.     private int age;
  8.     private double height;
  9.     private char sex;
  10.     // 静态方法:按照年龄比较:升序排序
  11.     public static int compareByAge(Student o1, Student o2) {
  12.         return o1.getAge() - o2.getAge();
  13.     }
  14.     // 实例方法:按照身高比较:升序排序
  15.     public int compareByHeight(Student o1, Student o2) {
  16.         return Double.compare(o1.getHeight(), o2.getHeight());
  17.     }
  18. }
  19. public class Test1 {
  20.     public static void main(String[] args) {
  21.         // 目标:静态方法引用:演示一个场景。
  22.         test();
  23.     }
  24.     public static void test(){
  25.         Student[] stus = new Student[6];
  26.         stus[0] = new Student("殷素素", 35, 171.5, '女');
  27.         stus[1] = new Student("赵敏", 18, 168.5, '女');
  28.         stus[4] = new Student("金毛狮王", 35, 181, '男');
  29.         stus[2] = new Student("周芷若", 18, 172.5, '女');
  30.         stus[3] = new Student("张无忌", 25, 170.5, '男');
  31.         stus[5] = new Student("小昭", 19, 168.5, '女');
  32.         // 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
  33. //        Arrays.sort(stus, (o1, o2) -> o1.getAge() - o2.getAge() );
  34. //        Arrays.sort(stus, (o1, o2) -> Student.compareByAge(o1, o2) );
  35.         // Lambda表达式简化:方法引用 -> 静态方法引用
  36.         Arrays.sort(stus, Student::compareByAge);
  37.         // 遍历数组中的学生对象并输出
  38.         for (int i = 0; i < stus.length; i++) {
  39.             Student s = stus[i];
  40.             System.out.println(s);
  41.         }
  42.     }
  43. }
复制代码

  • 实例方法引用:
    对象名::实例方法
    使用场景:如果某个Lambda表达式只是通过对象名称调用一个实例方法,并且“->”前后参数的形式一致,就可以使用实例方法引用。
  1. public class Test2 {
  2.     public static void main(String[] args) {
  3.         // 目标:实例方法引用
  4.         test();
  5.     }
  6.     public static void test(){
  7.         Student[] stus = new Student[6];
  8.         stus[0] = new Student("殷素素", 35, 171.5, '女');
  9.         stus[1] = new Student("赵敏", 18, 168.5, '女');
  10.         stus[4] = new Student("金毛狮王", 35, 181, '男');
  11.         stus[2] = new Student("周芷若", 18, 172.5, '女');
  12.         stus[3] = new Student("张无忌", 25, 170.5, '男');
  13.         stus[5] = new Student("小昭", 19, 168.5, '女');
  14.         // 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
  15.         // 实例方法引用要先创建对象,才能引用
  16.         Student t = new Student();
  17. //        Arrays.sort(stus, (o1, o2) -> t.compareByHeight(o1, o2) );
  18.         // 实例方法引用: 对象名::实例方法
  19.         Arrays.sort(stus, t::compareByHeight);
  20.         // 遍历数组中的学生对象并输出
  21.         for (int i = 0; i < stus.length; i++) {
  22.             Student s = stus[i];
  23.             System.out.println(s);
  24.         }
  25.     }
  26. }
复制代码

  • 特定类型方法的引用:
    特定类的名称::方法
    使用场景:如果某个Lambda表达式只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。
  1. public class Test3 {
  2.     public static void main(String[] args) {
  3.         // 目标:特定类型的方法引用
  4.         // 需求:有一个字符串数组,里面有一些人的名字,都是英文名字,请按照名字的首字母升序排序。
  5.         String[] names = {"Tom", "Jerry", "曹操","Mike","Angela", "Jack", "Rose", "Lucy", "Andy", "Bobi","caocao"};
  6.         // 把这个数组进行排序:Arrays.sort(names,Comparator)
  7.         Arrays.sort(names);  // 默认就是按照首字母的编号升序排序
  8.         // 要求:忽略首字母的大小进行升序排序(java官方默认是搞不定的,需要我们自己指定比较规则)
  9.         /*
  10.         Arrays.sort(names, new Comparator<String>() {
  11.             @Override
  12.             public int compare(String o1, String o2) {
  13.                 // o1 Angela
  14.                 // o2 Andy
  15.                 return o1.compareToIgnoreCase(o2);   // o1 > o2 返回正数,o1 < o2 返回负数,o1 == o2 返回0
  16.                 // java已经为我们提供了字符串按照首字母忽略大小写比较的方法:compareToIgnoreCase()
  17.             }
  18.         });*/
  19.         // 调用字符串类型的实例方法——特定类型的实例方法
  20. //        Arrays.sort(names, (o1, o2) -> o1.compareToIgnoreCase(o2) );
  21.         
  22.         // 调用字符串类型的静态方法——特定类型的静态方法  类型名称::方法
  23.         Arrays.sort(names, String::compareToIgnoreCase);
  24.         System.out.println(Arrays.toString(names));
  25.     }
  26. }
复制代码

  • 构造器引用:
    类名::new
    使用场景:如果某个Lambda表达式只是在创建对象,并且“->”前后参数的形式一致,就可以使用构造器引用。
  1. // 函数式接口
  2. @FunctionalInterface
  3. interface CarFactory {
  4.     Car create(String name);  // 根据名字name 创建一个Car对象返回
  5. }
  6. @Data
  7. @AllArgsConstructor
  8. @NoArgsConstructor
  9. class Car{
  10.     private String name;
  11. }
  12. public class Test4 {
  13.     public static void main(String[] args) {
  14.         // 目标:理解构造器引用
  15.         // 创建了接口的匿名内部类对象
  16.         /*CarFactory cf = new CarFactory() {
  17.             @Override
  18.             public Car create(String name) {
  19.                 return new Car(name);
  20.             }
  21.         };*/
  22.         // 匿名内部类简化:Lambda表达式 -> Lambda表达式省略
  23. //        CarFactory cf = name -> new Car(name) ;
  24.         // Lambda表达式简化:方法引用 -> 构造器引用
  25.         CarFactory cf = Car::new; ;
  26.         Car c1 = cf.create("奔驰");
  27.         System.out.println(c1);
  28.     }
  29. }
复制代码
4.常用API

4.1.String


  • 常用API接口:String
  • String是什么,有什么用?
    String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。
  • String创建字符串对象的方式:
    1、创建字符串对象,封装字符串数据
    2、调用String提供的操作字符串数据的方法。
  • String创建对象的区别:
    只要是以“”方式写出的字符串对象,会存储到字符串常量池(堆内存中有块区域叫常量池),且相同内容的字符串只存储一份;
    通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。
  1. public class StringDemo1 {
  2.     public static void main(String[] args) {
  3.         // 目标:创建字符串对象,封装要处理的字符串数据,调用String踢动的方法处理字符串
  4.         // 1.推荐方式一:直接“”就可以创建字符串对象,封装字符串数据。
  5.         String s1 = "hello 黑马";
  6.         System.out.println(s1);
  7.         System.out.println(s1.length());  // 处理字符串的方法
  8.         // 2.方式二:通过构造器初始化对象
  9.         String s2 = new String();  // 等价于 ""
  10.         System.out.println(s2); // 空字符串
  11.         String s3 = new String("hello java");
  12.         System.out.println(s3);
  13.         char [] chars = {'h', 'e', 'l', 'l', ' ', 'o', '赵', '子', '龙'};
  14.         String s4 = new String(chars);
  15.         System.out.println(s4);
  16.         byte [] bytes = {97, 98, 99, 68, 65, 66};
  17.         String s5 = new String(bytes);
  18.         System.out.println(s5);
  19.         System.out.println("============================");
  20.         String t1 = "abc";
  21.         String t2 = "abc";
  22.         System.out.println(t1 == t2);
  23.         String t3 = new String("abc");
  24.         String t4 = new String("abc");
  25.         System.out.println(t3 == t4);
  26.         System.out.println("============================");
  27.         // 调用字符串的方法,处理字符串数据。
  28.         // 简易版的登录:
  29.         String okLoginName = "admin";
  30.         System.out.println("请输入您的登录名称:");
  31.         Scanner sc = new Scanner(System.in);
  32.         String loginName = sc.next();
  33.         // loginName == okLoginName 默认比较的是地址
  34.         // 判断字符串内容,建议用String提供的equals方法,只关心内容一样,就返回true,不关心地址
  35.         if (loginName.equals(okLoginName)) {
  36.             System.out.println("登录成功!");
  37.         } else {
  38.             System.out.println("登录失败!");
  39.         }
  40.         System.out.println("============================");
  41.         // 18663666520 ===> 从0开始
  42.         // 0 1 2 3 4 5 6 7 8 9 10
  43.         System.out.println("请您用手机号码登录:");
  44.         String phone = sc.next();
  45.         System.out.println("系统显示以下手机号码进入:");
  46.         String newPhone = phone.substring(0, 3) + "****" + phone.substring(7);
  47.         // 包前不包后,012,    8-
  48.         System.out.println(newPhone);
  49.     }
  50. }
复制代码

  • String提供的常用方法:
    1.png

4.2.ArrayList集合


  • ArrayList:归属于集合,是泛型类,可以约束存储的数据类型。
  • 什么是集合?
    集合是一种容器,用来装数据的,类似于数组。
  • 有数组,为什么还需要学习集合?
    数组定义完成并启动后,长度就固定了;
    集合大小可变,功能丰富,开发中用的更多。
  • 集合的种类很多:Set,Map,ArrayList……
  • ArrayList集合学什么?
    1、创建ArrayList对象,代表一个集合容器
    2、调用ArrayList提供的方法,对容器中的数据进行增删改查操作。
  1. public class ArrayListDemo1 {
  2.     public static void main(String[] args) {
  3.         // 目标:掌握ArrayList集合的基本使用。
  4.         // 创建ArrayList对象,代表一个集合容器
  5. //        ArrayList list = new ArrayList();
  6.         // <String>:代表泛型,只能放String类型数据
  7.         ArrayList<String> list = new ArrayList<>();   // 泛型定义集合
  8.         // 添加数据
  9.         list.add("java");
  10.         list.add("mysql");
  11.         list.add("html");
  12.         list.add("赵敏");
  13.         System.out.println(list);
  14.         // 查看数据
  15.         System.out.println(list.get(0));
  16.         System.out.println(list.get(1));
  17.         System.out.println(list.get(2));
  18.         System.out.println(list.get(3));
  19.         System.out.println("======================");
  20.         // 遍历集合
  21.         for (int i = 0; i < list.size(); i++) {
  22.             // i 0 1 2 3
  23.             System.out.println(list.get(i));
  24.         }
  25.         System.out.println("======================");
  26.         // 删除数据
  27.         System.out.println(list.remove(0));  // 根据索引删除数据
  28.         System.out.println(list);
  29.         System.out.println(list.remove("赵敏"));  // 根据元素删除数据
  30.         System.out.println(list);
  31.         System.out.println("======================");
  32.         // 修改数据
  33.         list.set(0, "javaee");
  34.         System.out.println(list);
  35.     }
  36. }
复制代码
5.GUI编程


  • GUI编程:GUI(Graphical User Interface ,图形用户界面),是桌面的界面技术,不常用——是为了提高趣味性。
    通过图形元素(如窗口、按钮、文本框等)与用户进行交互;
    与命令行界面(CLI)相比,GUI更加直观,友好。
  • 为什么学习GUI编程?
    增强用户体验;
    广泛应用于桌面应用程序开发
    java提供了强大的GUI编程支持
  • java的GUI编程包
    AWT(Abstract Window Toolkit,抽象窗口工具集)提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统;
    Swing(用这个,不用AWT)基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统。
  • 常用的Swing组件:(前面不加J就是AWT组件)
    JFrame:窗口
    JPanel:用于组织其他组件的容器
    JButton:按钮组件
    JTextField:输入框
    JTable:表格
  • 布局管理器(Layout Manager)它们可以决定组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。
  • 常见的布局管理器:
    FlowLayout:水平布局/垂直布局
    BorderLayout:方向布局
    GridLayout:网格布局
    BoxLayout:盒子布局
  • GUI编程:事件处理
    GUI编程中,事件的处理是通过事件监听器(Event Listener)来完成的。
  • 常用的事件监听器对象:
    点击事件监听器 ActionListener
    按键事件监听器 KeyListener
    鼠标行为监听器 MouseListener
    ……
  • 事件的几种常见写法:
    1、直接提供实现类,用于创建事件监听对象;
    2、直接使用匿名内部类的对象,代表事件监听对象
    3、自定义窗口,让窗口对象实现事件接口。
  1. import javax.swing.*;
  2. import java.awt.*;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. public class LoginScreen extends JFrame {
  6.     private JTextField usernameField;
  7.     private JPasswordField passwordField;
  8.     private JButton loginButton;
  9.     private JLabel errorLabel;
  10.     public LoginScreen() {
  11.         // 设置窗口标题
  12.         setTitle("Login Screen");
  13.         setSize(400, 300);
  14.         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  15.         setLocationRelativeTo(null); // 居中显示
  16.         // 创建面板并设置布局
  17.         JPanel panel = new JPanel();
  18.         panel.setLayout(new GridBagLayout());
  19.         GridBagConstraints gbc = new GridBagConstraints();
  20.         // 标题
  21.         JLabel titleLabel = new JLabel("Welcome Back!");
  22.         titleLabel.setFont(new Font("Serif", Font.BOLD, 24));
  23.         gbc.gridx = 0;
  24.         gbc.gridy = 0;
  25.         gbc.gridwidth = 2;
  26.         gbc.insets = new Insets(10, 0, 20, 0); // 上下左右边距
  27.         panel.add(titleLabel, gbc);
  28.         // 用户名标签和输入框
  29.         JLabel usernameLabel = new JLabel("Username:");
  30.         usernameField = new JTextField(15);
  31.         gbc.gridx = 0;
  32.         gbc.gridy = 1;
  33.         gbc.gridwidth = 1;
  34.         gbc.insets = new Insets(10, 0, 10, 10); // 左侧留出空间
  35.         panel.add(usernameLabel, gbc);
  36.         gbc.gridx = 1;
  37.         gbc.gridy = 1;
  38.         gbc.insets = new Insets(10, 0, 10, 0);
  39.         panel.add(usernameField, gbc);
  40.         // 密码标签和输入框
  41.         JLabel passwordLabel = new JLabel("Password:");
  42.         passwordField = new JPasswordField(15);
  43.         gbc.gridx = 0;
  44.         gbc.gridy = 2;
  45.         gbc.insets = new Insets(10, 0, 10, 10);
  46.         panel.add(passwordLabel, gbc);
  47.         gbc.gridx = 1;
  48.         gbc.gridy = 2;
  49.         gbc.insets = new Insets(10, 0, 10, 0);
  50.         panel.add(passwordField, gbc);
  51.         // 登录按钮
  52.         loginButton = new JButton("Login");
  53.         loginButton.setBackground(new Color(76, 175, 80)); // 设置按钮颜色为绿色
  54.         loginButton.setForeground(Color.WHITE); // 文字颜色为白色
  55.         loginButton.setFocusPainted(false); // 去除焦点边框
  56.         loginButton.addActionListener(new ActionListener() {
  57.             @Override
  58.             public void actionPerformed(ActionEvent e) {
  59.                 authenticate();
  60.             }
  61.         });
  62.         gbc.gridx = 0;
  63.         gbc.gridy = 3;
  64.         gbc.gridwidth = 2;
  65.         gbc.insets = new Insets(20, 0, 10, 0);
  66.         panel.add(loginButton, gbc);
  67.         // 错误信息标签
  68.         errorLabel = new JLabel("", SwingConstants.CENTER);
  69.         errorLabel.setForeground(Color.RED);
  70.         gbc.gridx = 0;
  71.         gbc.gridy = 4;
  72.         gbc.gridwidth = 2;
  73.         panel.add(errorLabel, gbc);
  74.         add(panel);
  75.         setVisible(true);
  76.     }
  77.     private void authenticate() {
  78.         String username = usernameField.getText();
  79.         String password = new String(passwordField.getPassword());
  80.         if ("admin".equals(username) && "password".equals(password)) {
  81.             JOptionPane.showMessageDialog(this, "Login successful!", "Success", JOptionPane.INFORMATION_MESSAGE);
  82.         } else {
  83.             errorLabel.setText("Invalid username or password.");
  84.         }
  85.     }
  86.     public static void main(String[] args) {
  87.         SwingUtilities.invokeLater(LoginScreen::new);
  88.     }
  89. }
复制代码
6.关于返回数组的内容


  • 看数组内容:

    • 使用循环语句输出之外
    • java提供了Arrays.toString(数组名); ,可以返回数组的内容
      [A,2,3,……]

  • Arrays.sort(A,B)Array的排序算法:
[code]public static  void sort(T[] a, Comparator
您需要登录后才可以回帖 登录 | 立即注册