java复习笔记

记录暑假实习期间java复习笔记-随机更新

Posted by hangyangjun on July 12, 2025

参考:10分钟速成JavaJavaGuideProJAVA基础——接口
话说真是忘了太彻底了,和新学一样

基础中的基础

长期支持的java版本:8、11、17、21
JDK - java development kit
包含:代码编译器javac、运行环境jre、其他工具
编译器负责将java源文件编译为字节码文件(.class)给jre执行
jre中的jvm将字节码转换为不同设备上的机器码并执行

.java文件由类构成,类名应与文件同名,如下固定格式设置 main 方法

1
2
3
4
5
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello,World!");
    }
}
  • (String[] args):参数列表,接收一个字符串数组,用于传递命令行参数。
  • static:静态修饰符,表示该方法属于类本身,而非类的实例。因此,调用时无需创建对象。

在终端中:
javac HelloWorld.java 编译
得到字节文件 HelloWorld.class
java+类名 的方式运行文件:java HelloWorld

有关强制类型转换

1
System.Out.println((double)10 / 3)

变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int num = 10;
double num2;
num2 = 20.2;
final int num3 = 30; //变量不可修改
byte num4 = 127;//8位
short num5 = 32767;//16位
long num6 = Long.MAX_VALUE;//64位 最大9,223,372,036,854,775,807
float num7 = 100.3F;//32位单精度浮点
char char1 = 'a';//字符型
boolean b = true;//布尔

//字符串
String string1 = "abc";
String string2 = new String("qwe");//构造函数的方式声明
//字符串可以通过 + 连接 .length()方法获取字符串长度

String str3 = "abc" + "-" + "qwe" + "-" + "666";
System.out.println(str3.indexOf("qwe"));//通过indexOf查找(子串)的位置(输出4-当然从零开始的下标)
//replace("qwe", "rty")替换子串
System.out.println(String.join("~",str3.split("-")));
//通过join()连接由split分割的str3 分割条件为- 连接之间添加~

条件判断和循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
System.out.println(b ? 1 : 2);//三目运算

if (num4 >= 100) {
    System.out.println("6");
} else {
    System.out.println("666");
}

switch (num) {
    case 1:
        System.out.println("666");
        break;
    default:
        System.out.println("66");
}

for (int i = 0; i < 10 ; i++) {
    System.out.println(i);
}

int i =0;
while (i<10){
    System.out.println("6666");
    i++;
}

do {
    System.out.println("6666");
    i++;
}while (i<10);

数组

1
2
3
4
5
    int [] aa = {1, 2, 3};//完整int [] aa = new int[3] {1, 2, 3};
    int [] bb = new int[3];//元素个数声明后无法更改
    System.out.println(Arrays.toString(aa));//注意输出需转换
    System.out.println(aa[0]);//通过索引访问
    int [] cc = Arrays.copyOf(aa, 5);//复制数组,改变长度

类 — 对一类事物的抽象

具体的:实例对象
抽象的:类

面向对象的三步操作:封装 继承 多态

  • 封装(Encapsulation) 是指将数据(属性)和操作数据的方法(行为)绑定在一起,并通过访问控制修饰符(如private、public)限制外部对数据的直接访问。封装的核心目标是隐藏对象的内部实现细节,仅对外提供必要的接口,从而提高代码的安全性、可维护性和复用性。
  • 继承是 extends
  • 多态是一个方法多个效果

创造对象
在 Java 中,类型 名称 = new 对象; 这种写法是创建和使用对象的核心方式

  • 左边:声明一个引用变量(reference variable),它存储的是对象在内存中的地址(类似指针),而不是对象本身。
  • 右边:在堆内存中创建一个实际的对象实例,并返回该对象的内存地址。

以下是一个综合例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package org.example;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Animal("dog",10);//new Animal()创建实例对象

        a1.print();//调用
        System.out.println(a1.getName());//通过getter函数获取名字
        a1.setName("cat");//setter函数更新名字
        System.out.println(a1.getName());//获取名字

        Cat c1 = new Cat("圆头耄耋", 6 ,"黄");//new了子类对象(创建一个 Cat 类的对象实例,并调用其构造方法进行初始化)
        a1.say();
        c1.say();//这就是多态

        a1.eat();
        c1.eat("欧润橘");//这也是多态
    }

}

class Animal { //class+类名创建类
    private String name = "66";//默认值,private时,外部获取会报错
    int age = 5;

    public Animal (String name, int age) { //与类同名的构造方法,进行值的接收
        this.name = name;
        this.age = age;//this代表实例
    }

