凋零 發表於 2025-6-23 18:18:00

JavaSE-08面向对象高级二

<h1 id="javase-08面向对象高级二"><strong>JavaSE-08面向对象高级二</strong></h1>
<ul>
<li>[ 任务列表 ]</li>
<li>1.代码块</li>
<li>2.内部类</li>
<li>3.函数式编程</li>
<li>3.1.Lambda表达式</li>
<li>3.2.函数式接口</li>
<li>3.3.方法引用</li>
<li>4.常用API</li>
<li>4.1.String</li>
<li>4.2.ArrayList集合</li>
<li>5.GUI编程</li>
<li>6.其他</li>
</ul>
<hr>
<h2 id="1代码块"><span id="target-1"><strong>1.代码块</strong></span></h2>
<ul>
<li>
<p>类中的五大成分:成员变量、构造器、成员方法、代码块、内部类。</p>
</li>
<li>
<p>JDK8开始,新增的代码编程:函数式编程。</p>
</li>
<li>
<p>代码块:是类的五大成分之一。</p>
</li>
<li>
<p>代码块分为两种:<br>
① 静态代码块<br>
格式:<code>static{ }</code>——属于类<br>
特点:类加载时自动执行,由于类只加载一次,所以静态代码块也只会执行一次。<br>
作用:完成类的静态资源数据初始化。静态代码块中的代码实际上是在<strong>方法区</strong>(Method Area)执行的。<br>
例如:对静态变量的初始化赋值。例如类的静态数组变量定义之后,可以在静态代码块中初始化。(比在main中初始化更加优雅,是最佳实践)<br>
② 实例代码块:<br>
格式:<code>{ }</code> ——属于对象<br>
特点:每次创建对象时,执行实例代码块,并在构造器前执行。与构造器一样,实例初始化代码块也是在<strong>堆</strong>上执行的,因为它涉及到对实例成员的初始化。<br>
作用:和构造器一样,都是用来完成对象实例资源的初始化的。例如:对实例变量进行初始化赋值。</p>
</li>
</ul>
<pre><code class="language-java">public class CodeDemo1 {
    public static String schoolName;
    public static String [] cards = new String; // 静态数组
    // 静态代码块:有static修饰,属于类,与类一起优先加载,自动执行一次
    // 基本作用:可以完成对类的静态资源的初始化
    static{
      System.out.println("静态代码块执行了");// 先加载类,再执行main方法
      schoolName = "黑马程序员";
      cards = "A";
      cards = "2";
      cards = "3";
      cards = "4";
    }

    public static void main(String[] args) {
      // 目标:认识代码块,搞清楚代码块的基本作用。
      System.out.println("main方法执行了");
      System.out.println(schoolName);
      System.out.println(Arrays.toString(cards));// 返回数组内容观察
    }
}
</code></pre>
<pre><code class="language-txt">运行结果:
静态代码块执行了
main方法执行了
黑马程序员

</code></pre>
<pre><code class="language-java">public class Codedemo2 {
    private String name;
    private String [] direction = new String;// 实例变量
    // 实例代码块(构造代码块):无static修饰,属于对象,每次创建对象时,都会优先执行一次
    // 基本作用:初始化对象的实例资源
    {
      System.out.println("实例代码块执行了");
      name = "张三";
      direction = "N";
      direction = "S";
      direction = "W";
      direction = "E";
    }

    public static void main(String[] args) {
      // 目标:实例代码块
      System.out.println("main方法执行了");
      Codedemo2 A = new Codedemo2();
      new Codedemo2();
      new Codedemo2();
      System.out.println(A.name);
      System.out.println(Arrays.toString(A.direction));
    }
}
</code></pre>
<pre><code class="language-txt">运行结果:
main方法执行了
实例代码块执行了
实例代码块执行了
实例代码块执行了
张三

</code></pre>
<h2 id="2内部类"><span id="target-2"><strong>2.内部类</strong></span></h2>
<ul>
<li>内部类:指定义在另一个类内部的类,即在类的内部还有类存在。</li>
<li>场景:当一个类的内部,包含了一个完整的事物,且这个事物没必要单独设计时,就可以把这个事物设计成内部类。<br>
例如:汽车类内部可以定义一个完整的发动机类。</li>
<li>分类:
<ul>
<li>成员内部类</li>
<li>静态内部类</li>
<li>局部内部类</li>
<li>匿名内部类</li>
</ul>
</li>
<li>1、成员内部类:就是一个类是另一个类中的一个普通成员,类似前面我们学过的普通成员变量,成员方法。<br>
成员内部类:可以有成员变量,成员方法,构造器,getter和setter方法,可以创建对象,可以被继承,可以继承其他类……(类的对象可以干的它都可以干)。</li>
</ul>
<pre><code class="language-java">// 外部类
public class Outer {
    public static String schoolName = "heima程序员";
    public static void test(){
      System.out.println("test()");
    }
    private int age;
    public void run(){}

