当前位置: 首页 > news >正文

面向对象高级(2)

文章目录

  • 代码块
  • 内部类
    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类(重点)
      • 认识
      • 常见使用形式
      • 应用场景
  • 函数式编程
    • Lambda
      • 认识Lambda
      • Lambda表达式的省略规则
    • 方法引用
      • 静态方法的引用
      • 实例方法的引用
      • 特定类型方法的引用
      • 构造器引用
  • 常用API
    • String
    • ArrayList
  • GUI编程
    • 快速入门、常用组件
      • Java的GUI编程包
      • 常用的Swing组件
      • 常见的布局管理器
        • FlowLayout
        • BorderLayout
        • GridLayout
        • BoxLayout
    • 事件监听器
      • 事件处理
      • 常用的时间监听器对象
      • 事件的几种常见写法

代码块

代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)。
代码块分为两种:
静态代码块:
格式:static { }
特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
作用:完成类的初始化,例如:对静态变量的初始化赋值。

import java.util.Arrays;
public class CodeDemo1 {
    public static String schoolName;
    public static String[] cards = new String[54];
    // 静态代码块:有static修饰,属于类,与类一起优先加载,自动执行一次
    // 基本作用:可以完成对类的静态资源的初始化
    static {
        System.out.println("===静态代码块执行了====");
        schoolName = "黑马程序员";
        cards[0] = "A";
        cards[1] = "2";
        cards[2] = "3";
        // ...
    }
    public static void main(String[] args) {
        // 目标: 认识代码块,搞清楚代码块的基本作用。
        System.out.println("===main方法执行了====");
        System.out.println(schoolName);
        System.out.println(Arrays.toString(cards)); // 返回数组的内容观察

	//===静态代码块执行了====
	// ===main方法执行了====
	// 黑马程序员
	// [A, 2, 3, null, null, null, null, null...]
    }
}

实例代码块:
格式:{ }
特点:每次创建对象时,执行实例代码块,并在构造器前执行。
作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值。

public class CodeDemo2 {
    private String name;
    private String[] direction = new String[4]; // 实例变量
    // 实例代码块:无static修饰。属于对象,每次创建对象时,都会优先执行一次。
    // 基本作用:初始化对象的实例资源。
    {
        System.out.println("=========实例代码块执行了=========");
        name = "itheima"; // 赋值
        direction[0] = "N";
        direction[1] = "S";
        direction[2] = "E";
        direction[3] = "W";
    }
    public static void main(String[] args) {
        // 目标:实例代码块。
        System.out.println("=========main方法执行了=========");
        new CodeDemo2();
        new CodeDemo2();
        new CodeDemo2();
        // =========main方法执行了=========
        // =========实例代码块执行了=========
        // =========实例代码块执行了=========
        // =========实例代码块执行了=========
    }
}

内部类

什么是内部类
如果一个类定义在另一个类的内部,这个类就是内部类。
使用场景
场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
内部类可分为

  • 成员内部类(了解)
  • 静态内部类(了解)
  • 局部内部类(了解)
  • 匿名内部类(重点)

前三种语法只需要了解,我们基本不用。之所以学是为了看懂别人的代码。

成员内部类

什么是成员内部类
就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法。

写法是什么,如何调用。

public class Outer {    
	// 成员内部类
	public class Inner {	     
	}
}
// 创建对象的格式:
// 外部类名.内部类名 对象名 = new 外部类(...).new 内部类(...);
Outer.Inner in =  new Outer().new  Inner();

成员内部类中访问其他成员的特点:
1、成员内部类种可以直接访问外部类的实例成员、静态成员。
2、成员内部类的实例方法中,可以直接拿到当前外部类对象,格式是:外部类名.this 。

// 外部类
public class Outer {
    public static String schoolName = "黑马程序员";
    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); // 寄生的外部类对象
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}
public class InnerClassDemo1 {
    public static void main(String[] args) {
        // 目标:搞清楚成员内部类的语法。
        // 成员内部类创建对象的格式:
        // 外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
        Outer.Inner oi = new Outer().new Inner();
        oi.setName("王麻子");
        oi.show();
        // 成员内部类访问外部类成员的特点(拓展):
        // 1、成员内部类中可以直接访问外部类的静态成员,也可以直接访问外部类的实例成员
        // 2、成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象:外部类名.this。比如下面人和心脏的例子。
        People.Heart heart = new People().new Heart();
        heart.show();
    }
}
class People {
    private int heartBeat = 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.heartBeat);// 100
        }
    }
}

