07 - 面向对象编程(高级部分四)

一、函数式编程

函数的理解

  • 此“函数”类似于数学中的函数(强调做什么),只要输入的数据一致,返回的结果也是一致的。

函数式编程解决了什么问题

  • 使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。

Lambda的认识

  • JDK 8 开始新增的一种语法形式,表示函数。
  • 可以用于替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。
  • Lambda表达式 只能替代“函数式接口”的匿名内部类!
  • 函数式接口:有且仅有一个抽象方法的接口。
// 语法形式
(被重写方法的形参列表) -> {
    被重写方法的方法体代码
}

案例一:

public class LambdaDemo {
  public static void main(String[] args){
    // 目标:理解Lambda表达式,如何使用
    // 使用匿名内部类创建对象重写 cry() 方法
    Animal a = new Animal() {
      @Override
      public void cry() {
        System.out.println("小猫叫");
      }
    };
    
    a.cry();

    // 使用Lambda表达式
    Swim s = () -> {
      System.out.println("蛙泳~");
    };
    
    s.swimming();
  }
}

// 动物的抽象类
abstract class Animal {
  publlic abstract void cry();
}

// 函数式接口
@FunctionalInterface // 声明函数式接口的注解,有且仅有一个抽象方法
interface Swim {
  void swimming();
}

案例二:

public class TestDemo{
  pulic static void main(String[] args) {
    Student[] students = new Student[3];
    students[0] = new Student("可乐", 16, 170.3);
    students[1] = new Student("雪碧", 13, 159.1);
    students[2] = new Student("芬达", 18, 168.4);
    
    // 使用匿名内部类重写Comparator比较器方法,实现根据学生的年龄进行排序
    // 使用Lambda简化comparator接口的匿名内部类
    Array.sort(students, (student o1, student o2) -> {
        return o1.getAge() - o2.getAge();
    });

    System.out.println(Array.toString(students));
  }
}

Lambda表达式的省略规则

  • 作用:用于进一步简化Lambda表达式的写法
  • 具体规则:
  • 参数类型全部可以省略不写。
  • 如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()”。
  • 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号“;”。
  • 如果这行代码是return语句,也必须去掉return。
// 参数类型全部可以省略不写。
Array.sort(students, (o1, o2) -> {
  return o1.getAge() - o2.getAge();
});

// 如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()”。
// 如果这行代码是return语句,也必须去掉return。
Array.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());

函数式编程 - 方法引用

  • 静态方法引用
    类名::静态方法
    使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且“->”前后的参数形式一致,就可以使用静态方法引用。
public class TestDemo{
  pulic static void main(String[] args) {
    // 静态方法引用 如何使用
    test();
  }
}


public static void test(){
  Student[] students = new Student[3];
  students[0] = new Student("可乐", 16, 170.3);
  students[1] = new Student("雪碧", 13, 159.1);
  students[2] = new Student("芬达", 18, 168.4);
    
  // 使用匿名内部类重写Comparator比较器方法,实现根据学生的年龄进行排序
  // 使用Lambda简化comparator接口的匿名内部类
  // Array.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());

  // Lambda表达式里只是调用一个静态方法,“->”前后的参数形式一致
  Array.sort(students, (o1, o2) -> Student.compareByAge(o1, o2));
  // 简化为以下代码
  Array.sort(students, Student::compareByAge);

  System.out.println(Array.toString(students));
}

// 学生类
class Student {
  private String name;
  private int age;

  // 静态方法
  public static void compareByAge(Student o1, Student o2) {
    return o1.getAge() - o2.getAge();
  }
}
  • 实例方法引用
    对象名::实例方法
    使用场景:如果某个Lambda表达式里只是通过对象调用一个实例方法,并且“->”前后的参数形式一致,就可以使用实例方法引用。
public class TestDemo{
  pulic static void main(String[] args) {
    // 实例方法引用 如何使用
    test();
  }
}

public static void test(){
  Student[] students = new Student[3];
  students[0] = new Student("可乐", 16, 170.3);
  students[1] = new Student("雪碧", 13, 159.1);
  students[2] = new Student("芬达", 18, 168.4);
    
  // 根据学生的身高进行排序
  Student t = new student();
  Array.sort(students, (o1, o2) -> t.compareByHeight(o1, o2));

  // Lambda表达式里通过对象调用一个实例方法,“->”前后的参数形式一致
  // 简化为以下代码
  Array.sort(students, t::compareByHeight);

  System.out.println(Array.toString(students));
}

// 学生类
class Student {
  private String name;
  private int age;
  private double height;

  // 静态方法
  public static void compareByAge(Student o1, Student o2) {
    return o1.getAge() - o2.getAge();
  }

  // 实例方法
  public int compareByHeight(Student o1, Student o2) {
    return Double.compare(o1.getHeight(), o2.getHeight());
  }
}
  • 特定类型的方法引用
    特定类型的名称::方法
    使用场景:如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,就可以使用特定类型的方法引用。