    // 成员内部类:无static修饰,属于外部类的对象持有的
    public class Inner {
      // 成员变量
      private String name;
      // 构造器
      public Inner() {
            System.out.println("Inner() name = " + name);
      }
      // 有参构造器
      public Inner(String name) {
            this.name = name;
            System.out.println("Inner(String name)");
      }
      // 成员方法
      public void show() {
            System.out.println("show()");
            // 成员内部类中可以直接访问外部类的静态成员
            System.out.println(schoolName);
            test();
            // 也可以直接访问外部类的实例成员(非静态成员变量,成员方法)
            System.out.println(age);
            run();
            System.out.println(this); // 自己的对象
            System.out.println(Outer.this); // 寄身外部类的对象
      }
      // get方法
      public String getName() {
            return name;
      }
      // set方法
      public void setName(String name) {
            this.name = name;
      }
    }
}
</code></pre>
<ul>
<li>成员内部类访问外部类成员的特点(拓展知识):<br>
1、成员内部类中可以直接访问外部类的静态成员,也可以直接访问外部类的实例成员;<br>
2、成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象:<code>外部类名.this</code>;</li>
</ul>
<pre><code class="language-Java">public class InnerClassDemo1 {
    public static void main(String[] args) {
      // 目标:搞清楚成员内部类的语法。
      // 成员内部类创建对象的格式:
      // 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
      Outer.Inner oi = new Outer().new Inner();// 创建成员内部类
      oi.setName("小明");
      oi.show();
      System.out.println(oi.getName());

      // 成员内部类访问外部类成员的特点(拓展知识):
      System.out.println("============");
      People.Heart h = new People().new Heart();
      h.show();
    }
}

class People{
    private int heatBeat = 100;

    public class Heart{
      private int heartBeat = 80;
      public void show(){
            int heartBeat = 200;
            System.out.println(heartBeat);// 200
            System.out.println(this.heartBeat);// 80
            System.out.println(People.this.heatBeat);// 100
      }
    }
}
</code></pre>
<ul>
<li>2、静态内部类:<br>
有static修饰的内部类,属于外部类自己持有。</li>
</ul>
<pre><code class="language-java">public class Outer{
   // 静态内部类
   public static class Inner{}
}
// 外部类名.内部类名 对象名 = new 外部类.内部类();
// Outer.Inner in = new Outer.Inner(); // 创建静态内部类对象
</code></pre>
<p>1、静态内部类中可以直接访问外部类的静态成员;<br>
2、静态内部类中不可以直接访问外部类的实例成员;</p>
<pre><code class="language-java">public class InnerClassDemo2 {
    public static void main(String[] args) {
      // 目标:搞清楚静态内部类的语法。
      // 创建对象:外部类名.内部类名 对象名 = new 外部类名.内部类名();
      Outer.Inner oi = new Outer.Inner();
      // 1、静态内部类中可以直接访问外部类的静态成员;
      // 2、静态内部类中不可以直接访问外部类的实例成员;
    }
}

public class Outer {
    public static String schoolName;
    private int age;

    // 静态内部类:属于外部类本身持有
    public static class Inner{
      private String name;
      public void show(){
            // 静态类中可以直接访问外部类的静态成员
            System.out.println(schoolName);
            // 静态类中不可以直接访问外部类的实例成员
//            System.out.println(age);// 报错
      }

      public String getName() {
            return name;
      }
      public void setName(String name) {
            this.name = name;
      }
    }
}
</code></pre>
<ul>
<li>3、局部内部类:(了解)——鸡肋语法<br>
局部内部类是定义在方法中、代码块中、构造器等执行体中。<br>
局部内部类是为匿名内部类做铺垫的,没啥用。</li>
</ul>
<pre><code class="language-java">public class InnerClassDemo3 {
    public static void main(String[] args) {

    }
    public static void go(){
      // 定义在方法中的局部内部类
      class A{}
      abstract class B{}
      interface C{}
    }
}
</code></pre>
<ul>
<li>4、匿名内部类:<br>
认识:是一种特殊的局部内部类。<br>
所谓匿名:指的是程序员不需要为这个类声明名字,默认有个隐藏的名字。<br>
——本质上是Animal的一个子类,可以理解为一个猫类或者是一个狗类。同时立马还是一个子类对象,可以理解为一个猫对象或者一个狗对象。</li>
</ul>
<pre><code class="language-java">//(先有一个已经存在的类或者接口,参数值通常不写)
new 类或者接口(参数值...){
       类体(一般是方法重写);
};