静态内部类

什么是静态内部类
有static修饰的内部类,属于外部类自己持有。

写法是什么,如何调用。

public class Outer{
    // 静态内部类
    public static class Inner{   }
}
// 外部类名.内部类名 对象名 = new 外部类.内部类(…);
Outer.Inner in =  new Outer.Inner();

静态内部类中访问外部类成员的特点
可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。

// 外部类
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 void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}
public class InnerClassDemo2 {
    public static void main(String[] args) {
        // 目标:搞清楚静态内部类的语法。
        // 创建对象:外部类名.内部类名 对象名 = new 外部类名.内部类名();
        Outer.Inner inner = new Outer.Inner();
        inner.show();
        // 1、静态内部中是否可以直接访问外部类的静态成员? 可以!
        // 2、静态内部类中是否可以直接访问外部类的实例成员?不可以!
    }
}

局部内部类

局部内部类是定义在在方法中、代码块中、构造器等执行体中。
鸡肋语法看看就好

public class Test {
	public static void main(String[] args) {}
	public static void go(){
		class A{}
		abstract class B{}
		interface C{}
	}
}

匿名内部类(重点)

认识

什么是匿名内部类
是一种特殊的局部内部类;
所谓匿名:指的是程序员不需要为这个类声明名字,默认有个隐藏的名字。

new  类或接口(参数值…) {
	类体(一般是方法重写)};

new Animal(){
	@Override
	public void cry() { }
};

先展示不使用局部内部类

public abstract class Animal {
    public abstract void cry();
}
public class Test {
    public static void main(String[] args) {
        Animal cat = new Cat();
        cat.cry();
        // 我们需要新写一个Cat类继承动物类,再写new new Cat();
    }
}
class Cat extends Animal{
    @Override
    public void cry() {
        System.out.println("🐱猫是喵喵喵的叫~~~~");
    }
}

展示使用局部内部类

public abstract class Animal {
    public abstract void cry();
}
package com.itheima.innerclass3;

public class Test {
    public static void main(String[] args) {
        // Animal cat = new Cat();
        // cat.cry();
        // 我们不需要新写一个Cat类继承动物类,再写new new Cat();
        // class Cat extends Animal {} 省略了。
        Animal a = new Animal(){
            @Override
            public void cry() {
                System.out.println("🐱猫是喵喵喵的叫~~~~");
            }
        };
        a.cry();
    }
}

特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
作用:用于更方便的创建一个子类对象。

public abstract class Animal {
    public abstract void cry();
}
public class Test {
    public static void main(String[] args) {
        // 匿名内部类实际上是有名字:外部类名$编号.class  
        // 可以打开out对应的文件夹 进行查看
        // 匿名内部类本质是一个子类,同时会立即构建一个子类对象
        Animal a = new Animal(){
            @Override
            public void cry() {
                System.out.println("🐱猫是喵喵喵的叫~~~~");
            }
        };
        a.cry();
    }
}

可以打开out对应的文件夹 进行查看如下:
在这里插入图片描述

常见使用形式

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("结束。。。。");
    }
}

interface Swim {
    void swimming(); // 游泳方法
}

应用场景

