类中的五大成分:成员变量、构造器、成员方法、代码块、内部类。
JDK8开始,新增的代码编程:函数式编程。
代码块:是类的五大成分之一。
代码块分为两种:
① 静态代码块
格式:static{ }
——属于类
特点:类加载时自动执行,由于类只加载一次,所以静态代码块也只会执行一次。
作用:完成类的静态资源数据初始化。静态代码块中的代码实际上是在方法区(Method Area)执行的。
例如:对静态变量的初始化赋值。例如类的静态数组变量定义之后,可以在静态代码块中初始化。(比在main中初始化更加优雅,是最佳实践)
② 实例代码块:
格式:{ }
——属于对象
特点:每次创建对象时,执行实例代码块,并在构造器前执行。与构造器一样,实例初始化代码块也是在堆上执行的,因为它涉及到对实例成员的初始化。
作用:和构造器一样,都是用来完成对象实例资源的初始化的。例如:对实例变量进行初始化赋值。
public class CodeDemo1 {
public static String schoolName;
public static String [] cards = new String[5]; // 静态数组
// 静态代码块:有static修饰,属于类,与类一起优先加载,自动执行一次
// 基本作用:可以完成对类的静态资源的初始化
static{
System.out.println("静态代码块执行了"); // 先加载类,再执行main方法
schoolName = "黑马程序员";
cards[0] = "A";
cards[1] = "2";
cards[2] = "3";
cards[3] = "4";
}
public static void main(String[] args) {
// 目标:认识代码块,搞清楚代码块的基本作用。
System.out.println("main方法执行了");
System.out.println(schoolName);
System.out.println(Arrays.toString(cards)); // 返回数组内容观察
}
}
运行结果:
静态代码块执行了
main方法执行了
黑马程序员
[A, 2, 3, 4, null]
public class Codedemo2 {
private String name;
private String [] direction = new String[4]; // 实例变量
// 实例代码块(构造代码块):无static修饰,属于对象,每次创建对象时,都会优先执行一次
// 基本作用:初始化对象的实例资源
{
System.out.println("实例代码块执行了");
name = "张三";
direction[0] = "N";
direction[1] = "S";
direction[2] = "W";
direction[3] = "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));
}
}
运行结果:
main方法执行了
实例代码块执行了
实例代码块执行了
实例代码块执行了
张三
[N, S, W, E]
// 外部类
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;
}
}
}
外部类名.this
;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
}
}
}
public class Outer{
// 静态内部类
public static class Inner{}
}
// 外部类名.内部类名 对象名 = new 外部类.内部类();
// Outer.Inner in = new Outer.Inner(); // 创建静态内部类对象
1、静态内部类中可以直接访问外部类的静态成员;
2、静态内部类中不可以直接访问外部类的实例成员;
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;
}
}
}
public class InnerClassDemo3 {
public static void main(String[] args) {
}
public static void go(){
// 定义在方法中的局部内部类
class A{}
abstract class B{}
interface C{}
}
}
//(先有一个已经存在的类或者接口,参数值通常不写)
new 类或者接口(参数值...){
类体(一般是方法重写);
};
new Animal (){
@Override
public void cry(){
}
}
特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
作用:用于更方便的创建一个子类对象。
匿名内部类实际上是有名字的:外部类名.$编号.class
常见使用形式:(语法)
通常作为一个对象参数传输给方法;
应用场景:
调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用。
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("游泳结束……");
}
}
运行结果:
开始游泳……
学生蛙泳式游泳
游泳结束……
=======================
开始游泳……
老师狗爬式游泳
游泳结束……
(x)-> 2x+1
1、Lambda表达式:JDK8开始新增的一种语法形式,它表示函数。
Lambda表达式提供了一种简洁的方式来表示匿名方法(即没有名称的方法),这些方法可以作为参数传递给其他方法或者存储在变量中。
(被重写方法的形参列表) -> {
被重写方法的方法体代码。
}
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 = () ->{
// System.out.println("猫是喵喵喵~~~~");
// };
// a1.cry();
/* // 3、方法重写,但是可以写成Lambda简化形式
Swim s1 = new Swim() {
@Override
public void swimming() {
System.out.println("学生游泳贼快~~~");
}
};*/
// 4、这个是Lambda表达式简化这个匿名方法
Swim s1 = () ->{
System.out.println("学生游泳贼快~~~");
};
s1.swimming();
}
}
// 抽象类中只含有一个抽象方法
abstract class Animal{
public abstract void cry();
}
// 函数式接口:只有一个抽象方法的接口。
@FunctionalInterface // 声明函数式接口的注解
interface Swim{
void swimming();
// void swimming2(); // 报错
}
Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
lambda实战实例,省略规则(可以参考符合函数式接口规范的接口类型)
Lambda简化comparator,Runnable,Callable 接口的匿名内部类
作用:进一步简化Lambda表达式的写法
lambda表达式省略具体规则:
@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[6];
stus[0] = new Student("殷素素", 35, 171.5, '女');
stus[1] = new Student("赵敏", 18, 168.5, '女');
stus[4] = new Student("金毛狮王", 35, 181, '男');
stus[2] = new Student("周芷若", 18, 172.5, '女');
stus[3] = new Student("张无忌", 25, 170.5, '男');
stus[5] = new Student("小昭", 19, 168.5, '女');
// 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
// 1、方法重写
/*Arrays.sort(stus, new Comparator() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge(); // 按照年龄的升序!
}
});*/
// 2、方法重写可以写成Lambda表达式
// Arrays.sort(stus, (Student o1, Student o2) -> {
// return o1.getAge() - o2.getAge(); // 按照年龄的升序!
// });
// 3、Lambda表达式可以进一步省略
Arrays.sort(stus, (o1, o2) -> o1.getAge() - o2.getAge() );
// 遍历数组中的学生对象并输出
for (int i = 0; i System.out.println("登录成功!!!") );
win.setVisible(true); // 显示窗口
}
}
什么是函数式接口?
@FunctionalInterface
注解(非强制,但建议加上)。函数式接口可以通过Lambda表达式、方法引用或构造器引用来实例化。
@FunctionalInterface
注解,用于声明一个接口为函数式接口。
符合函数式接口规范的接口类型有:
Runnable
Callable
Comparator
Function
, Predicate
, Consumer
等)方法引用:本质上是简化Lambda表达式,当你要传递的方法已经存在时,可以使用方法引用来直接引用已有的方法,而不是通过 Lambda 表达式重新定义。
方法引用(Method Reference)在使用时必须满足“参数一致性”要求,也就是说:
方法引用的目标方法的参数列表和返回类型,必须与函数式接口中抽象方法的参数列表和返回类型兼容。
方法引用包括:
静态方法引用
类名::静态方法
使用场景:如果某个Lambda表达式只是调用一个静态方法,并且“->”前后参数的形式一致,就可以使用静态方法引用。
@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[6];
stus[0] = new Student("殷素素", 35, 171.5, '女');
stus[1] = new Student("赵敏", 18, 168.5, '女');
stus[4] = new Student("金毛狮王", 35, 181, '男');
stus[2] = new Student("周芷若", 18, 172.5, '女');
stus[3] = new Student("张无忌", 25, 170.5, '男');
stus[5] = new Student("小昭", 19, 168.5, '女');
// 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
// Arrays.sort(stus, (o1, o2) -> o1.getAge() - o2.getAge() );
// Arrays.sort(stus, (o1, o2) -> Student.compareByAge(o1, o2) );
// Lambda表达式简化:方法引用 -> 静态方法引用
Arrays.sort(stus, Student::compareByAge);
// 遍历数组中的学生对象并输出
for (int i = 0; i
对象名::实例方法
public class Test2 {
public static void main(String[] args) {
// 目标:实例方法引用
test();
}
public static void test(){
Student[] stus = new Student[6];
stus[0] = new Student("殷素素", 35, 171.5, '女');
stus[1] = new Student("赵敏", 18, 168.5, '女');
stus[4] = new Student("金毛狮王", 35, 181, '男');
stus[2] = new Student("周芷若", 18, 172.5, '女');
stus[3] = new Student("张无忌", 25, 170.5, '男');
stus[5] = new Student("小昭", 19, 168.5, '女');
// 需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
// 实例方法引用要先创建对象,才能引用
Student t = new Student();
// Arrays.sort(stus, (o1, o2) -> t.compareByHeight(o1, o2) );
// 实例方法引用: 对象名::实例方法
Arrays.sort(stus, t::compareByHeight);
// 遍历数组中的学生对象并输出
for (int i = 0; i
特定类的名称::方法
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() {
@Override
public int compare(String o1, String o2) {
// o1 Angela
// o2 Andy
return o1.compareToIgnoreCase(o2); // o1 > o2 返回正数,o1 o1.compareToIgnoreCase(o2) );
// 调用字符串类型的静态方法——特定类型的静态方法 类型名称::方法
Arrays.sort(names, String::compareToIgnoreCase);
System.out.println(Arrays.toString(names));
}
}
类名::new
// 函数式接口
@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表达式 -> Lambda表达式省略
// CarFactory cf = name -> new Car(name) ;
// Lambda表达式简化:方法引用 -> 构造器引用
CarFactory cf = Car::new; ;
Car c1 = cf.create("奔驰");
System.out.println(c1);
}
}
常用API接口:String
String是什么,有什么用?
String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。
String创建字符串对象的方式:
1、创建字符串对象,封装字符串数据
2、调用String提供的操作字符串数据的方法。
String创建对象的区别:
只要是以“”方式写出的字符串对象,会存储到字符串常量池(堆内存中有块区域叫常量池),且相同内容的字符串只存储一份;
通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。
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 ===> 从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);
}
}
ArrayList:归属于集合,是泛型类,可以约束存储的数据类型。
什么是集合?
集合是一种容器,用来装数据的,类似于数组。
有数组,为什么还需要学习集合?
数组定义完成并启动后,长度就固定了;
集合大小可变,功能丰富,开发中用的更多。
集合的种类很多:Set,Map,ArrayList……
ArrayList集合学什么?
1、创建ArrayList对象,代表一个集合容器
2、调用ArrayList提供的方法,对容器中的数据进行增删改查操作。
public class ArrayListDemo1 {
public static void main(String[] args) {
// 目标:掌握ArrayList集合的基本使用。
// 创建ArrayList对象,代表一个集合容器
// ArrayList list = new ArrayList();
// :代表泛型,只能放String类型数据
ArrayList list = new ArrayList(); // 泛型定义集合
// 添加数据
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
GUI编程:GUI(Graphical User Interface ,图形用户界面),是桌面的界面技术,不常用——是为了提高趣味性。
通过图形元素(如窗口、按钮、文本框等)与用户进行交互;
与命令行界面(CLI)相比,GUI更加直观,友好。
为什么学习GUI编程?
增强用户体验;
广泛应用于桌面应用程序开发
java提供了强大的GUI编程支持
java的GUI编程包
AWT(Abstract Window Toolkit,抽象窗口工具集)提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统;
Swing(用这个,不用AWT)基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统。
常用的Swing组件:(前面不加J就是AWT组件)
JFrame:窗口
JPanel:用于组织其他组件的容器
JButton:按钮组件
JTextField:输入框
JTable:表格
布局管理器(Layout Manager)它们可以决定组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。
常见的布局管理器:
FlowLayout:水平布局/垂直布局
BorderLayout:方向布局
GridLayout:网格布局
BoxLayout:盒子布局
GUI编程:事件处理
GUI编程中,事件的处理是通过事件监听器(Event Listener)来完成的。
常用的事件监听器对象:
点击事件监听器 ActionListener
按键事件监听器 KeyListener
鼠标行为监听器 MouseListener
……
事件的几种常见写法:
1、直接提供实现类,用于创建事件监听对象;
2、直接使用匿名内部类的对象,代表事件监听对象
3、自定义窗口,让窗口对象实现事件接口。
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) && "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);
}
}
public static void sort(T[] a, Comparator super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
参与评论
手机查看
返回顶部