面向对象高级(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
-
什么是集合?
集合是一种容器,用来装数据的,类似于数组。 -
有数组,为啥还学习集合?
数组定义完成并启动后,长度就固定了。 集合大小可变,功能丰富,开发中用的更多。 -
集合的种类很多,请举例
-
ArrayList是什么?
是集合中最常用的一种,ArrayList是泛型类,可以约束存储的数据类型。 -
怎么使用?
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种:自定义窗口,让窗口对象实现事件接口