别人写好的api需要我们传给他一个匿名参数:比如使用comparator接口的匿名内部类实现对数组进行排序。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    // 姓名 年龄 身高 性别
    private String name;
    private int age;
    private double height;
    private char sex;
}
//Test4.java
import java.util.Arrays;
import java.util.Comparator;
public class Test4 {
    public static void main(String[] args) {
        // 目标:完成给数组排序,理解其中匿名内部类的用法。
        // 准备一个学生类型的数组,存放6个学生对象。
        Student[] students = new Student[6];
        students[0] = new Student("殷素素", 35, 171.5, '女');
        students[1] = new Student("杨幂", 28, 168.5, '女');
        students[2] = new Student("张无忌", 25, 181.5, '男');
        students[3] = new Student("小昭", 19, 165.5, '女');
        students[4] = new Student("赵敏", 27, 167.5, '女');
        students[5] = new Student("刘亦菲", 36, 168, '女');

        // 需求:按钮年龄升序排序。可以调用sun公司写好的API直接对数组进行排序。
        // public static void sort(T[] a, Comparator<T> c)
        //           参数一: 需要排序的数组
        //           参数二: 需要给sort方法声明一个Comparator比较器对象(指定排序的规则)
        //    sort方法内部会调用匿名内部类对象的compare方法,对数组中的学生对象进行两两比较,从而实现排序。
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                // 指定排序规则:
                // 如果你认为左边对象 大于 右边对象 那么返回正整数。
                // 如果你认为左边对象 小于 右边对象 那么返回负整数。
                // 如果两边相等那么返回0
//                if(o1.getAge() > o2.getAge()){
//                    return 1;
//                }else if(o1.getAge() < o2.getAge()){
//                      return -1;
//                }
//                return 0;
// 				  上面这么多可以简写为下面的。
//                return o1.getAge() - o2.getAge(); // 按照年龄升序!
                 return o2.getAge() - o1.getAge(); // 按照年龄降序!
            }
        });

        // 遍历数组中的学生对象并输出
        for (int i = 0; i < students.length; i++) {
            Student s = students[i];
            System.out.println(s);
        }
    }
}

相当于下面的

import java.util.Comparator;
public class Ssort implements Comparator<Student> {
    public int compare(Student o1, Student o2) {
        return o2.getAge() - o1.getAge();
    }
}
//Test4.java
import java.util.Arrays;
import java.util.Comparator;

public class Test {
    public static void main(String[] args) {
        Student[] students = new Student[6];
        // .....
        Ssort ssort = new Ssort();
        Arrays.sort(students, ssort);
        // 遍历数组中的学生对象并输出.....
    }
}

函数式编程

Lambda

认识Lambda

什么是函数式编程?有是好处?
使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。

Lambda表达式(函数)是啥?有什么用?怎么写?
JDK 8开始新增的一种语法形式,它表示函数。
可以用于替代某些匿名内部类对象,从而让程序更简洁,可读性更好。

(被重写方法的形参列表) -> {被重写方法的方法体代码。}

适用范围
注意 : Lambda表达式只能替代函数式接口的匿名内部类!!!,否则报错

什么样的接口是函数式接口?怎么确保一个接口必须是函数式接口?
只有一个抽象方法接口就是函数式接口。
可以在接口上加上@FuncationalInterface注解即可。

public class LambdaDemo1 {
    public static void main(String[] args) {
       Swim s1 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("学生🏊‍贼快~~~~");
            }
        };
        s1.swimming();

        // Lambda只能简化函数式接口的匿名内部类。
        Swim s2 = () -> {
            System.out.println("学生🏊‍贼快~~~~");
        };
        s2.swimming();
    }
}

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

Lambda表达式的省略规则

作用:用于进一步简化Lambda表达式的写法。
具体规则

  • 参数类型全部可以省略不写。
  • 如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()”
  • 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号“;”如果这行代码是return语句,也必须去掉return。
import java.util.Arrays;
public class LamdbaDemo2 {
    public static void main(String[] args) {
        // 目标:用Lambda表达式简化实际示例。
        test1();
    }
    public static void test1(){
        Student[] students = new Student[6];
        students[0] = new Student("殷素素", 35, 171.5, '女');
        students[1] = new Student("杨幂", 28, 168.5, '女');
        students[2] = new Student("张无忌", 25, 181.5, '男');
        students[3] = new Student("小昭", 19, 165.5, '女');
        students[4] = new Student("赵敏", 27, 167.5, '女');
        students[5] = new Student("刘亦菲", 36, 168, '女');

        // 需求:按钮年龄升序排序。可以调用sun公司写好的API直接对数组进行排序。
//        Arrays.sort(students, new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                return o1.getAge() - o2.getAge(); // 按照年龄升序!
//            }
//        });

//        Arrays.sort(students, (Student o1, Student o2) -> {
//            return o1.getAge() - o2.getAge(); // 按照年龄升序!
//        });

        Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());

        // 遍历数组中的学生对象并输出
        for (int i = 0; i < students.length; i++) {
            Student s = students[i];
            System.out.println(s);
        }
    }
}

方法引用

静态方法的引用