new Animal (){
       @Override
      public void cry(){
      }
}
</code></pre>
<ul>
<li>
<p>特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。<br>
作用:用于更方便的创建一个子类对象。<br>
匿名内部类实际上是有名字的:<code>外部类名.$编号.class</code></p>
</li>
<li>
<p>常见使用形式:(语法)<br>
通常作为一个对象参数传输给方法;</p>
</li>
<li>
<p>应用场景:<br>
调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用。</p>
</li>
</ul>
<pre><code class="language-java">interface Swim{
    void swimming(); // 游泳方法
}

public class Test2 {
    public static void main(String[] args) {
      // 目标:搞清楚匿名内部类的使用形式(语法):通常可以作为一个对象参数传输给方法使用。
      // 需求:学生、老师要参加游泳比赛
      Swim s1 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("学生蛙泳式游泳");
            }
      };
      start(s1);// 对象回调

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

      start(new Swim() {
            @Override
            public void swimming() {
                System.out.println("老师狗爬式游泳");
            }
      });


    }

    public static void start(Swim s){
      System.out.println("开始游泳……");
      s.swimming();
      System.out.println("游泳结束……");
    }
}
</code></pre>
<pre><code class="language-txt">运行结果:
开始游泳……
学生蛙泳式游泳
游泳结束……
=======================
开始游泳……
老师狗爬式游泳
游泳结束……
</code></pre>
<h2 id="3函数式编程"><span id="target-3"><strong>3.函数式编程</strong></span></h2>
<ul>
<li>函数式编程:java从JDK8开始新增的一种特性<br>
主要有Lambda表达式,方法引用,Stream流……等</li>
<li>什么是函数式编程?<br>
此函数类似于数学中的函数(强调做什么),只要输入数据一致返回的结果也是一致的。<br>
数学中的函数示例:2x+1<br>
java中的函数(Lambda表达式):<code>(x)-&gt; 2x+1</code></li>
<li>函数式编程解决了什么问题?<br>
使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。</li>
</ul>
<h3 id="31lambda表达式"><span id="target-3.1"><strong>3.1.Lambda表达式</strong></span></h3>
<ul>
<li>
<p>1、Lambda表达式:JDK8开始新增的一种语法形式,它表示函数。</p>
<p>Lambda表达式提供了一种简洁的方式来表示<strong>匿名方法</strong>(即没有名称的方法),这些方法可以作为参数传递给其他方法或者存储在变量中。</p>
</li>
</ul>
<pre><code class="language-java">(被重写方法的形参列表) -&gt; {
       被重写方法的方法体代码。
}
</code></pre>
<pre><code class="language-java">public class LambdaDemo1 {
    public static void main(String[] args) {
      // 目标:认识Lambda表达式:搞清楚其基本作用。
      // 1、这个是方法重写
      Animal a = new Animal() {
            @Override
            public void cry() {
                System.out.println("猫是喵喵喵~~~~");
            }
      };
      a.cry();

      // 2、错误示范:Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
//      Animal a1 = () -&gt;{
//            System.out.println("猫是喵喵喵~~~~");
//      };
//      a1.cry();

       /* // 3、方法重写,但是可以写成Lambda简化形式
               Swim s1 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("学生游泳贼快~~~");
            }
      };*/

      // 4、这个是Lambda表达式简化这个匿名方法
      Swim s1 = () -&gt;{
            System.out.println("学生游泳贼快~~~");
      };
      s1.swimming();
    }
}

// 抽象类中只含有一个抽象方法
abstract class Animal{
    public abstract void cry();
}

