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

Java基础:代码块/内部类/Lambda函数/常用API/GUI编程

目录

  • 一、代码块
    • 1.静态代码块
    • 2.实例代码块
  • 二、内部类
    • 1.内部类介绍
    • 2.成员内部类
    • 3.静态内部类
    • 4.局部内部类
    • 5.匿名内部类(重点)
      • 1)认识匿名内部类
      • 2)匿名内部类语法的常见使用形式
      • 3)使用场景1-传输匿名内部类对象给方法使用
      • 4)使用场景2-使用comparator接口
  • 三、Lambda函数
    • 1.理解Lambda函数
    • 2.Lambda表达式的省略规则
    • 3.静态方法引用
    • 4.实例方法引用
    • 5.特定类型的方法引用
    • 6.构造器引用
  • 四、常用API
    • 1.String
    • 2.ArrayList
  • 五、GUI编程
    • 1.GUI是什么?
    • 2.常见的布局管理器
    • 3.事件处理
    • 4.事件的几种常用写法

一、代码块

1.静态代码块

格式:static{ }
特点:类加载时自动执行,由于类只加载一次,所以静态代码块也只执行一次
作用:完成类的初始化,常用于对静态内容的初始化赋值(例如对静态变量的初始化赋值)

public class CodeDemo1 {//创建静态数组(扑克牌)static final String[] cards = new String[54];//创建静态代码块static{//加载类的同时创建扑克牌数组cards[0] = "大王";cards[1] = "小王";System.out.println("静态代码块执行了");}public static void main(String[] args) {System.out.println("main方法执行了");System.out.println(cards[0]);}
}
//执行输出结果:
//静态代码块执行了
//main方法执行了
//大王

2.实例代码块

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

public class CodeDemo2 {//创建数组,存储姓名private String[] names = new String[3];//创建实例代码块{//初始化对象的属性names[0] = "张三";System.out.println("实例代码块执行了");}public static void main(String[] args) {System.out.println("main方法执行了");CodeDemo2 codeDemo2 =new CodeDemo2();System.out.println(codeDemo2.names[0]);}
}
//打印结果:
//main方法执行了
//实例代码块执行了
//张三

二、内部类

1.内部类介绍

1)一个类定义在另一个类的内部,这个类就是内部类,当一个类的内部包含了完整的事物,且该事物没有单独设计的必要时,就可以将该事物设计为内部类,示例:

//汽车
public class Car {//发动机public class Engine {}
}

2)内部类分为4种:成员内部类、静态内部类、局部内部类、匿名内部类

2.成员内部类

1)成员内部类的语法

//外部类
public class Outer {//创建成员内部类,属于外部类的对象持有public class Inner {public void show() {System.out.println("内部类的show()方法执行了");}}
}

2)创建对象的语法

public class InnerClassDemo1 {public static void main(String[] args) {Outer.Inner inner = new Outer().new Inner();inner.show();//打印结果:内部类的show方法执行了}
}

3)成员内部类访问外部类成员的特点:内部类可直接访问外部类的静态成员和实例成员

//外部类
public class Outer {//创建外部类的静态成员public static String name = "张三";//创建外部类的静态方法public static void show() {}//创建外部类的实例成员public String age = "18";//创建外部类的实例方法public void test() {}//创建成员内部类public class Inner {public void show() {//访问外部类的静态成员System.out.println("外部类的静态成员:" + name);//访问外部类的实例成员System.out.println("外部类的实例成员:" + age);//访问外部类的静态方法show();//访问外部类的实例方法test();}}
}

4)成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象,使用方式:外部类名.this

public class InnerClassDemo1 {public static void main(String[] args) {//创建成员内部类对象People.Student student = new People().new Student();student.show(); //打印结果:30 25 18 }
}
//创建外部类
class People {//创建外部类成员变量private int age = 18;//创建成员内部类public class Student {//创建成员内部类的成员变量private int age = 25;//创建成员内部类的实例方法public void show(){//创建实例方法中的局部变量int age = 30;//打印方法中的局部变量System.out.println(age); //30//打印成员内部类的成员变量System.out.println(this.age); //25//打印外部类的成员变量System.out.println(People.this.age); //}}
}

总结:
①成员内部类就是类中的一个普通成员,创建对象的方式为:外部类名.内部类名 对象名 = new 外部类(…).new 内部类(…);
②成员内部类的实例方法中,可以直接访问外部类的实例成员、静态成员
③在成员内部类的实例方法中拿到外部类对象的格式:外部类名.this

3.静态内部类

1)静态内部类语法,内部类名添加static修饰