类名::静态方法
使用场景
如果某个Lambda表达式里只是调用一个静态方法,并且“→”前后参数的形式一致,就可以使用静态方法引用。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
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();
    }
}

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

    public static void test() {
        Student[] students = new Student[6];
        students[0] = new Student("殷素素", 35, 171.5, '女');
        students[1] = new Student("杨幂", 28, 168.5, '女');
        students[2] = new Student("张无忌", 25, 181.5, '男');
        students[3] = new Student("小昭", 19, 165.5, '女');
        students[4] = new Student("赵敏", 27, 167.5, '女');
        students[5] = new Student("刘亦菲", 36, 168, '女');

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

        // 静态方法引用: 类名:: 静态方法
        // 前提:-> 前后参数的形式一致,才可以使用实例方法引用
        Arrays.sort(students, Student::compareByAge);

        // 遍历数组中的学生对象并输出
        for (int i = 0; i < students.length; i++) {
            Student s = students[i];
            System.out.println(s);
        }
    }
}

实例方法的引用

对象名::实例方法。
使用场景
如果某个Lambda表达式里只是通过对象名称调用一个实例方法,并且“→”前后参数的形式一致,就可以使用实例方法引用。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    // 姓名 年龄 身高 性别
    private String name;
    private int age;
    private double height;
    private char sex;

    // 实例方法
    public int compareByHeight(Student o1, Student o2) {
        // 按照身高比较
        return Double.compare(o1.getHeight(), o2.getHeight());
    }
}
// Demo2.java
import java.util.Arrays;
public class Demo2 {
    public static void main(String[] args) {
        // 目标:实例方法引用:演示一个场景。
        test();
    }
    public static void test() {
        Student[] students = new Student[6];
        students[0] = new Student("殷素素", 35, 171.5, '女');
        students[1] = new Student("杨幂", 28, 168.5, '女');
        students[2] = new Student("张无忌", 25, 181.5, '男');
        students[3] = new Student("小昭", 19, 165.5, '女');
        students[4] = new Student("赵敏", 27, 167.5, '女');
        students[5] = new Student("刘亦菲", 36, 168, '女');

        // 需求:按照身高升序排序。可以调用sun公司写好的API直接对数组进行排序。
        Student t = new Student();
        // Arrays.sort(students, (o1, o2) ->  t.compareByHeight(o1, o2));

        // 实例方法引用:对象名::实例方法
        // 前提:-> 前后参数的形式一致,才可以使用实例方法引用
        Arrays.sort(students, t::compareByHeight);

        // 遍历数组中的学生对象并输出
        for (int i = 0; i < students.length; i++) {
            Student s = students[i];
            System.out.println(s);
        }
    }
}

特定类型方法的引用

特定类的名称::方法
使用场景
如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。

import java.util.Arrays;
public class Demo3 {
    public static void main(String[] args) {
        // 目标:特定类型的方法引用。
        // 需求:有一个字符串数组,里面有一些人的名字都是,英文名称,请按照名字的首字母升序排序。
        String[] names = {"Tom", "Jerry", "Bobi", "曹操" , "Mike", "angela",  "Dlei", "Jack", "Rose", "Andy", "caocao"};

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

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

//        Arrays.sort(names, (o1,  o2)  ->  o1.compareToIgnoreCase(o2) );

        // 特定类型方法引用:类型名称::方法名
        // 如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,
        // 后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。
        Arrays.sort(names, String::compareToIgnoreCase);
        
        System.out.println(Arrays.toString(names));
        // [Andy, angela, Bobi, caocao, Dlei, Jack, Jerry, Mike, Rose, Tom, 曹操]
    }
}

构造器引用

类名::new
使用场景
如果某个Lambda表达式里只是在创建对象,并且“→”前后参数情况一致,就可以使用构造器引用。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

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