// 函数式接口:只有一个抽象方法的接口。
@FunctionalInterface// 声明函数式接口的注解
interface Swim{
    void swimming();
//    void swimming2(); // 报错
}
</code></pre>
<ul>
<li>
<p>Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。</p>
</li>
<li>
<p>lambda实战实例,省略规则(可以参考符合函数式接口规范的接口类型)<br>
Lambda简化comparator,Runnable,Callable 接口的匿名内部类<br>
作用:进一步简化Lambda表达式的写法</p>
</li>
<li>
<p>lambda表达式省略具体规则:</p>
<ul>
<li>参数类型全部可以省略不写;</li>
<li>如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()” ;</li>
<li>如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略“;”,</li>
<li>如果这行代码是return语句,也必须去掉return。</li>
</ul>
</li>
</ul>
<pre><code class="language-java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    // 姓名 年龄 身高 性别
    private String name;
    private int age;
    private double height;
    private char sex;
}

public class LambdaDemo2 {
    public static void main(String[] args) {
      // 目标:Lambda表达式简化实际示例
      test1();
      test2();
    }

    public static void test1(){
      Student[] stus = new Student;
      stus = new Student("殷素素", 35, 171.5, '女');
      stus = new Student("赵敏", 18, 168.5, '女');
      stus = new Student("金毛狮王", 35, 181, '男');
      stus = new Student("周芷若", 18, 172.5, '女');
      stus = new Student("张无忌", 25, 170.5, '男');
      stus = new Student("小昭", 19, 168.5, '女');

      // 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
      // 1、方法重写
      /*Arrays.sort(stus, new Comparator&lt;Student&gt;() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();// 按照年龄的升序!
            }
      });*/

      // 2、方法重写可以写成Lambda表达式
//      Arrays.sort(stus, (Student o1, Student o2) -&gt; {
//            return o1.getAge() - o2.getAge();// 按照年龄的升序!
//      });
      
      // 3、Lambda表达式可以进一步省略
      Arrays.sort(stus, (o1, o2) -&gt; o1.getAge() - o2.getAge() );

      // 遍历数组中的学生对象并输出
      for (int i = 0; i &lt; stus.length; i++) {
            Student s = stus;
            System.out.println(s);
      }
    }
       
    // 一个登录窗口
    public static void test2(){
      JFrame win = new JFrame("登录窗口");
      win.setSize(300, 200);// 窗口大小
      win.setLocationRelativeTo(null);// 居中显示
      win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 点击关闭按钮,程序退出

      JPanel panel = new JPanel();// 添加一个桌布(面板),可以自适应大小
      win.add(panel);// 添加到窗口中

      JButton btn = new JButton("登录");// 登录按钮
      panel.add(btn);// 添加到面板中
      // java要求必须给这个按钮添加一个点击事件的监听器对象,这样就可以监听用户的点击操作,就可以做出反应
      // 开发中不是我们要主动去写匿名内部类,而是用别人的功能的时候,别人可以让我们写一个匿名内部类吗,我们才会写

      /*btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("登录成功!!!");
            }
      });*/
      
      // Lambda表达式的简化的使用例子
      btn.addActionListener(e -&gt; System.out.println("登录成功!!!") );
      
      win.setVisible(true);// 显示窗口
    }
}
</code></pre>
<h3 id="32函数式接口"><span id="target-3.2"><strong>3.2.函数式接口</strong></span></h3>
<ul>
<li>
<p>什么是函数式接口?</p>
<ul>
<li>有且仅有一个抽象方法的接口。接口中<strong>只有一个抽象方法</strong>(可以有多个默认方法或静态方法)。</li>
<li>可以加上 <code>@FunctionalInterface</code> 注解(非强制,但建议加上)。</li>
</ul>
</li>
<li>
<p>函数式接口可以通过Lambda表达式、方法引用或构造器引用来实例化。</p>
<p><code>@FunctionalInterface</code> 注解,用于声明一个接口为函数式接口。</p>
</li>
<li>
<p>符合函数式接口规范的接口类型有:</p>
<ul>
<li><code>Runnable</code></li>
<li><code>Callable</code></li>
<li><code>Comparator</code></li>
<li>自定义的函数式接口</li>
<li>Java 提供的内置函数式接口(如 <code>Function</code>, <code>Predicate</code>, <code>Consumer</code> 等)</li>
</ul>
</li>
</ul>
<h3 id="33方法引用"><span id="target-3.3"><strong>3.3.方法引用</strong></span></h3>
<ul>
<li>
<p>方法引用:本质上是简化Lambda表达式,当你要传递的方法已经存在时,可以使用方法引用来直接引用已有的方法,而不是通过 Lambda 表达式重新定义。</p>
</li>
<li>
<p><strong>方法引用(Method Reference)在使用时必须满足“参数一致性”要求</strong>,也就是说:</p>
<p>方法引用的目标方法的参数列表和返回类型,必须与函数式接口中抽象方法的参数列表和返回类型兼容。</p>
</li>
<li>
<p>方法引用包括:</p>
<ul>
<li>静态方法引用</li>
<li>实例方法引用</li>
<li>特定类型方法引用</li>
<li>构造器引用。</li>
</ul>
</li>
<li>
<p>静态方法引用<br>
<code>类名::静态方法</code><br>
使用场景:如果某个Lambda表达式只是调用一个静态方法,并且“-&gt;”前后参数的形式一致,就可以使用静态方法引用。</p>
</li>
</ul>
<pre><code class="language-java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    // 姓名 年龄 身高 性别
    private String name;
    private int age;
    private double height;
    private char sex;

    // 静态方法:按照年龄比较:升序排序
    public static int compareByAge(Student o1, Student o2) {
      return o1.getAge() - o2.getAge();
    }

    // 实例方法:按照身高比较:升序排序
    public int compareByHeight(Student o1, Student o2) {
      return Double.compare(o1.getHeight(), o2.getHeight());
    }
}