public class TestDemo{
  pulic static void main(String[] args) {
    // 目标:特定类的方法引用
    // 需求:生成一个字符串数组,每个字符串表示人名,按照名字首字母排序
    String[] names = {"Tom", "Jack", "Angela", "Rose", "Bruce", "andy"}
     
    // 对数组进行排序
    Arrays.sort(names); // 默认按照首字母编号升序排序
    
    // 要求忽略首字母大小进行排序
    Arrays.sort(names, new Comparator<String>() {
      @Override
      public int compare(String o1, String o2) {
        return o1.compareToIgnoreCase(o2);
      }
    });

    // 简化匿名内部类
    Arrays.sort(names, (o1, o2) -> o1.compareToIgnoreCase(o2));

    // Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参
    Arrays.sort(names, String::compareToIgnoreCase);
  }
}
  • 构造器引用
    类名::new
    使用场景:如果某个Lambda表达式里只是在创建对象,并且“->”前后参数保持一致,就可以使用构造器引用。
public class TestDemo{
  pulic static void main(String[] args) {
    // 目标:理解构造器引用
    // 创建匿名内部类对象
    CarFactory cf = new CarFactory(){
      @Override
      public Car getCar(String name){
        return new Car(name);
      }
    };

    // Lambda表达式简化匿名内部类
    CarFactory cf =  name -> new Car(name);

    // Lambda表达式里只是在创建对象,并且“->”前后参数保持一致
    CarFactory cf =  Car::new;

    Car c1 = cf.getCar("奥迪");
    System.out.println(c1);
  }
}

// 接口
interface CarFactory {
  Car getCar(String name);
}

// 汽车类
@Data
@AllArgsConstructor
@NoArgsConstructor
class Car {
  private String name;
}

二、常用API

常用API - String

  • String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。

流程:
1. 创建字符串对象,封装字符串数据
2. 调用String提供的操作字符串数据的方法

String创建字符串对象的方式

// 方式一:Java程序中的所有字符串文字(例如“abc”)都为此类的对象。
public class TestDemo{
  pulic static void main(String[] args) {
    // 目标:创建字符串对象,封装字符串数据,并调用String提供的操作字符串数据的方法
    String s1 = "Hello,World";
    System.out.println(s1);
    
    // 计算字符串长度
    System.out.println(s1.length());
  }
}

// 方式二:调用String类的构造器初始化字符串对象。
public class TestDemo{
  pulic static void main(String[] args) {
    // 目标:创建字符串对象,封装字符串数据,并调用String提供的操作字符串数据的方法
    String s2 = new String();
    System.out.println(s2); // "" 空字符串

    String s3 = new String("Hello,World");
    System.out.println(s3);

    char[] chars = {'H', 'e', 'l', 'l', 'o'}
    String s4 = new String(chars);
    System.out.println(s4);

    byte[] bytes = {97, 98, 99, 65, 66}
    String s5 = new String(bytes);
    System.out.println(s5); // abcAB
  }
}

注意事项:

以 "..." 方式创建的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份。

通过 new 方式创建的字符串对象,每 new 一次都会产生一个新的对象放在堆里。

常用API - ArrayList

  • ArrayList是一种集合,集合是容器,用来装数据,类似于数组。
  • 数组定义完成并创建后,长度是固定的。
  • 集合大小可变,功能丰富,开发中用的更频繁。

流程:
1. 创建ArrayList对象,代表一个集合容器
2. 调用ArrayList提供的方法,对容器中的数据进行增删改查操作

public class TestDemo{
  pulic static void main(String[] args) {
    // 目标:创建ArrayList对象,代表一个集合容器,调用ArrayList提供的方法
    ArrayList<String> list = new ArrayList<>();
    
    // 添加数据
    list.add("java");
    list.add("golang");
    list.add("python");
  
    // 遍历集合
    for(int i = 0; i < list.size(); i++) {
      String s = list.get(i);
      System.out.println(s);
    }

    // 删除数据
    // 根据索引
    list.remove(2);
    // 根据内容
    list.remove("golang");

    // 修改数据
    list.set(0, "C++");
  }
}

三、GUI界面编程

GUI,全称 Graphical User Interface,指图形用户界面。

  • 通过图形元素(如窗口、按钮、文本框等)与用户进行交互
  • 与命令行界面(CLI)相比,GUI更直观、友好
  • 增强用户体验,应用于桌面应用程序开发,Java提供GUI编程支持

Java的GUI编程包

  • AWT(Abstract Window Toolkit)
    提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统

  • Swing
    基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统

常用的Swing组件
JFrame:窗口
JPanel:用于组织其他组件的容器
JButton:按钮组件
JTextField:输入框
JTable:表格

posted @ 2025-07-16 17:25  SpockC  阅读(9)  评论(0)    收藏  举报