//      CarFactory cf = name -> new Car(name);

        // 构造器引用: 类名::new
        CarFactory cf = Car::new;

        Car c1 = cf.getCar("奔驰");
        System.out.println(c1);
        // Car(name=奔驰)
        // 重写了toString 打印了Car(name=奔驰)
    }
}
@FunctionalInterface
interface CarFactory {
    Car getCar(String name);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Car{
    private String name;
}

常用API

什么是api
Java API(Application Programming Interface)是Java编程语言提供的​​标准化编程接口集合​​,由预先定义的类、接口、方法和常量构成,为开发者提供了一套访问系统资源、实现功能逻辑的标准工具。

简单来说就是Java的API(应用程序编程接口)就像一套​​“现成的工具包”​​,专门为Java开发者设计,帮助你快速完成各种编程任务,而不需要自己从零开始造轮子。举个生活中的例子:API就像乐高积木,已经提前造好了各种形状的积木块(比如轮子、门窗),你只需要把它们组合起来就能搭出想要的房子,而不需要自己烧砖头、做零件。

String

String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。
1、创建字符串对象,封装字符串数据
2、调用String提供的操作字符串数据的方法

方式一: Java 程序中的所有字符串文字(例如“abc”)都为此类的对象。

String name = "小黑";
String schoolName = "黑马程序员";

方式二: 调用String类的构造器初始化字符串对象。

构造器说明
public String()创建一个空白字符串对象,不含有任何内容
public String(String original)根据传入的字符串内容,来创建字符串对象
public String(char[] chars)根据字符数组的内容,来创建字符串对象
public String(byte[] bytes)根据字节数组的内容,来创建字符串对象

两种方式的区别

  • 只要是以“…方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份;
  • 通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。

方式一
在这里插入图片描述
方式二
在这里插入图片描述

public class ublic 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,黑马"); // 不推荐
    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, 67};
    String s5 = new String(bytes);
    System.out.println(s5);

    System.out.println("========================================");
    // 只有“”给出的字符串对象放在字符串常量池,相同内容只放一个。
    String t1 = "abc";
    String t2 = "abc";
    System.out.println(t1 == t2);// true

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

String提供的常用方法

方法名说明
public int length()获取字符串的长度返回(就是字符个数)
public char charAt(int index)获取某个索引位置处的字符返回
public char[] toCharArray():将当前字符串转换成字符数组返回
public boolean equals(Object anObject)判断当前字符串与另一个字符串的内容一样,一样返回true
public boolean equalsIgnoreCase(String anotherString)判断当前字符串与另一个字符串的内容是否一样(忽略大小写)
public String substring(int beginIndex, int endIndex)根据开始和结束索引进行截取,得到新的字符串(包前不包后)
public String substring(int beginIndex)从传入的索引处截取,截取到末尾,得到新的字符串返回
public String replace(CharSequence target, CharSequence replacement)使用新值,将字符串中的旧值替换,得到新的字符串
public boolean contains(CharSequence s)判断字符串中是否包含了某个字符串
public boolean startsWith(String prefix)判断字符串是否以某个字符串内容开头,开头返回true,反之
public String[] split(String regex)把字符串按照某个字符串内容分割,并返回字符串数组回来

ArrayList

  1. 什么是集合?
    集合是一种容器,用来装数据的,类似于数组。

  2. 有数组,为啥还学习集合?
    数组定义完成并启动后,长度就固定了。 集合大小可变,功能丰富,开发中用的更多。

  3. 集合的种类很多,请举例

  4. ArrayList是什么?
    是集合中最常用的一种,ArrayList是泛型类,可以约束存储的数据类型。

  5. 怎么使用?
    1、 调用无参数构造器ArrayList<T> list = new ArrayList<>();创建ArrayList对象,代表一个集合容器。
    2、调用ArrayList提供的方法,对容器中的数据进行增删改查操作