    void print () {
        System.out.println(name + age);
    }

    public String getName () {//getter函数,方便外部获取值
        return this.name;
    }

    public void setName (String newValue1) { //setter函数
        this.name = newValue1;//更改name值
    }

    public void eat () {//更多功能
        System.out.println("您的"+this.name+"正在吃屎!");
    }
    public void say () {
        System.out.println("大狗叫");
    }
}

class Cat extends Animal {//子类,继承。故意保留了一部分Animal的味道让你知道我使用了继承。
    private String color = "";//Cat 类的私有成员变量

    public Cat(String name, int age, String color) {//构造,添加了新的熟悉color
        super(name, age);//super 关键字:显式调用父类 Animal 的构造方法,将参数传递给父类初始化。
        this.color = color;
    }

    @Override//重写方法(多态方式一)多态
    public void say() {
        System.out.println(color+"色"+"哈基咪");
    }
    public void eat(String food) {//重载(多态方法二)与原方法同名但参数不同
        System.out.println("您的"+ this.getName() +"正在吃"+food+"!");//使用父类方法
    }
}

更进一步

接口 - interface

巴拉巴拉:

Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)

有接口是因为Java不像C++一样支持多继承,但是接口在实际中更多的作用是制定标准.

一个类可以实现不止一个接口。

一个接口可以继承于另一个接口,或者另一些接口,接口也可以继承,并且可以多继承。

一个类如果要实现某个接口的话,那么它必须要实现这个接口中的所有方法。

接口中所有的方法都是抽象的和public的,所有的属性都是public,static,final的。

接口也可以用来实现解耦。
解耦:抽象层次上的依赖关系使得各个组件之间的耦合度降低,从而更容易地进行修改和替换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class test2 {
    interface i1{
        final int a = 10;
        void display();
    }

    static class tell_666 implements i1 {//静态类
        @Override
        public void display() {
            System.out.println("666");
        }

        public void display2() {
            System.out.println("六百六十六");
        }
    }
    
    public static void main (String[] args){
        tell_666 t = new tell_666();//具体类类型引用
        i1 t2 = new tell_666();//注意! 接口类型引用,只能访问 i1 接口中声明的方法,无法直接访问 tell_666 类特有的方法
        t.display();
        
        ((tell_666)t2).display2();//此时需要强制类型转换才能调用YouPan类特有的方法
        System.out.println(i1.a);//访问接口i1的常量a
    }
}

回调函数 - Callback

在 Java 中,回调函数是一种通过接口实现的编程模式,允许将一个方法作为参数传递给另一个方法,在某个事件发生或条件满足时被调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package org.example;

interface Callback {// 回调接口
    void onComplete(String result); // 回调方法
}

class Task {
    public void execute(Callback callback) {
        // 模拟耗时操作
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 操作完成后调用回调
        String result = "任务完成";
        callback.onComplete(result);
    }
}

public class Main {
    public static void main(String[] args) {
        Task task = new Task();

        // 实现回调接口(匿名内部类)
        task.execute(/*
            new Callback() { //这里传递的是一个匿名内部类对象,它实现了Callback接口。
                @Override
                public void onComplete(String result) {
                    System.out.println("收到结果: " + result);
                }
            } */

            //下面是Lambda 表达式简化版,用于简化函数式接口(只有一个抽象方法的接口)的实现
            result -> {
                System.out.println("收到结果: " + result);
            }
        );//Lambda 的本质:自动创建一个实现了Callback接口的匿名类实例,并将 Lambda 体作为接口方法的实现。

        System.out.println("主线程继续执行...");
    }
}

Java 的回调机制看似复杂,实则是为了在类型安全和灵活性之间取得平衡。
回调允许代码在运行时动态决定执行哪个方法,而不是在编译时硬编码。
在处理耗时操作(如网络请求、文件读写)时,回调避免了线程阻塞。
回调是事件监听模式的基础,广泛用于 GUI、消息队列等场景。

一个综合例子——短信服务商

一个典型的适配器模式(Adapter Pattern) 示例,核心目的是解决 “不同接口的类无法直接兼容” 的问题。而且更灵活,修改更方便。

简单说,适配器就像 “转换插头”—— 不同国家的插座(第三方服务)接口不同,但通过转换插头(适配器),都能在同一台设备(系统)上使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.example;

// 短信服务接口
interface CommonSmsServiceInterface {
    void sendLoginSMS(String phoneNumbers, String message);
}