//创建外部类
public class Outer {//创建静态内部类static class Inner{public void show(){System.out.println("静态内部类");}}
}

2)创建对象调用静态内部类的方法

public class InnerClassDemo {public static void main(String[] args) {//创建对象语法:外部类名.内部类名 对象名 = new 外部类名.内部类名();Outer.Inner oi = new Outer.Inner();//调用静态内部类的方法oi.show();}
}

注意:
①内部类名使用static修饰,静态内部类属于外部类自己持有,不属于外部类的对象
②创建对象的方式为:外部类名.内部类名 对象名 = new 外部类名.内部类名();
③静态内部类中可以直接访问外部类的静态成员,但无法直接访问外部类的实例成员(实例成员属于外部类的对象)

4.局部内部类

在方法中定义内部类(普通类、抽象类、接口),一般无实际意义,仅做了解

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

5.匿名内部类(重点)

1)认识匿名内部类

一种特殊的局部内部类,匿名是指不需要为这个类声明类名,默认存在隐藏的类名;匿名内部类本质上是一个子类,创建的时候同时也会创建出一个子类对象(作用:更方便的创建子类对象)。
例如:有个动物父类,存在食物方法,每个动物需要创建子类继承父类重写食物方法(每个动物爱吃的食物不同),使用匿名内部类则无需单独创建具体的动物子类。

创建动物父类

//创建抽象动物父类
public abstract class Animal {//定义抽象食物方法public abstract void eat();
}

使用匿名内部类语法

public class Test {public static void main(String[] args) {//使用匿名内部类语法,创建子类:猫,同时会自动构建猫对象Animal cat = new Animal() {//重写动物父类的食物方法@Overridepublic void eat() {System.out.println("猫喜欢吃猫粮");}};cat.eat(); //打印结果:猫喜欢吃骨头//使用匿名内部类语法,创建子类:狗,同时会自动构建狗对象Animal dog = new Animal() {//重写动物父类的食物方法@Overridepublic void eat() {System.out.println("狗喜欢吃骨头");}};dog.eat(); //打印结果:狗喜欢吃肉}
}

查看out目录编译后的class文件,可以发现匿名内部类默认存在的隐藏类名(Test$1和Test2),隐藏类名格式:匿名内部类所在的类名+2),隐藏类名格式:匿名内部类所在的类名+2),隐藏类名格式:匿名内部类所在的类名++序号
在这里插入图片描述
查看编译后的class文件内容,可以看到继承自动物父类,印证开头的“匿名内部类本质上是一个子类”

class Test$1 extends Animal {Test$1() {}public void eat() {System.out.println("猫喜欢吃猫粮");}
}

2)匿名内部类语法的常见使用形式

常见使用形式:通常可以作为一个对象参数传给方法使用
需求:学生、老师参加游泳比赛,思路:将游泳比赛定义为方法,学生、老师定义为匿名内部类(对象)传递给游泳比赛方法使用

public class Test2 {public static void main(String[] args) {//创建学生匿名内部类(方法一)swim student = new swim() {//重写接口的抽象方法@Overridepublic void swiming() {System.out.println("学生游完用了20秒");}};swim(student); //打印结果:开始游泳\n学生游完用了20秒//创建老师匿名内部类(方法二,直接将匿名内部类创建语法放进游泳比赛方法)swim(new swim() {@Overridepublic void swiming() {System.out.println("老师游完用了10秒");}});//打印结果:开始游泳\n老师游完用了10秒}//创建游泳比赛方法public static void swim(swim s){System.out.println("开始游泳");s.swiming();}
}
//定义接口和游泳方法用于创建匿名内部类
interface swim{void swiming();
}

3)使用场景1-传输匿名内部类对象给方法使用

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class Test3 {public static void main(String[] args) {//创建窗口JFrame jf = new JFrame("登录窗口");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setBounds(100,100,500,300);jf.setVisible(true);jf.setLayout(null);//创建登录按钮JButton jb = new JButton("登录");jb.setBounds(200,200,100,50);//在窗口中添加登录按钮jf.add(jb);//给登录按钮添加监听器,点击时候执行代码//匿名内部类的使用场景:调用别人的方法实现需求时(监听点击按钮的动作),该方法正好允许传输一个匿名内部类对象给方法使用jb.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("登录成功!");}});}
}

4)使用场景2-使用comparator接口