构造器说明
public ArrayList()创建一个空的集合对象
常用方法名说明
public boolean add(E e)将指定的元素添加到此集合的末尾
public void add(int index,E element)在此集合中的指定位置插入指定的元素
public E get(int index)返回指定索引处的元素
public int size()返回集合中的元素的个数
public E remove(int index)删除指定索引处的元素,返回被删除的元素
public boolean remove(Object o)删除指定的元素,返回删除是否成功
public E set(int index,E element)修改指定索引处的元素,返回被修改的元素
import java.util.ArrayList;
public class ArrayListDemo1 {
    public static void main(String[] args) {
        // 创建ArrayList对象,代表一个集合容器
        // 不加泛型,默认是Object类型。
        ArrayList list1 = new ArrayList();
        list1.add("java");
        list1.add(34);
        list1.add(true);


        ArrayList<String> list = new ArrayList<>(); // 泛型定义集合。
        // 添加数据
        list.add("java");
        list.add("java2");
        list.add("java3");
        list.add("赵敏");
        // list.add(34); 报错因为指定了集合中只能放 String类型。
        System.out.println(list); // [java, java2, java3, 赵敏]
        // 查看数据
        System.out.println(list.get(0)); // java
        System.out.println(list.get(1)); // java2
        System.out.println(list.get(2)); // java3
        System.out.println(list.get(3)); // 赵敏

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

        // 遍历集合。
        for (int i = 0; i < list.size(); i++) {
            // i 0 1 2 3
            String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("-------------------------------");
        // 删除数据
        System.out.println(list.remove(2)); // java3 根据索引删除 返回被删除的元素
        System.out.println(list);// [java, java2, 赵敏]

        System.out.println(list.remove("赵敏")); // 根据元素删除 返回true/false
        System.out.println(list); // [java, java2]

        // 修改数据
        list.set(0, "java4");
        System.out.println(list); // [java4, java2]
    }
}

GUI编程

GUI,全称Graphical User Interface,是指图形用户界面。
通过图形元素(如窗口、按钮、文本框等)与用户进行交互。
与命令行界面(CLI)相比,GUI更加直观、友好。

为什么学习GUI编程?
增强用户体验
广泛应用于桌面应用程序开发
Java提供了强大的GUI编程支持

快速入门、常用组件

Java的GUI编程包

AWT(Abstract Window Toolkit)
提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统
Swing
基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统

常用的Swing组件

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

import javax.swing.*;
public class JFrameDemo1 {
    public static void main(String[] args) {
        // 目标:快速入门一下GUI Swing的编程。
        // 1、创建一个窗口,有一个登录按钮。
        JFrame jf = new JFrame("登录窗口");

        JPanel panel = new JPanel(); // 创建一个面板
        jf.add(panel); // 将面板添加到窗口中

        jf.setSize(400, 300); // 设置窗口大小
        jf.setLocationRelativeTo(null); // 设置窗口居中
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        // 设置关闭窗口的默认操作: 关闭窗口退出程序

        JButton jb = new JButton("登录"); // 创建一个按钮
        panel.add(jb); // 将按钮添加到面板中

        jf.setVisible(true); // 显示窗口
    }
}

常见的布局管理器

常见的布局管理器
布局管理器(Layout Manager)它们可以决定组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。
常见的布局管理器
FlowLayout
BorderLayout
GridLayout
BoxLayout

FlowLayout
  • 简介: FlowLayout 是最简单的布局管理器,它按水平方向从左到右排列组件,当一行排满时,自动换到下一行。

  • 特点

    • 默认居中对齐,可以设置为左对齐或右对齐。
    • 适用于需要简单排列的场景。
  • 代码示例

    import java.awt.*;
    
    public class FlowLayoutExample {
        public static void main(String[] args) {
            JFrame frame = new JFrame("FlowLayout Example");
            frame.setSize(400, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.setLayout(new FlowLayout());
    
            frame.add(new JButton("Button 1"));
            frame.add(new JButton("Button 2"));
            frame.add(new JButton("Button 3"));
            frame.add(new JButton("Button 4"));
            frame.add(new JButton("Button 5"));
    
            frame.setVisible(true);
        }
    }
    

在这里插入图片描述

BorderLayout
  • 简介: BorderLayout 将容器划分为五个区域:东、南、西、北和中(East, South, West, North, Center)。每个区域只能添加一个组件,未添加组件的区域保持空白。

  • 特点

    • 适用于需要在特定区域布局组件的场景。
    • 中间区域会占据所有剩余的空间。
  • 代码示例

    import java.awt.*;
    
    public class BorderLayoutExample {
        public static void main(String[] args) {
            JFrame frame = new JFrame("BorderLayout Example");
            frame.setSize(400, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.setLayout(new BorderLayout());
    
            frame.add(new JButton("North"), BorderLayout.NORTH);
            frame.add(new JButton("South"), BorderLayout.SOUTH);
            frame.add(new JButton("East"), BorderLayout.EAST);
            frame.add(new JButton("West"), BorderLayout.WEST);
            frame.add(new JButton("Center"), BorderLayout.CENTER);
    
            frame.setVisible(true);
        }
    }
    

在这里插入图片描述

GridLayout
  • 简介: GridLayout 将容器划分为等大小的网格,每个网格中可以添加一个组件,所有组件大小相同。