// 阿里云短信实现-不可修改
class AliyunSMS {
    void sendLoginSMS(String phoneNumbers, String message) {
        System.out.println("【阿里云】登录短信发送给"+phoneNumbers+":"+message);
    }
}

// 腾讯云短信实现-不可修改
class TencentSMS {
    void sendLoginSMS(String message, String phoneNumbers) {
        System.out.println("【腾讯云】登录短信发送给"+phoneNumbers+":"+message);
    }
}//(阿里云、腾讯云)提供的接口参数顺序不一样

// 阿里云短信服务适配器
class AliyunSmsServiceInterfaceImpl implements CommonSmsServiceInterface {
    private final AliyunSMS aliyunSMS;// 持有第三方服务的引用
    public AliyunSmsServiceInterfaceImpl(AliyunSMS aliyunSMS) {//// 构造方法传入阿里云实例
        this.aliyunSMS = aliyunSMS;
    }
    @Override public void sendLoginSMS(String phoneNumbers, String message) {
        aliyunSMS.sendLoginSMS(phoneNumbers, message);// 实现统一接口:直接调用阿里云方法(参数顺序一致)
    }
}

// 腾讯云短信服务适配器
class TencentSmsServiceInterfaceImpl implements CommonSmsServiceInterface {
    private final TencentSMS tencentSMS;
    public TencentSmsServiceInterfaceImpl(TencentSMS tencentSMS) {
        this.tencentSMS = tencentSMS;
    }
    @Override public void sendLoginSMS(String phoneNumbers, String message) {
        tencentSMS.sendLoginSMS(message, phoneNumbers);// 这里交换了参数
    }
}//适配器的作用是 “包装” 第三方服务,让它们符合 CommonSmsServiceInterface 标准。

public class test20 {
    public static void main(String[] args) {
        // 使用阿里云短信服务
        CommonSmsServiceInterface smsService = new AliyunSmsServiceInterfaceImpl(new AliyunSMS());
        smsService.sendLoginSMS("13800138000", "您的验证码是1234");

        // 切换到腾讯云(只需换适配器,调用代码不变)
        TencentSMS tencentSMS = new TencentSMS();//1
        smsService = new TencentSmsServiceInterfaceImpl(tencentSMS);//2,到时候只需修改这两句和适配器。
        smsService.sendLoginSMS("13800138000", "您的验证码是5678");
    }
}//假设有一百个地方用到这些代码,那么更换短信服务商就变得非常简单了。

适配器模式的核心价值

  • 解耦:系统代码只依赖统一接口,不依赖具体服务商。
  • 兼容:让接口不兼容的类可以一起工作(比如腾讯云的参数顺序问题)。
  • 灵活:切换服务商时,调用代码无需修改(符合 “开闭原则”)。

持有(Holding) 是一种对象间的关系,指一个对象(持有者)内部包含对另一个对象(被持有者)的引用。这种关系通过成员变量实现,使得持有者可以直接访问被持有者的方法和属性。
持有是has-A 继承是is-A

  • 避免类爆炸:如果通过继承修改接口,每个第三方服务都需要创建子类,导致类数量膨胀。
  • 更灵活:持有关系允许在运行时动态更换被持有者(如切换不同的短信服务商)。

适配器类 AliyunSmsServiceInterfaceImpl 通过成员变量 private final AliyunSMS aliyunSMS 持有阿里云服务的引用

Lambda

Lambda 表达式本质上是一个匿名函数,它允许你将函数作为参数传递给方法,或者将代码作为数据进行处理。

基本语法如下:

1
2
3
(parameters) -> expression
或
(parameters) -> { statements; }
  • parameters:表示 Lambda 表达式的参数列表,可以为空。
  • ->:箭头符号,用于分隔参数列表和 Lambda 表达式的主体。
  • expression:如果 Lambda 表达式的主体只有一条语句,可以直接使用表达式。
  • { statements; }:如果 Lambda 表达式的主体包含多条语句,需要使用花括号将语句括起来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package org.example;

class Main {
    public static void main(String[] args) {
        // 传统方式创建 Runnable 实例
        Runnable r1 = new Runnable() { //Runnable:Java 中内置的接口,用于表示一个可执行的任务,只有一个 run() 方法
            @Override
            public void run() {
                System.out.println("传统方式执行任务");
            }
        };

// 使用 Lambda 表达式创建 Runnable 实例
        Runnable r2 = () -> System.out.println("Lambda 方式执行任务");

// 启动线程
        new Thread(r1).start();
        new Thread(r2).start();
    }
}

精通:Java 中的 Lambda 表达式:从入门到精通