使用comparator接口的匿名内部类实现对数组的排序
需求:有一个学生数组,存储了学生的姓名的分数,需要对分数高低进行排序

创建学生信息类:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private double score;
}

创建数组初始化数据并排序:

import java.util.Arrays;
import java.util.Comparator;public class Test4 {public static void main(String[] args) {//创建一个Student数组Student[] s = new Student[5];//创建5个Student对象s[0] = new Student("张三", 73);s[1] = new Student("李四", 85);s[2] = new Student("王五", 92);s[3] = new Student("赵六", 66);s[4] = new Student("孙七", 97);//调用sun公司提供的sort方法对数组s进行排序//参数一:需要排序的数组//参数二:声明一个匿名内部类,实现Comparator接口,重写compare方法:定义排序规则Arrays.sort(s, new Comparator<Student>() {@Override//传入两个Student对象,比较两个Student对象的score属性,并返回结果public int compare(Student s1, Student s2) {//当左边减去右边的值为正数时,返回正数,表示s1比s2大//当左边减去右边的值为负数时,返回负数,表示s1比s2小//当左边减去右边的值为0时,返回0,表示s1和s2相等return (s1.getScore() - s2.getScore()); //升序排序,降序排序改为s2.getScore() - s1.getScore()即可}});System.out.println("排序后的结果:");for (int i = 0; i < s.length; i++) {System.out.println(s[i]);}}
}

三、Lambda函数

1.理解Lambda函数

JDK8新增的一种语法形式,表示函数。用于替代【函数式接口】的匿名内部类对象,使程序更简洁。
函数式接口:有且仅有一个抽象方法的接口

语法示例:

public class LambdaDemo1 {public static void main(String[] args) {//常规方式:创建匿名内部类实现函数式接口(创建接口对象)/*swim s = new swim() {@Overridepublic void swiming() {System.out.println("开始游泳");}};s.swiming();*///使用Lambda表达式swim s = () -> {System.out.println("开始游泳");};s.swiming();}
}
//声明函数式接口的注解,当接口中的抽象方法唯一时,可以省略
//作用:更安全,保证接口中只有一个抽象方法,否则会报错
@FunctionalInterface
interface swim {void swiming();
}

2.Lambda表达式的省略规则

①参数类型可以全部不写
②如果只有一个参数,省略参数类型的同时还可以省略参数的括号(),但多个参数不能省略括号()
③如果lambda表达式中只有一行代码,还可以省略大括号和这行代码的分号,若这行代码是return语句,则必须省略掉return

示例1,通过lambda表达式简化2.5.4中对数组的排序功能:

public class Test4 {public static void main(String[] args) {//创建一个Student数组Student[] s = new Student[5];//创建5个Student对象s[0] = new Student("张三", 73);s[1] = new Student("李四", 85);s[2] = new Student("王五", 92);s[3] = new Student("赵六", 66);s[4] = new Student("孙七", 97);//调用sun公司提供的sort方法对数组s进行排序//参数一:需要排序的数组//参数二:声明一个匿名内部类,实现Comparator接口,重写compare方法:定义排序规则Arrays.sort(s, new Comparator<Student>() {@Override//传入两个Student对象,比较两个Student对象的score属性,并返回结果public int compare(Student s1, Student s2) {//当左边减去右边的值为正数时,返回正数,表示s1比s2大//当左边减去右边的值为负数时,返回负数,表示s1比s2小//当左边减去右边的值为0时,返回0,表示s1和s2相等return (s1.getScore() - s2.getScore()); //升序排序,降序排序改为s2.getScore() - s1.getScore()即可}});//使用lambda表达式进行简化:将方法参数替换匿名内部类Arrays.sort(s, (Student s1, Student s2) -> {return s1.getScore() - s2.getScore();});//继续简化:省略参数类型的写法Arrays.sort(s, (s1,s2) -> {return s1.getScore() - s2.getScore();});//继续简化:省略return 和 {}Arrays.sort(s, (s1,s2) -> s1.getScore() - s2.getScore());System.out.println("排序后的结果:");for (int i = 0; i < s.length; i++) {System.out.println(s[i]);}}
}

示例2,通过lambda表达式简化2.5.3中监听点击按钮功能

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class Test3 {public static void main(String[] args) {//创建窗口JFrame jf = new JFrame("登录窗口");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setBounds(100,100,500,300);jf.setVisible(true);jf.setLayout(null);//创建登录按钮JButton jb = new JButton("登录");jb.setBounds(200,200,100,50);//在窗口中添加登录按钮jf.add(jb);//给登录按钮添加监听器,点击时候执行代码//匿名内部类的使用场景:调用别人的方法实现需求时(监听点击按钮的动作),该方法正好允许传输一个匿名内部类对象给方法使用jb.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("登录成功!");}});//使用lambda表达式简化:将方法参数替换匿名内部类jb.addActionListener((ActionEvent e) -> {System.out.println("登录成功!");});//继续简化:省略参数类型且只有一个参数时可以省略参数括号jb.addActionListener(e -> {System.out.println("登录成功!");});//继续简化:省略{}jb.addActionListener(e -> System.out.println("登录成功!"));}
}

3.静态方法引用

当lambda表达式中只是调用一个静态方法且箭头"->"前后的参数一致时,即可使用静态方法引用

以2.5.4的数组排序为例,将排序功能由程序入口改为封装在父类中作为静态方法,通过lambda静态方法引用

创建学生父类并定义对数组排序的静态方法:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private int score;//定义静态方法对数组元素(分数)进行排序public static int compareScore(Student s1,Student s2){return s1.getScore() - s2.getScore();}
}

lambda静态方法引用示例:

import java.util.Arrays;public class Test4 {public static void main(String[] args) {//创建一个Student数组Student[] s = new Student[5];//创建5个Student对象s[0] = new Student("张三", 73);s[1] = new Student("李四", 85);s[2] = new Student("王五", 92);s[3] = new Student("赵六", 66);s[4] = new Student("孙七", 97);/* 调用Arrays的sort方法对数组s进行排序* 当lambda表达式里只有一个静态方法且箭头前后的参数类型一致时,可使用静态方法引用简化Arrays.sort(s,(s1,s2) -> Student.compareScore(s1,s2));*///优化写法:lambda引用静态方法(类名::静态方法名)Arrays.sort(s,Student::compareScore);System.out.println("排序后的结果:");for (int i = 0; i < s.length; i++) {System.out.println(s[i]);}}
}

4.实例方法引用

当lambda表达式中只是通过对象名调用一个实例方法且箭头"->"前后的参数一致时,即可使用实例方法引用

创建学生父类并定义对数据排序的实例方法:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private int score;private double height;//定义静态方法对数组元素进行排序public static int compareScore(Student s1,Student s2){return s1.getScore() - s2.getScore();}//定义实例方法对数组元素(身高)进行排序public int compareHeight(Student s1,Student s2){//不能直接调用s1.getHeight() - s2.getHeight(),因为getHeight()返回的是double类型//也不能使用int强转s1.getHeight() - s2.getHeight()的结果,例如:(int)s1.getHeight() - s2.getHeight()//当171.2-171时,结果会被强转为0,而不是1,导致排序失败//正确写法:使用Double.compare()方法return Double.compare(s1.getHeight(),s2.getHeight());}
}

lambda实例方法引用示例:

import java.util.Arrays;public class Test5 {public static void main(String[] args) {//创建一个Student数组Student[] s = new Student[5];//创建5个Student对象s[0] = new Student("张三", 73,180);s[1] = new Student("李四", 85,170);s[2] = new Student("王五", 92,183.5);s[3] = new Student("赵六", 66,155);s[4] = new Student("孙七", 97,168);//创建对象Student temp = new Student();/*调用Arrays的sort方法对数组s进行排序*当lambda表达式中只是通过对象调用一个实例方法,且箭头"->"前后参数类型一致时,可使用实例方法引用简化Arrays.sort(s, (s1, s2) -> temp.compareHeight(s1, s2));*///lambda实例方法引用写法:对象名::实例方法名Arrays.sort(s, temp::compareHeight);System.out.println("排序后的结果:");for (int i = 0; i < s.length; i++) {System.out.println(s[i]);}}
}

5.特定类型的方法引用

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

需求1:创建一个字符串数组,对数组中的名字进行字符串排序:

import java.util.Arrays;public class Test {public static void main(String[] args) {String[] name = { "Angela", "jack", "Tom", "allen", "bob" , "lucy" , "Zac", "Mike", "jerry"};Arrays.sort(name);System.out.println(Arrays.toString(name));//排序结果:[Angela, Mike, Tom, Zac, allen, bob, jack, jerry, lucy]//默认排序规则:按照字符串的ASCII码值进行排序,导致大写字符串排前面,小写字符串排后面//当jack, jerry都是j开头时,第二位e比a的ASCII码值大,所以jack排前面,jerry排后面}
}

需求2:忽略字符串的首字母大小写进行排序(大写A和小写a都拍到最前面)

import java.util.Arrays;
import java.util.Comparator;public class Test {public static void main(String[] args) {String[] name = { "Angela", "jack", "Tom", "allen", "bob" , "lucy" , "Zac", "Mike", "jerry"};Arrays.sort(name, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {//调用String类中的compareToIgnoreCase方法可以实现忽略大小写的排序return o1.compareToIgnoreCase(o2);}});System.out.println(Arrays.toString(name));//打印结果:[allen, Angela, bob, jack, jerry, lucy, Mike, Tom, Zac]}
}

需求3:将需求2的实现代码使用lambda特定类型方法引用进行简化

import java.util.Arrays;public class Test {public static void main(String[] args) {String[] name = { "Angela", "jack", "Tom", "allen", "bob" , "lucy" , "Zac", "Mike", "jerry"};/*默认实现方式Arrays.sort(name, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {//调用String类中的compareToIgnoreCase方法可以实现忽略大小写的排序return o1.compareToIgnoreCase(o2);}});*//*改为lambda表达式的简化结果:Arrays.sort(name, (o1,o2) -> o1.compareToIgnoreCase(o2));* 同时符合以下情况,可使用特定类型方法引用进一步简化* 1.表达式中调用一个特定类型的实例方法(compareToIgnoreCase为特定类型String的方法)* 2.箭头前面第一个参数作为后面方法的主调(o1做为compareToIgnoreCase方法的主调)* 3.后面参数作为方法入参(o2作为compareToIgnoreCase方法参数)*///改为lambda特定类型的方法引用进一步简化,写法:特定类名称::方法名Arrays.sort(name, String::compareToIgnoreCase);System.out.println(Arrays.toString(name));//打印结果:[allen, Angela, bob, jack, jerry, lucy, Mike, Tom, Zac]}
}

6.构造器引用

使用场景:如果lambda表达式中只是在创建对象,并且箭头"->"前后的参数一致,就可以使用构造器引用

造例子体现lambda构造器引用:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;public class Test2 {public static void main(String[] args) {/*创建接口的匿名内部类对象实现接口CreateCar cc = new CreateCar() {@Overridepublic Car create(String name) {return new Car();}};*///使用lambda表达式简化匿名内部类//CreateCar cc = name -> new Car();//继续使用lambda构造器引用简化,语法:类名::newCreateCar cc = Car::new;//创建汽车Car c = cc.create("保时捷");System.out.println(c);}
}
//创建函数式接口定义创建汽车的抽象方法
@FunctionalInterface
interface CreateCar{Car create(String name);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
//创建汽车类
class Car{private String name;
}

四、常用API

1.String

作用:创建字符串对象,封装要处理的字符串,或提供方法处理字符串内容

1)使用String封装字符串的几种语法

public class StringDemo1 {public static void main(String[] args) {//常用方式一:字面量定义字符串,直接使用""即可创建字符串对象,封装字符串数据String s1 = "hello";//不常用方式:通过构造器创建字符串对象String s2 = new String(); //创建一个空字符串对象,不推荐的使用方式String s3 = new String("hello"); //创建一个字符串对象,封装字符串数据,不推荐使用//根据字符数组创建字符串对象char[] c = {'h','e','l','l','o'};String s4 = new String(c);System.out.println(s4); //打印结果:hello//根据字节数组创建字符串对象byte[] b = {104,101,108,108,111}; //hello对应的ASCII码String s5 = new String(b);System.out.println(s5); //打印结果:hello}
}

2)不同方式创建String对象的区别:通过常用方式" "创建的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份;通过new方式创建的字符串对象,每new一次都会产生一个新的对象放在堆内存中

public class StringDemo2 {public static void main(String[] args) {String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2); //打印结果: true//原因:直接创建字符串对象,字符串对象放在字符串常量池中,且内容相同的字符串只存一个,所以s1和s2指向同一内存地址//目的:节约内存空间,提高效率String s3 = new String("hello");String s4 = new String("hello");System.out.println(s3 == s4); //打印结果: false//原因:new创建字符串对象,字符串对象放在堆内存中,每new一次,就会创建一个对象,所以s3和s4指向不同的内存地址}
}

3)调用String的方法, 处理字符串数据
在这里插入图片描述
注意:
①对比两个字符串的值是否一致不能使用 ==,例如接收输入内容时创建的字符串对象与系统进行内容对比的字符串对象内存地址不同,尽管两个字符串的值相同,对比结果也只能是false;使用equals方法对比则只关注两个字符串的内容,不关心内存地址。
②比对验证码是否一致的场景中需要忽略大小写时,则推荐使用equalsIgnoreCase方法

4)案例:实现验证码生成
需求:随机生成验证码,验证码可能是数字、大写字母或小写字母

public class StringDemo3 {public static void main(String[] args) {System.out.println(getRandomCode(6));}//随机生成验证码public static String getRandomCode(int n) {//定义空字符串用于拼接生成的随机字符String code = "";//定义验证码所需的字符集String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";//根据入参的整数循环生成n位随机字符for (int i = 0; i < n; i++) {//生成随机索引int index = (int)(Math.random() * str.length()); // [0,1) * [0,62) = [0,61]//拼接随机字符code += str.charAt(index);}return code;}
}

2.ArrayList

1)什么是集合?
集合属于一种容器,用来装数据,类似数组。但数组长度一开始就固定了,集合的大小可动态变更,ArrayList则是一种常用的集合。属于泛型类,可以通过<>中的内容约束存储的数据类型,使用方式:先调用ArrayList的无参构造器创建集合对象,然后使用增删改查的对应方法操作集合。

import java.util.ArrayList;public class ArrayListdemo {public static void main(String[] args) {//创建集合,若<>中没有指定数据类型,则可以存入任意数据类型ArrayList<String> list = new ArrayList<>();//添加数据list.add("张三");list.add("李四");list.add("王五");list.add("赵六");//遍历集合查询数据for (int i = 0; i < list.size(); i++) { //获取集合的长度System.out.println(list.get(i)); //根据索引获取集合中的元素}//修改数据list.set(0, "小张");  //set方法:修改集合中索引为0的元素System.out.println(list.get(0));//删除数据方式1,通过索引删除list.remove(0);//删除数据方式2,通过元素值删除list.remove("赵六");}
}

2)ArrayList的常用方法:
在这里插入图片描述

五、GUI编程

1.GUI是什么?

1)GUI:Graphical User Interface 图形用户界面,使用较少,并非主流,设计一个界面代码臃肿。
2)通过图形元素(窗口、按钮、文本框等)与用户进行交互
3)与命令行界面(CLI)相比,GUI更直观、友好
4)Java提供了两套GUI编程库:AWT(Abstract Window Toolkit)抽象窗口工具集,提供一组原生GUI组件,但依赖操作系统的本地窗口系统,例如在Windows能运行在macOS就无法运行,逐渐淘汰。Swing:基于AWT,提供了更丰富份GUI组件,不依赖本地窗口系统
5)常用是Swing组件:JFrame(窗口)、JPanel(放在窗口中的面板或画布,用于组织其他组件的容器)、JButton(按钮)、JTextField(输入框)、JTable(表格)……

2.常见的布局管理器

作用:决定组件在容器中的布局方式,避免手动设置每个组件的位置和大小,简化GUI设计过程

1)FlowLayout:最简单的布局管理器,它按水平方向从左到右排列组件,当一行排满时,自动换到下一行
特点:默认居中对齐,可以设置为左对齐或右对齐,适用于需要简单排列的场景

import javax.swing.*;
import java.awt.*;public class FlowLayoutDemo {public static void main(String[] args) {JFrame jf = new JFrame("流式布局"); //创建窗体jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭模式:点击X退出时关闭程序jf.setSize(400,300); //设置窗体大小jf.setVisible(true); //显示窗体jf.setLayout(new FlowLayout()); //设置窗体的布局管理器jf.add(new JButton("登录")); //添加按钮jf.add(new JButton("注册")); //添加按钮jf.add(new JButton("忘记密码")); //添加按钮jf.add(new JButton("帮助")); //添加按钮jf.add(new JButton("关于")); //添加按钮jf.add(new JButton("退出")); //添加按钮}
}

界面效果:
在这里插入图片描述

2)BorderLayout:将容器划分为五个区域:东、南、西、北和中(East, South,West,North,center),每个区域只能添加一个组件,未添加组件的区域保持空白
特点:适用于需要在特定区域布局组件的场景,中间区域会占据所有剩余的空间

import javax.swing.*;
import java.awt.*;public class BorderLayoutDemo {public static void main(String[] args) {JFrame jf = new JFrame("边界布局");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setSize(400,300);jf.setVisible(true);jf.setLayout(new BorderLayout());jf.add(new JButton("上"),BorderLayout.NORTH);jf.add(new JButton("下"),BorderLayout.SOUTH);jf.add(new JButton("左"),BorderLayout.WEST);jf.add(new JButton("右"),BorderLayout.EAST);jf.add(new JButton("中间"),BorderLayout.CENTER);}
}

界面效果:
在这里插入图片描述

3)GridLayout:将容器划分为等大小的网格,每个网格中可以添加一个组件,所有组件大小相同
特点:适用于需要均匀排列组件的场景,行和列的数量可以指定