  • 特点

    • 适用于需要均匀排列组件的场景。
    • 行和列的数量可以指定。
  • 代码示例

    java复制代码import javax.swing.*;
    import java.awt.*;
    
    public class GridLayoutExample {
        public static void main(String[] args) {
            JFrame frame = new JFrame("GridLayout Example");
            frame.setSize(400, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.setLayout(new GridLayout(2, 3)); // 2行3列的网格
    
            frame.add(new JButton("Button 1"));
            frame.add(new JButton("Button 2"));
            frame.add(new JButton("Button 3"));
            frame.add(new JButton("Button 4"));
            frame.add(new JButton("Button 5"));
            frame.add(new JButton("Button 6"));
    
            frame.setVisible(true);
        }
    }
    

在这里插入图片描述

BoxLayout
  • 简介: BoxLayout 能够沿着单一轴线(X轴或Y轴)排列组件。可以创建水平(X轴)或垂直(Y轴)排列的布局。

  • 特点

    • 适用于需要沿单一方向排列组件的场景。
    • 可以通过添加垂直或水平间隔(Glue、Strut)来调整组件间距。
  • 代码示例

    import java.awt.*;
    
    public class BoxLayoutExample {
        public static void main(String[] args) {
            JFrame frame = new JFrame("BoxLayout Example");
            frame.setSize(400, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JPanel panel = new JPanel();
            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); // 垂直排列
    
            panel.add(new JButton("Button 1"));
            panel.add(Box.createVerticalStrut(10)); // 添加垂直间隔
            panel.add(new JButton("Button 2"));
            panel.add(Box.createVerticalStrut(10));
            panel.add(new JButton("Button 3"));
            panel.add(Box.createVerticalStrut(10));
            panel.add(new JButton("Button 4"));
    
            frame.add(panel);
            frame.setVisible(true);
        }
    }
    

在这里插入图片描述

这些示例展示了布局管理器在Java Swing中的基本用法。你可以根据实际需求选择合适的布局管理器来设计你的GUI应用程序。

事件监听器

事件处理

GUI编程中,事件的处理是通过事件监听器(Event Listener)来完成的。

常用的时间监听器对象

点击事件监听器 ActionListener
按键事件监听器 KeyListener
鼠标行为监听器 MouseListener

在这里插入图片描述

在这里插入图片描述

事件的几种常见写法

第1种:直接提供实现类,用于创建事件监听对象
第2种:直接使用匿名内部类的对象,代表事件监听对象
第3种:自定义窗口,让窗口对象实现事件接口

相关文章:

  • Apache与Nginx网站压测对比
  • C语言 共用体和typedef
  • 集群搭建Weblogic服务器!
  • C++学习之金融类安全传输平台项目git
  • 第十五届蓝桥杯C/C++B组省赛真题讲解(分享去年比赛的一些真实感受)
  • 智体知识库:poplang编程语言是什么?
  • 具身机器人中AI(DEEPSEEK)与PLC、驱动器协同发展研究:突破数据困境与指令精确控制(1)
  • System 应用访问 Vendor 库的详细方案
  • 如何将数组转换为对象(键为数组元素,值为 true)
  • 用 Vue 3 + D3.js 实现动态数据流图
  • noscript 标签是干什么的
  • Linux上位机开发实践(关于Qt的移植)
  • 具身智能零碎知识点(三):深入解析 “1D UNet”:结构、原理与实战
  • Python_levl2.3函数
  • 【AutoTest】自动化测试工具大全(Python)
  • 限流、降级、熔断、隔离?
  • 【Hyperlane 】轻松实现大文件分块上传!
  • 六、测试分类
  • Python中NumPy的逻辑和比较
  • API 请求失败时的处理方法
  • 做非遗网站的原因/百度开户需要什么资质
  • 网站开发报价表 excel/培训加盟
  • 南通做网站厉害的/b站推广网站mmm
  • 武汉网站建设报价/企业seo外包公司
  • 黄冈市住房和城乡建设厅网站/武汉seo搜索引擎
  • wordpress网站数据迁移/seo文章是什么意思