public class Test1 {
    public static void main(String[] args) {
      // 目标:静态方法引用:演示一个场景。
      test();
    }

    public static void test(){
      Student[] stus = new Student;
      stus = new Student("殷素素", 35, 171.5, '女');
      stus = new Student("赵敏", 18, 168.5, '女');
      stus = new Student("金毛狮王", 35, 181, '男');
      stus = new Student("周芷若", 18, 172.5, '女');
      stus = new Student("张无忌", 25, 170.5, '男');
      stus = new Student("小昭", 19, 168.5, '女');

      // 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
//      Arrays.sort(stus, (o1, o2) -&gt; o1.getAge() - o2.getAge() );

//      Arrays.sort(stus, (o1, o2) -&gt; Student.compareByAge(o1, o2) );

      // Lambda表达式简化:方法引用 -&gt; 静态方法引用
      Arrays.sort(stus, Student::compareByAge);

      // 遍历数组中的学生对象并输出
      for (int i = 0; i &lt; stus.length; i++) {
            Student s = stus;
            System.out.println(s);
      }
    }
}
</code></pre>
<ul>
<li>实例方法引用:<br>
<code>对象名::实例方法</code><br>
使用场景:如果某个Lambda表达式只是通过对象名称调用一个实例方法,并且“-&gt;”前后参数的形式一致,就可以使用实例方法引用。</li>
</ul>
<pre><code class="language-java">public class Test2 {
    public static void main(String[] args) {
      // 目标:实例方法引用
      test();
    }

    public static void test(){
      Student[] stus = new Student;
      stus = new Student("殷素素", 35, 171.5, '女');
      stus = new Student("赵敏", 18, 168.5, '女');
      stus = new Student("金毛狮王", 35, 181, '男');
      stus = new Student("周芷若", 18, 172.5, '女');
      stus = new Student("张无忌", 25, 170.5, '男');
      stus = new Student("小昭", 19, 168.5, '女');

      // 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
      // 实例方法引用要先创建对象,才能引用
      Student t = new Student();
//      Arrays.sort(stus, (o1, o2) -&gt; t.compareByHeight(o1, o2) );

      // 实例方法引用: 对象名::实例方法
      Arrays.sort(stus, t::compareByHeight);

      // 遍历数组中的学生对象并输出
      for (int i = 0; i &lt; stus.length; i++) {
            Student s = stus;
            System.out.println(s);
      }
    }
}
</code></pre>
<ul>
<li>特定类型方法的引用:<br>
<code>特定类的名称::方法</code><br>
使用场景:如果某个Lambda表达式只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。</li>
</ul>
<pre><code class="language-java">public class Test3 {
    public static void main(String[] args) {
      // 目标:特定类型的方法引用
      // 需求:有一个字符串数组,里面有一些人的名字,都是英文名字,请按照名字的首字母升序排序。
      String[] names = {"Tom", "Jerry", "曹操","Mike","Angela", "Jack", "Rose", "Lucy", "Andy", "Bobi","caocao"};

      // 把这个数组进行排序:Arrays.sort(names,Comparator)
      Arrays.sort(names);// 默认就是按照首字母的编号升序排序

      // 要求:忽略首字母的大小进行升序排序(java官方默认是搞不定的,需要我们自己指定比较规则)
      /*
      Arrays.sort(names, new Comparator&lt;String&gt;() {
            @Override
            public int compare(String o1, String o2) {
                // o1 Angela
                // o2 Andy
                return o1.compareToIgnoreCase(o2);   // o1 &gt; o2 返回正数,o1 &lt; o2 返回负数,o1 == o2 返回0
                // java已经为我们提供了字符串按照首字母忽略大小写比较的方法:compareToIgnoreCase()
            }
      });*/

      // 调用字符串类型的实例方法——特定类型的实例方法
//      Arrays.sort(names, (o1, o2) -&gt; o1.compareToIgnoreCase(o2) );
      
      // 调用字符串类型的静态方法——特定类型的静态方法类型名称::方法
      Arrays.sort(names, String::compareToIgnoreCase);

      System.out.println(Arrays.toString(names));
    }
}
</code></pre>
<ul>
<li>构造器引用:<br>
<code>类名::new</code><br>
使用场景:如果某个Lambda表达式只是在创建对象,并且“-&gt;”前后参数的形式一致,就可以使用构造器引用。</li>
</ul>
<pre><code class="language-java">// 函数式接口
@FunctionalInterface
interface CarFactory {
    Car create(String name);// 根据名字name 创建一个Car对象返回
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Car{
    private String name;
}

public class Test4 {
    public static void main(String[] args) {
      // 目标:理解构造器引用
      // 创建了接口的匿名内部类对象
      /*CarFactory cf = new CarFactory() {
            @Override
            public Car create(String name) {
                return new Car(name);
            }
      };*/

      // 匿名内部类简化:Lambda表达式 -&gt; Lambda表达式省略
//      CarFactory cf = name -&gt; new Car(name) ;

      // Lambda表达式简化:方法引用 -&gt; 构造器引用
      CarFactory cf = Car::new; ;

      Car c1 = cf.create("奔驰");
      System.out.println(c1);
    }
}
</code></pre>
<h2 id="4常用api"><span id="target-4"><strong>4.常用API</strong></span></h2>
<h3 id="41string"><span id="target-4.1"><strong>4.1.String</strong></span></h3>
<ul>
<li>
<p>常用API接口:String</p>
</li>
<li>
<p>String是什么,有什么用?<br>
String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。</p>
</li>
<li>
<p>String创建字符串对象的方式:<br>
1、创建字符串对象,封装字符串数据<br>
2、调用String提供的操作字符串数据的方法。</p>
</li>
<li>
<p>String创建对象的区别:<br>
只要是以<strong>“”</strong>方式写出的字符串对象,会存储到字符串常量池(堆内存中有块区域叫常量池),且相同内容的字符串只存储一份;<br>
通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。</p>
</li>
</ul>
<pre><code class="language-java">public class StringDemo1 {
    public static void main(String[] args) {
      // 目标:创建字符串对象,封装要处理的字符串数据,调用String踢动的方法处理字符串
      // 1.推荐方式一:直接“”就可以创建字符串对象,封装字符串数据。
      String s1 = "hello 黑马";
      System.out.println(s1);
      System.out.println(s1.length());// 处理字符串的方法

      // 2.方式二:通过构造器初始化对象
      String s2 = new String();// 等价于 ""
      System.out.println(s2); // 空字符串

      String s3 = new String("hello java");
      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, 68, 65, 66};
      String s5 = new String(bytes);
      System.out.println(s5);

      System.out.println("============================");
      String t1 = "abc";
      String t2 = "abc";
      System.out.println(t1 == t2);

      String t3 = new String("abc");
      String t4 = new String("abc");
      System.out.println(t3 == t4);

      System.out.println("============================");
      // 调用字符串的方法,处理字符串数据。
      // 简易版的登录:
      String okLoginName = "admin";
      System.out.println("请输入您的登录名称:");
      Scanner sc = new Scanner(System.in);
      String loginName = sc.next();
      // loginName == okLoginName 默认比较的是地址
      // 判断字符串内容,建议用String提供的equals方法,只关心内容一样,就返回true,不关心地址
      if (loginName.equals(okLoginName)) {
            System.out.println("登录成功!");
      } else {
            System.out.println("登录失败!");
      }
      System.out.println("============================");
      // 18663666520 ===&gt; 从0开始
      // 0 1 2 3 4 5 6 7 8 9 10
      System.out.println("请您用手机号码登录:");
      String phone = sc.next();

      System.out.println("系统显示以下手机号码进入:");
      String newPhone = phone.substring(0, 3) + "****" + phone.substring(7);
      // 包前不包后,012,    8-
      System.out.println(newPhone);
    }
}
</code></pre>
<ul>
<li>String提供的常用方法:<br>
<img src="https://img2024.cnblogs.com/blog/2732631/202502/2732631-20250204180655699-851768986.png"></li>
</ul>
<h3 id="42arraylist集合"><span id="target-4.2"><strong>4.2.ArrayList集合</strong></span></h3>
<ul>
<li>
<p>ArrayList:归属于集合,是泛型类,可以约束存储的数据类型。</p>
</li>
<li>
<p>什么是集合?<br>
集合是一种容器,用来装数据的,类似于数组。</p>
</li>
<li>
<p>有数组,为什么还需要学习集合?<br>
数组定义完成并启动后,长度就固定了;<br>
<strong>集合大小可变</strong>,功能丰富,开发中用的更多。</p>
</li>
<li>
<p>集合的种类很多:Set,Map,ArrayList……</p>
</li>
<li>
<p>ArrayList集合学什么?<br>
1、创建ArrayList对象,代表一个集合容器<br>
2、调用ArrayList提供的方法,对容器中的数据进行增删改查操作。</p>
</li>
</ul>
<pre><code class="language-java">public class ArrayListDemo1 {
    public static void main(String[] args) {
      // 目标:掌握ArrayList集合的基本使用。
      // 创建ArrayList对象,代表一个集合容器
//      ArrayList list = new ArrayList();
      // &lt;String&gt;:代表泛型,只能放String类型数据
      ArrayList&lt;String&gt; list = new ArrayList&lt;&gt;();   // 泛型定义集合
      // 添加数据
      list.add("java");
      list.add("mysql");
      list.add("html");
      list.add("赵敏");
      System.out.println(list);

      // 查看数据
      System.out.println(list.get(0));
      System.out.println(list.get(1));
      System.out.println(list.get(2));
      System.out.println(list.get(3));
      System.out.println("======================");
      // 遍历集合
      for (int i = 0; i &lt; list.size(); i++) {
            // i 0 1 2 3
            System.out.println(list.get(i));
      }
      System.out.println("======================");

      // 删除数据
      System.out.println(list.remove(0));// 根据索引删除数据
      System.out.println(list);
      System.out.println(list.remove("赵敏"));// 根据元素删除数据
      System.out.println(list);
      System.out.println("======================");

      // 修改数据
      list.set(0, "javaee");
      System.out.println(list);
    }
}
</code></pre>
<h2 id="5gui编程"><span id="target-5"><strong>5.GUI编程</strong></span></h2>
<ul>
<li>
<p>GUI编程:GUI(Graphical User Interface ,图形用户界面),是桌面的界面技术,不常用——是为了提高趣味性。<br>
通过图形元素(如窗口、按钮、文本框等)与用户进行交互;<br>
与命令行界面(CLI)相比,GUI更加直观,友好。</p>
</li>
<li>
<p>为什么学习GUI编程?<br>
增强用户体验;<br>
广泛应用于桌面应用程序开发<br>
java提供了强大的GUI编程支持</p>
</li>
<li>
<p>java的GUI编程包<br>
AWT(Abstract Window Toolkit,抽象窗口工具集)提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统;<br>
<strong>Swing</strong>(用这个,不用AWT)基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统。</p>
</li>
<li>
<p>常用的Swing组件:(前面不加J就是AWT组件)<br>
JFrame:窗口<br>
JPanel:用于组织其他组件的容器<br>
JButton:按钮组件<br>
JTextField:输入框<br>
JTable:表格</p>
</li>
<li>
<p>布局管理器(Layout Manager)它们可以决定组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。</p>
</li>
<li>
<p>常见的布局管理器:<br>
FlowLayout:水平布局/垂直布局<br>
BorderLayout:方向布局<br>
GridLayout:网格布局<br>
BoxLayout:盒子布局</p>
</li>
<li>
<p>GUI编程:事件处理<br>
GUI编程中,事件的处理是通过事件监听器(Event Listener)来完成的。</p>
</li>
<li>
<p>常用的事件监听器对象:<br>
点击事件监听器 ActionListener<br>
按键事件监听器 KeyListener<br>
鼠标行为监听器 MouseListener<br>
……</p>
</li>
<li>
<p>事件的几种常见写法:<br>
1、直接提供实现类,用于创建事件监听对象;<br>
2、直接使用匿名内部类的对象,代表事件监听对象<br>
3、自定义窗口,让窗口对象实现事件接口。</p>
</li>
</ul>
<pre><code class="language-java">import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginScreen extends JFrame {
    private JTextField usernameField;
    private JPasswordField passwordField;
    private JButton loginButton;
    private JLabel errorLabel;

    public LoginScreen() {
      // 设置窗口标题
      setTitle("Login Screen");
      setSize(400, 300);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setLocationRelativeTo(null); // 居中显示

      // 创建面板并设置布局
      JPanel panel = new JPanel();
      panel.setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints();

      // 标题
      JLabel titleLabel = new JLabel("Welcome Back!");
      titleLabel.setFont(new Font("Serif", Font.BOLD, 24));
      gbc.gridx = 0;
      gbc.gridy = 0;
      gbc.gridwidth = 2;
      gbc.insets = new Insets(10, 0, 20, 0); // 上下左右边距
      panel.add(titleLabel, gbc);

      // 用户名标签和输入框
      JLabel usernameLabel = new JLabel("Username:");
      usernameField = new JTextField(15);
      gbc.gridx = 0;
      gbc.gridy = 1;
      gbc.gridwidth = 1;
      gbc.insets = new Insets(10, 0, 10, 10); // 左侧留出空间
      panel.add(usernameLabel, gbc);

      gbc.gridx = 1;
      gbc.gridy = 1;
      gbc.insets = new Insets(10, 0, 10, 0);
      panel.add(usernameField, gbc);

      // 密码标签和输入框
      JLabel passwordLabel = new JLabel("Password:");
      passwordField = new JPasswordField(15);
      gbc.gridx = 0;
      gbc.gridy = 2;
      gbc.insets = new Insets(10, 0, 10, 10);
      panel.add(passwordLabel, gbc);

      gbc.gridx = 1;
      gbc.gridy = 2;
      gbc.insets = new Insets(10, 0, 10, 0);
      panel.add(passwordField, gbc);

      // 登录按钮
      loginButton = new JButton("Login");
      loginButton.setBackground(new Color(76, 175, 80)); // 设置按钮颜色为绿色
      loginButton.setForeground(Color.WHITE); // 文字颜色为白色
      loginButton.setFocusPainted(false); // 去除焦点边框
      loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                authenticate();
            }
      });
      gbc.gridx = 0;
      gbc.gridy = 3;
      gbc.gridwidth = 2;
      gbc.insets = new Insets(20, 0, 10, 0);
      panel.add(loginButton, gbc);

      // 错误信息标签
      errorLabel = new JLabel("", SwingConstants.CENTER);
      errorLabel.setForeground(Color.RED);
      gbc.gridx = 0;
      gbc.gridy = 4;
      gbc.gridwidth = 2;
      panel.add(errorLabel, gbc);

      add(panel);
      setVisible(true);
    }

    private void authenticate() {
      String username = usernameField.getText();
      String password = new String(passwordField.getPassword());

      if ("admin".equals(username) &amp;&amp; "password".equals(password)) {
            JOptionPane.showMessageDialog(this, "Login successful!", "Success", JOptionPane.INFORMATION_MESSAGE);
      } else {
            errorLabel.setText("Invalid username or password.");
      }
    }

    public static void main(String[] args) {
      SwingUtilities.invokeLater(LoginScreen::new);
    }
}
</code></pre>
<h2 id="6关于返回数组的内容"><span id="target-6"><strong>6.关于返回数组的内容</strong></span></h2>
<ul>
<li>看数组内容:
<ul>
<li>使用循环语句输出之外</li>
<li>java提供了Arrays.toString(数组名); ,可以返回数组的内容<br>
</li>
</ul>
</li>
<li>Arrays.sort(A,B)Array的排序算法:</li>
</ul>
<pre><code class="language-java">public static &lt;T&gt; void sort(T[] a, Comparator&lt;? super T&gt; c) {
      if (c == null) {
            sort(a);
      } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
      }
    }
</code></pre>
<h2 id="7-参考资料"><span id="target-7"><strong>7. 参考资料</strong></span></h2>
<ul>
<li>黑马程序员:黑马程序员Java+AI智能辅助编程全套视频教程,java零基础入门到大牛一套通关_哔哩哔哩_bilibili</li>
<li>通义千问:通义 - 你的实用AI助手</li>
</ul><br><br>
来源:https://www.cnblogs.com/superstring-sun/p/18696319
頁: [1]
查看完整版本: JavaSE-08面向对象高级二