import javax.swing.*;
import java.awt.*;public class GridLayoutDemo {public static void main(String[] args) {JFrame jf = new JFrame("网格布局");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setSize(400,300);jf.setVisible(true);jf.setLayout(new GridLayout(3,2)); // 3行2列jf.add(new JButton("1"));jf.add(new JButton("2"));jf.add(new JButton("3"));jf.add(new JButton("4"));jf.add(new JButton("5"));jf.add(new JButton("6"));}
}

界面效果:
在这里插入图片描述

4)BoxLayout:能够沿着单一轴线(X轴或Y轴)排列组件,可以创建水平(X轴)或垂直(Y轴)排列的布局
特点:适用于需要沿单一方向排列组件的场景,可以通过添加垂直或水平间隔(Glue、strut)来调整组件间距

public class BoxLayoutDemo {public static void main(String[] args) {JFrame jf = new JFrame("盒子布局");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setSize(400,300);jf.setVisible(true);JPanel jp = new JPanel(); //创建面板(容器)jp.setLayout(new BoxLayout(jp,BoxLayout.Y_AXIS)); // 垂直布局//添加按钮和垂直间隔jp.add(new JButton("登录"));jp.add(Box.createVerticalStrut(10));jp.add(new JButton("注册"));jp.add(Box.createVerticalStrut(10));jp.add(new JButton("忘记密码"));jp.add(Box.createVerticalStrut(10));jp.add(new JButton("帮助"));jp.add(Box.createVerticalStrut(10));//添加面板到窗口jf.add(jp);}
}

界面效果:
在这里插入图片描述

3.事件处理

GUI编程中,事件(点击按钮)的处理是通过事件监听器(EventListener)来完成的
常用的时间监听器对象:点击事件监听器 ActionListener、按键事件监听器 KeyListener、鼠标行为监听器 MouseListener

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;public class Test {public static void main(String[] args) {//创建登录窗口JFrame jf = new JFrame("登录窗口");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setBounds(100,100,500,300);jf.setVisible(true);//创建登录按钮JButton jb = new JButton("登录");jb.setBounds(200,200,100,50);//在窗口中添加登录按钮jf.add(jb);//给登录按钮添加监听器,点击时候执行代码jb.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//点击按钮弹框显示登录成功JOptionPane.showMessageDialog(jf,"登录成功!");//弹框完成后设置主窗口为焦点接收键盘事件jf.requestFocus();}});//给窗口添加按键事件监听器,监听用户输入的上下左右按键jf.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {//根据点击的键盘按键,判断用户输入的按键switch (e.getKeyCode()) {case KeyEvent.VK_UP:System.out.println("用户按了上键!");break;case KeyEvent.VK_DOWN:System.out.println("用户按了下键!");break;case KeyEvent.VK_LEFT:System.out.println("用户按了左键!");break;case KeyEvent.VK_RIGHT:System.out.println("用户按了右键!");break;default:System.out.println("用户按下了非上下左右键!");break;}}});}
}

4.事件的几种常用写法

第1种:直接使用匿名内部类的对象,代表事件监听对象,参考3.事件处理中的写法

第2种:直接提供实现类,用于创建事件监听对象

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class Test2 {public static void main(String[] args) {//创建登录窗口JFrame jf = new JFrame("登录窗口");jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setBounds(100, 100, 500, 300);jf.setVisible(true);//创建登录按钮JButton jb = new JButton("登录");jb.setBounds(200, 200, 100, 50);//在窗口中添加登录按钮jf.add(jb);//给登录按钮添加监听器,点击时候执行代码jb.addActionListener(new AL(jf));}
}
//创建点击按钮监听器的实现类
class AL implements ActionListener {//创建成员变量private JFrame jf;//创建有参构造方法,传入JFrame对象public AL (JFrame jf) {this.jf = jf;};@Overridepublic void actionPerformed(ActionEvent e){//弹窗提示登录成功JOptionPane.showMessageDialog(jf, "登录成功!");}
}

第3种:自定义窗口,让窗口对象实现事件接口(实际开发一个页面时,可为每个页面设计一个类,继承JFrame并实现ActionListener接口)

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//自定义登录界面继承窗体类并实现ActionListener接口
public class LoginInterface extends JFrame implements ActionListener {//创建登录窗口public LoginInterface() {setTitle("登录窗口");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100, 100, 500, 300);setVisible(true);//创建登录按钮JButton jb = new JButton("登录");jb.setBounds(200, 200, 100, 50);//初始化组件init();}private void init() {//创建面板JPanel jp = new JPanel();//创建登录按钮JButton jb = new JButton("登录");jb.setBounds(200, 200, 100, 50);//在面板中添加登录按钮jp.add(jb);//在窗口中添加面板add(jp);//给登录按钮添加监听器,点击时候执行代码jb.addActionListener(this);}@Overridepublic void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog(this, "登录成功!");}
}
http://www.dtcms.com/a/313701.html

相关文章:

  • LeetCode - 合并两个有序链表 / 删除链表的倒数第 N 个结点
  • 三角洲行动ACE反作弊VT-d报错?CPU虚拟化如何开启!
  • MySQL架构全面理解
  • 克罗均线策略思路
  • 无刷电机母线电容计算
  • SpringBoot AI自动化测试实战案例
  • 大模型能力测评(提示词请帮我把这个项目改写成为python项目)
  • 译|数据驱动智慧供应链的构成要素与关联思考
  • 死锁深度解析:原理、检测与解决之道
  • C++ <type_traits> 应用详解
  • 志邦家居PMO负责人李蓉蓉受邀为PMO大会主持人
  • 【深度学习新浪潮】谷歌新推出的AlphaEarth是款什么产品?
  • ZStack Cloud 5.3.40正式发布
  • 《测试驱动的React开发:从单元验证到集成协同的深度实践》
  • JAVA中的String类方法介绍
  • 【Bluetooth】【Transport层篇】第三章 基础的串口(UART)通信
  • 智能图书馆管理系统开发实战系列(六):Google Test单元测试实践
  • SAP 服务号传输(同环境的不同客户端SCC1,跨环境的STMS)
  • 一个网页的加载过程详解
  • lua中 list.last = last 和list[last]=value区别
  • C语言实现猜数字游戏
  • 多模态大模型综述:BLIP-2详解(第二篇)
  • 问题集000
  • 图像张量中的通道维度
  • 力扣经典算法篇-41-旋转图像(辅助数组法,原地旋转法)
  • Kubernetes中ingess以及它和nginx的关系
  • 单表查询-模糊匹配
  • CMake 命令行参数完全指南(4)
  • sqli-labs靶场less26/a
  • awk对文本进行列处理