本文包含Java 基础语法、面向对象、常用 API、集合、IO、多线程、反射注解、泛型、网络编程、JDBC 数据库全套核心知识点。

一、Java 入门与环境搭建

1.1 什么是 Java

Java 是一门跨平台、面向对象、安全、稳定、支持多线程的编程语言。

通俗理解:

  • 跨平台:一次编写,Windows、Linux、Mac 都能运行
  • 面向对象:代码结构清晰、好维护、好扩展
  • 安全:没有指针,不会随便访问内存
  • 稳定:自带自动内存管理(垃圾回收),程序不容易崩溃
  • 用途:企业后端、安卓 App、大数据、游戏服务器、银行系统都在用

1.2 JDK、JRE、JVM 的区别

JVM(Java 虚拟机)

真正执行 Java 代码的程序。

  • 读取编译后的 .class 字节码
  • 不同系统对应不同 JVM,是跨平台的核心

JRE(Java 运行环境)

运行 Java 程序必备

  • JRE = JVM + Java 核心类库(String、ArrayList 等)
  • 只负责运行,不能写代码

JDK(Java 开发工具包)

开发 Java 程序必备

  • JDK = JRE + 编译器 + 调试工具
  • 用来写代码、编译、调试

一句话总结:开发用 JDK,运行用 JRE,真正干活的是 JVM

1.3 开发环境搭建

1.3.1 下载 JDK

推荐长期支持版:Java 8、11、17

1.3.2 安装

双击安装包,一路“下一步”,记住安装路径。

1.3.3 配置环境变量

  1. JAVA_HOME:填写 JDK 安装目录
  2. Path:添加 %JAVA_HOME%\bin

1.3.4 验证

打开命令提示符(cmd)输入:

java -version
javac

输出版本号,说明配置成功。

1.4 第一个 Java 程序:HelloWorld

代码

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

简单解释

  • public class HelloWorld:定义公共类,文件名必须一致
  • main:程序入口,Java 必须有
  • System.out.println:控制台打印内容

编译运行

  1. 保存为 HelloWorld.java
  2. 编译:
javac HelloWorld.java
  1. 运行:
java HelloWorld

结果

Hello World!

1.5 Java 程序运行原理

完整流程:

  1. 编写 .java 源代码
  2. javac 编译 → 生成 .class 字节码
  3. JVM 加载 .class
  4. JVM 执行程序

一句话:人写 .java,编译器转 .class,虚拟机执行

1.6 IDEA 基本使用

1.6.1 新建项目

File → New Project → 选择 Java → 选已安装的 JDK

1.6.2 新建类

public Demo {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

二、Java 语法基础

2.1 标识符

标识符:给类、方法、变量、包、接口起名字。

命名规则

  • 只能由字母、数字、下划线_、美元符$组成
  • 不能以数字开头
  • 不能是关键字
  • 区分大小写

命名规范

  • 类:大驼峰 HelloWorld
  • 变量/方法:小驼峰 userName
  • 常量:全大写 MAX_SIZE

示例

int age;
String userName;
public class Student {}

2.2 关键字

关键字:Java内置、有特殊含义、不能当标识符。

常用关键字

  • 访问:public private protected
  • 类:class interface enum
  • 方法:static void return
  • 流程:if else for while switch break continue
  • 异常:try catch finally throw throws
  • 对象:new this super
  • 类型:int double boolean char

示例

// 关键字不能当变量名
// int class;  错误
int num;     // 正确

2.3 注释

单行注释

// 我是单行注释
int a = 10;

多行注释

/*
我是多行注释
可以写很多行
*/
int b = 20;

文档注释

/**
 * 文档注释:用于生成API文档
 */
public void test(){}

2.4 数据类型

2.4.1 基本数据类型(8种)

  • byte:-128~127
  • short:短整型
  • int:整型(最常用)
  • long:长整型
  • float:单精度小数
  • double:双精度小数(常用)
  • char:字符
  • boolean:true/false

示例

byte b = 10;
int i = 100;
long l = 1000L;
double d = 3.14;
char c = 'A';
boolean flag = true;

2.4.2 引用数据类型

  • 类、接口、数组、字符串
String str = "Java";
int[] arr = new int[5];

2.4.3 类型转换

自动转换(小→大)
int a = 10;
double b = a;
强制转换(大→小)
double d = 3.9;
int i = (int) d;

2.5 变量与常量

变量

值可改变

int age = 18;
age = 20;

常量

值不可变,用final

final int MAX = 100;

变量作用域

  • 局部:方法内
  • 成员:类内、方法外

2.6 运算符

算术

int a=10, b=3;
System.out.println(a+b);
System.out.println(a-b);
System.out.println(a*b);
System.out.println(a/b);
System.out.println(a%b);
a++; b--;

赋值

int a=10;
a += 5;
a -= 3;

比较

System.out.println(10 == 5);
System.out.println(10 != 5);
System.out.println(10 > 5);

逻辑

true && false;
true || false;
!true;

三元

int max = a > b ? a : b;

2.7 流程控制

if

if (age >= 18) {
    System.out.println("成年");
}

if-else

if (age >= 18) {
    System.out.println("成年");
} else {
    System.out.println("未成年");
}

switch

int num=2;
switch (num) {
    case 1: System.out.println("一"); break;
    case 2: System.out.println("二"); break;
    default: System.out.println("其他");
}

for

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

while

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

break / continue

for (int i=0; i<10; i++) {
    if (i==5) break;
    if (i==3) continue;
    System.out.println(i);
}

2.8 数组

一维数组

int[] arr = {1,2,3};
for (int num : arr) {
    System.out.println(num);
}

二维数组

int[][] arr = {{1,2},{3,4}};

Arrays工具类

import java.util.Arrays;
Arrays.sort(arr);

三、面向对象编程(OOP)

3.1 面向对象三大特性

封装

把**数据(成员变量)方法(行为)**打包到类里,对外只暴露必要的方法,隐藏内部细节。
好处:安全、可控、易维护

继承

子类继承父类,复用父类代码,扩展新功能
好处:代码复用、减少重复、易扩展

多态

同一行为,不同实现
好处:灵活、可扩展、解耦

3.2 类与对象

模板、蓝图,定义属性和行为。

public class Person {
    // 属性
    String name;
    int age;

    // 行为
    public void sayHello() {
        System.out.println("你好!");
    }
}

对象

类的实例、具体事物,new 出来。

public class Test {
    public static void main(String[] args) {
        // 创建对象
        Person p = new Person();
        // 赋值
        p.name = "张三";
        p.age = 20;
        // 调用方法
        p.sayHello();
    }
}

3.3 构造方法

创建对象时自动调用,用于初始化
特点:

  • 名字和类名完全一样
  • 没有返回值
  • 可重载
public class Person {
    String name;
    int age;

    // 无参构造
    public Person() {
        name = "未知";
        age = 0;
    }

    // 有参构造(重载)
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

3.4 this 关键字

代表当前对象
用途:

  • 区分成员变量和局部变量
  • 调用本类构造方法
public class Person {
    String name;

    public void setName(String name) {
        // this.name:成员变量
        // name:局部变量
        this.name = name;
    }
}

3.5 封装

隐藏数据,通过方法访问
private 修饰成员变量,提供 get/set 方法。

public class Person {
    // 私有成员,外部不能直接访问
    private String name;
    private int age;

    // 获取
    public String getName() {
        return name;
    }

    // 设置
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 0) { // 加校验
            this.age = age;
        }
    }
}

3.6 继承

子类继承父,复用代码
关键字:extends

// 父类
public class Person {
    String name;
    public void say() {
        System.out.println("人会说话");
    }
}

// 子类 Student 继承 Person
public class Student extends Person {
    // 扩展自己的属性和方法
    int score;
    public void study() {
        System.out.println("学生学习");
    }
}

3.7 方法重写

子类重写父类方法,改变实现
条件:方法名、参数、返回值必须一样,加 @Override 注解。

public class Student extends Person {
    @Override
    public void say() {
        System.out.println("学生说:好好学习");
    }
}

3.8 super 关键字

代表父类对象
用途:

  • 调用父类构造
  • 调用父类方法
public class Student extends Person {
    public Student() {
        super(); // 调用父类无参构造
    }

    @Override
    public void say() {
        super.say(); // 调用父类方法
        System.out.println("学生自己说");
    }
}

3.9 多态

方法重载

同一类中,方法名相同,参数不同

public class Demo {
    public void add(int a) {}
    public void add(int a, int b) {}
}

向上转型

父类引用指向子类对象

Person p = new Student();
p.say(); // 调用子类重写方法

向下转型

子类引用指向父类对象(强转)

Student s = (Student) p;

instanceof

判断对象类型

if (p instanceof Student) {
    Student s = (Student) p;
}

3.10 抽象类

不能实例化,有抽象方法
关键字:abstract

public abstract class Animal {
    // 抽象方法:无实现,子类必须重写
    public abstract void eat();
}

3.11 接口

规范、标准,全是抽象方法
关键字:interfaceimplements

public interface Run {
    void run();
}

public class Person implements Run {
    @Override
    public void run() {
        System.out.println("人跑步");
    }
}

3.12 static 关键字

属于类,不属于对象

public class Demo {
    // 静态变量
    public static int count;

    // 静态方法
    public static void test() {}

    // 静态代码块
    static {
        System.out.println("静态代码块");
    }
}

3.13 final 关键字

最终、不可变

  • 修饰类:不能被继承
  • 修饰方法:不能重写
  • 修饰变量:常量,不可改
final int MAX = 100;

3.14 内部类

成员内部

public class Outer {
    class Inner {}
}

匿名内部

new Runnable() {
    public void run() {}
};

3.15 包与导入

管理类,避免重名

package com.test;
import java.util.ArrayList;

3.16 代码块

构造代码块

{
    System.out.println("构造代码块");
}

静态代码块

static {
    System.out.println("静态代码块");
}

四、异常处理

4.1 异常体系

异常(Exception):程序运行时出现的不正常情况,导致代码中断。

异常的总父类:Throwable

  • Error(错误):严重、不可处理,如内存溢出、虚拟机崩溃。
  • Exception(异常):可处理,分为:
    • 编译时异常(受检异常):必须处理,如文件找不到、网络异常。
    • 运行时异常(非受检异常):运行才报错,可处理可不处理,如空指针、数组越界。

4.2 try-catch-finally

捕获并处理异常

格式

try {
    // 可能出错的代码
} catch (异常类型 e) {
    // 处理异常
} finally {
    // 无论是否出错,一定会执行
}

示例

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            int a = 10 / 0; // 除零异常
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        } finally {
            System.out.println("程序结束");
        }
    }
}

4.3 throws 关键字

声明方法可能抛出异常,交给调用者处理

示例

public void readFile() throws Exception {
    // 可能出错的代码
}

4.4 throw 关键字

手动抛出异常对象

示例

public void checkAge(int age) {
    if (age < 18) {
        throw new RuntimeException("未成年不能访问");
    }
}

4.5 自定义异常

自己定义异常类,用于业务错误

步骤

  1. 继承 Exception(编译时)或 RuntimeException(运行时)
  2. 提供构造方法

示例

// 自定义运行时异常
public class AgeException extends RuntimeException {
    public AgeException(String message) {
        super(message);
    }
}

// 使用
public void checkAge(int age) {
    if (age < 18) {
        throw new AgeException("年龄太小");
    }
}

五、常用 API

5.1 String(字符串)

字符串不可变,每次修改都会生成新对象。

常用方法

String str = "  JavaStudy  ";

// 1. 获取长度
int len = str.length();

// 2. 去除首尾空格
String trimStr = str.trim();

// 3. 比较内容(区分大小写)
boolean eq = "java".equals(str);

// 4. 比较内容(忽略大小写)
boolean eqIgnoreCase = "java".equalsIgnoreCase(str);

// 5. 截取子串
String sub = str.substring(2, 6);

// 6. 分割字符串
String[] arr = str.split(" ");

// 7. 替换
String rep = str.replace("a", "A");

// 8. 转大小写
String upper = str.toUpperCase();
String lower = str.toLowerCase();

// 9. 查找索引
int idx = str.indexOf("S");

5.2 StringBuilder / StringBuffer

可变字符串,适合频繁拼接。

  • StringBuilder:非线程安全、效率高(常用)
  • StringBuffer:线程安全、效率低

示例

StringBuilder sb = new StringBuilder();

// 拼接
sb.append("Hello");
sb.append(" ");
sb.append("Java");

// 反转
sb.reverse();

// 转为String
String str = sb.toString();

5.3 包装类

把基本类型变成对象,支持自动装箱/拆箱。

8 种对应关系

  • Integerint
  • Doubledouble
  • Booleanboolean
  • Characterchar
  • Byte/Short/Long/Float

自动装箱 / 拆箱

// 装箱:int → Integer
Integer a = 10;

// 拆箱:Integer → int
int b = a;

常用方法

// 字符串转int
int num = Integer.parseInt("123");

// int转字符串
String str = Integer.toString(456);

5.4 日期相关 API

5.4.1 传统日期(Date、SimpleDateFormat、Calendar)

import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;

// Date:当前时间
Date date = new Date();

// SimpleDateFormat:格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(date);

// Calendar:日期计算
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, 7); // 加7天

5.4.2 Java 8 新日期(推荐、线程安全)

import java.time.*;
import java.time.format.DateTimeFormatter;

// 本地日期
LocalDate localDate = LocalDate.now();

// 本地时间
LocalTime localTime = LocalTime.now();

// 日期+时间
LocalDateTime ldt = LocalDateTime.now();

// 格式化
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String str = ldt.format(dtf);

5.5 System、Math、Random

System

// 当前时间戳(毫秒)
long time = System.currentTimeMillis();

// 退出程序
// System.exit(0);

Math

// 绝对值
Math.abs(-5);

// 最大值
Math.max(3, 9);

// 随机数 [0,1)
double r = Math.random();

// 四舍五入
Math.round(3.6);

Random

import java.util.Random;

Random r = new Random();
int num = r.nextInt(10); // 0~9

5.6 Object 类

所有类的父类,默认继承。

常用方法

// 比较地址
obj.equals(o);

// 哈希值
obj.hashCode();

// 转字符串
obj.toString();

六、集合框架

6.1 集合体系结构

集合是用来存储多个数据的容器,比数组更灵活、功能更强。

  • Collection:单列集合,一次存一个元素
    • List:有序、可重复
    • Set:无序、不可重复
  • Map:双列集合,以**键值对(key-value)**形式存储

6.2 List 接口

特点:有序、可重复、有索引

6.2.1 ArrayList

  • 底层:数组
  • 优点:查询快
  • 缺点:增删慢
import java.util.ArrayList;
import java.util.List;

public class ListDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        
        // 添加
        list.add("Java");
        list.add("Python");
        list.add("C++");
        
        // 获取
        String s = list.get(0);
        
        // 遍历
        for (String str : list) {
            System.out.println(str);
        }
        
        // 删除
        list.remove(1);
        
        // 大小
        int size = list.size();
    }
}

6.2.2 LinkedList

  • 底层:双向链表
  • 优点:增删快
  • 缺点:查询慢
import java.util.LinkedList;

LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("A");
linkedList.addFirst("First");
linkedList.removeLast();

6.3 Set 接口

特点:无序、不可重复、无索引

6.3.1 HashSet

  • 底层:哈希表
  • 去重原理:hashCode() + equals()
import java.util.HashSet;
import java.util.Set;

Set<String> set = new HashSet<>();
set.add("张三");
set.add("李四");
set.add("张三"); // 重复,添加失败

// 遍历
for (String s : set) {
    System.out.println(s);
}

6.3.2 TreeSet

  • 底层:红黑树
  • 特点:自动排序
import java.util.TreeSet;

TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);
ts.add(1);
ts.add(2);
// 结果:[1,2,3]

6.4 Map 接口

特点:存储键值对,key 不可重复,value 可重复

6.4.1 HashMap

  • 底层:哈希表
  • 最常用
import java.util.HashMap;
import java.util.Map;

public class MapDemo {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        
        // 添加
        map.put("张三", 20);
        map.put("李四", 22);
        
        // 获取
        int age = map.get("张三");
        
        // 遍历(键值对)
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        
        // 判断key是否存在
        boolean exists = map.containsKey("张三");
    }
}

6.5 Collections 工具类

专门用来操作Collection 集合的工具类

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

List<Integer> list = new ArrayList<>();
list.add(3);
list.add(1);
list.add(2);

// 排序
Collections.sort(list);

// 反转
Collections.reverse(list);

// 最大值
int max = Collections.max(list);

6.6 Java 8 Stream 流

对集合进行高效、简洁的批量操作(过滤、统计、排序、收集)

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C");
list.add("JavaScript");

// 1. 过滤:长度大于3
List<String> result = list.stream()
                          .filter(s -> s.length() > 3)
                          .collect(Collectors.toList());

// 2. 转大写
List<String> upperList = list.stream()
                              .map(String::toUpperCase)
                              .collect(Collectors.toList());

// 3. 计数
long count = list.stream().count();

七、IO 与 NIO

7.1 IO 概述

IO(输入/输出):用于读写文件、网络传输、控制台交互

  • 字节流:处理一切文件(图片、视频、文本)
  • 字符流:只处理纯文本(.txt、.java)

7.2 字节流(InputStream / OutputStream)

文件字节流

import java.io.FileInputStream;
import java.io.FileOutputStream;

// 读文件
FileInputStream fis = new FileInputStream("test.txt");
int data = fis.read(); // 读一个字节
fis.close();

// 写文件
FileOutputStream fos = new FileOutputStream("test.txt");
fos.write(97); // 写一个字节(a)
fos.close();

7.3 字符流(Reader / Writer)

文件字符流

import java.io.FileReader;
import java.io.FileWriter;

// 读文本
FileReader fr = new FileReader("test.txt");
int ch = fr.read();
fr.close();

// 写文本
FileWriter fw = new FileWriter("test.txt");
fw.write("Hello IO");
fw.close();

7.4 缓冲流(高效读写)

包装普通流,带缓冲区,速度快

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;

// 缓冲字符流
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
String line = br.readLine(); // 读一行
br.close();

BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
bw.write("一行文字");
bw.newLine(); // 换行
bw.close();

7.5 File 类(文件/目录操作)

import java.io.File;

File file = new File("test.txt");

// 判断
file.exists();
file.isFile();
file.isDirectory();

// 创建/删除
file.createNewFile();
file.delete();

// 目录
File dir = new File("myFolder");
dir.mkdir();

7.6 NIO(Java 新IO,非阻塞)

Path、Files

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

Path path = Paths.get("test.txt");

// 读
String content = Files.readString(path);

// 写
Files.write(path, "NIO 写入".getBytes());

Channel、Buffer

NIO 核心:通道 + 缓冲区。


7.7 序列化

把对象 → 字节流,用于保存对象、网络传输

import java.io.Serializable;

// 实现Serializable接口
class User implements Serializable {
    String name;
    int age;
}

ObjectOutputStream / ObjectInputStream

// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.obj"));
oos.writeObject(new User("张三", 20));

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.obj"));
User u = (User) ois.readObject();

7.8 transient 关键字

序列化时忽略该字段

transient String password;

八、多线程

8.1 进程与线程

  • 进程:独立运行的程序,资源分配单位
  • 线程:进程内的执行单元,CPU调度单位
  • 一个进程可以包含多个线程,并发执行、提高效率

8.2 线程生命周期

新建 → 就绪 → 运行 → 阻塞 → 死亡

8.3 线程创建方式

方式一:继承 Thread 类

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行");
    }
}

// 启动
new MyThread().start();

方式二:实现 Runnable 接口(推荐)

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable线程");
    }
}

new Thread(new MyRunnable()).start();

方式三:Lambda(简化)

new Thread(() -> {
    System.out.println("Lambda线程");
}).start();

方式四:Callable(有返回值)

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "线程返回结果";
    }
}

FutureTask<String> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
String res = task.get();

8.4 线程常用方法

Thread t = new Thread();

t.start();     // 启动线程
t.sleep(1000); // 休眠1秒
t.join();      // 等待线程执行完毕
t.yield();     // 让出CPU
t.interrupt(); // 中断线程

8.5 线程安全问题

多个线程同时操作共享数据,会出现数据错乱。

解决:synchronized 同步

// 同步方法
public synchronized void add() {
    count++;
}

// 同步代码块
synchronized (对象) {
    count++;
}

Lock 锁(更灵活)

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

Lock lock = new ReentrantLock();
lock.lock();
try {
    count++;
} finally {
    lock.unlock();
}

8.6 线程通信

wait() / notify() / notifyAll()

synchronized (obj) {
    obj.wait();   // 等待,释放锁
    obj.notify(); // 唤醒一个线程
}

8.7 线程池

复用线程、避免频繁创建销毁

常用线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

// 固定线程池
ExecutorService pool = Executors.newFixedThreadPool(3);

pool.submit(() -> {
    System.out.println("线程池任务");
});

pool.shutdown();

8.8 并发工具

  • CountDownLatch:等待多线程完成
  • CyclicBarrier:线程屏障
  • Semaphore:控制并发数

8.9 并发集合

  • ConcurrentHashMap:线程安全Map
  • CopyOnWriteArrayList:线程安全List

九、反射与注解

9.1 反射(Reflection)

反射:程序运行时,动态获取/操作类、对象、方法、属性
一句话:运行时看透类的所有信息,甚至私有

9.1.1 获取 Class 对象(三种方式)

// 1. 类名.class
Class<?> clazz1 = Person.class;

// 2. 对象.getClass()
Person p = new Person();
Class<?> clazz2 = p.getClass();

// 3. Class.forName("全类名")(最常用)
Class<?> clazz3 = Class.forName("com.example.Person");

9.1.2 通过反射创建对象

Class<?> clazz = Person.class;
// 无参构造
Person p = (Person) clazz.newInstance();

// 有参构造
Constructor<?> con = clazz.getConstructor(String.class, int.class);
Person p2 = (Person) con.newInstance("张三", 20);

9.1.3 反射操作成员变量

Class<?> clazz = Person.class;
Person p = new Person();

// 获取私有字段
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 暴力破解,取消私有
field.set(p, "李四");      // 赋值
String name = (String) field.get(p); // 取值

9.1.4 反射调用方法

Class<?> clazz = Person.class;
Person p = new Person();

// 获取方法
Method method = clazz.getDeclaredMethod("sayHello");
method.invoke(p); // 调用方法

// 带参数方法
Method setAge = clazz.getDeclaredMethod("setAge", int.class);
setAge.invoke(p, 25);

9.2 注解(Annotation)

注解:给代码打标记,编译器/程序可以读取
分为:内置注解、元注解、自定义注解。

9.2.1 内置注解(常用)

@Override       // 重写
@Deprecated     // 过时
@SuppressWarnings // 抑制警告

9.2.2 元注解(修饰注解的注解)

@Target      // 注解作用位置:类、方法、字段
@Retention   // 生命周期:源码、class、运行时
@Documented  // 生成文档
@Inherited   // 可被继承

9.2.3 自定义注解

import java.lang.annotation.*;

// 自定义注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value();
    int age() default 18;
}

9.2.4 使用注解

@MyAnnotation(value = "测试", age = 20)
public class Demo {
    @MyAnnotation("方法注解")
    public void test(){}
}

9.2.5 反射读取注解

Class<?> clazz = Demo.class;
MyAnnotation anno = clazz.getAnnotation(MyAnnotation.class);
System.out.println(anno.value());

十、泛型

10.1 泛型概念

泛型可以在编译阶段约束数据类型,把类型校验提前,避免类型转换异常,同时复用代码。使用尖括号<>定义类型参数,统一规范容器存储的数据类型。

10.2 泛型类

定义类时指定未知类型,实例化时确定具体类型

// 定义泛型类
public class Box<T> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

// 使用泛型类
public class Test {
    public static void main(String[] args) {
        Box<String> strBox = new Box<>();
        strBox.setData("Java泛型");
        String res = strBox.getData();

        Box<Integer> intBox = new Box<>();
        intBox.setData(666);
    }
}

10.3 泛型方法

方法定义独立的泛型参数,适配不同类型参数

public class GenericMethod {
    // 泛型方法
    public <E> E getElement(E element){
        return element;
    }

    public static void main(String[] args) {
        GenericMethod gm = new GenericMethod();
        String s = gm.getElement("字符串");
        Integer num = gm.getElement(100);
    }
}

10.4 泛型接口

接口中声明泛型,实现类确定具体类型

// 泛型接口
public interface IGeneric<T> {
    void show(T t);
}

// 实现类指定具体类型
class StringImpl implements IGeneric<String>{
    @Override
    public void show(String s) {
        System.out.println(s);
    }
}

10.5 泛型通配符

无边界通配符 ?

代表任意未知类型,只能读取数据,不能写入

import java.util.ArrayList;
import java.util.List;

public class WildcardDemo {
    public static void printList(List<?> list){
        for (Object obj : list) {
            System.out.println(obj);
        }
    }

    public static void main(String[] args) {
        List<String> strList = new ArrayList<>();
        List<Integer> intList = new ArrayList<>();
        printList(strList);
        printList(intList);
    }
}

上限通配符 ? extends T

限定类型只能是T本身或者T的子类

// 只能接收Animal及子类集合
public void getAnimal(List<? extends Animal> list){}

下限通配符 ? super T

限定类型只能是T本身或者T的父类

// 只能接收Dog及父类集合
public void setDog(List<? super Dog> list){}

10.6 泛型擦除

编译阶段泛型生效,编译完成后会抹去泛型标识,统一转为Object类型,运行阶段不存在泛型类型

  • 基本数据类型不能作为泛型参数,只能使用包装类
  • 无法使用泛型直接创建数组实例
  • 不同泛型参数的同类对象,运行时视为同一个类型

补充第十一章 网络编程

十一、网络编程

11.1 网络编程基础

网络编程用于实现设备之间的数据交互,核心依托IP地址定位主机、端口号定位程序、协议规范传输规则。

  • IP地址:区分网络中不同计算机
  • 端口号:0-65535,标识设备上运行的应用程序
  • 常用协议:TCP可靠连接传输、UDP无连接快速传输

11.2 InetAddress 地址类

用于获取本机、远端主机IP与主机名

import java.net.InetAddress;

public class InetDemo {
    public static void main(String[] args) throws Exception {
        // 获取本机地址
        InetAddress local = InetAddress.getLocalHost();
        System.out.println(local.getHostAddress());
        // 根据域名获取地址
        InetAddress remote = InetAddress.getByName("www.baidu.com");
    }
}

11.3 TCP通信

面向连接、可靠稳定、三次握手建立通道,适用于文件传输、网页数据交互

客户端

import java.io.OutputStream;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) throws Exception {
        // 绑定服务端IP和端口
        Socket socket = new Socket("127.0.0.1", 8888);
        OutputStream os = socket.getOutputStream();
        os.write("TCP客户端消息".getBytes());
        socket.close();
    }
}

服务端

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws Exception {
        // 监听指定端口
        ServerSocket server = new ServerSocket(8888);
        Socket socket = server.accept();
        InputStream is = socket.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        System.out.println(new String(buf,0,len));
        server.close();
    }
}

11.4 UDP通信

无连接、数据以数据包形式发送,速度快但不可靠,适用于直播、语音通话

发送端

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpSend {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();
        byte[] data = "UDP数据报文".getBytes();
        InetAddress ip = InetAddress.getLocalHost();
        // 封装数据包
        DatagramPacket packet = new DatagramPacket(data,data.length,ip,9999);
        socket.send(packet);
        socket.close();
    }
}

接收端

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpReceive {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(9999);
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf,buf.length);
        socket.receive(packet);
        System.out.println(new String(buf,0,packet.getLength()));
        socket.close();
    }
}

11.5 URL网络访问

通过统一资源定位符,读取网络网页资源数据

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class UrlDemo {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://www.baidu.com");
        BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
        String line;
        while((line = br.readLine()) != null){
            System.out.println(line);
        }
        br.close();
    }
}

十二、JDBC数据库编程

12.1 JDBC概述

JDBC是Java操作数据库的标准接口,通过固定规范实现Java程序增删改查MySQL、Oracle等数据库,实现程序与数据持久化交互。

12.2 核心使用步骤

  1. 导入数据库驱动包
  2. 加载驱动类
  3. 获取数据库连接
  4. 创建执行SQL对象
  5. 执行语句,处理结果
  6. 关闭资源

12.3 基础连接与查询示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JdbcDemo {
    public static void main(String[] args) throws Exception {
        // 1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 2.数据库连接参数
        String url = "jdbc:mysql://localhost:3306/testdb?useSSL=false";
        String user = "root";
        String password = "123456";
        // 3.获取连接
        Connection conn = DriverManager.getConnection(url, user, password);
        // 4.创建执行对象
        Statement stmt = conn.createStatement();
        // 5.执行查询
        String sql = "select * from user";
        ResultSet rs = stmt.executeQuery(sql);
        // 遍历结果集
        while(rs.next()){
            System.out.println(rs.getInt("id")+" "+rs.getString("name"));
        }
        // 6.关闭资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

12.4 增删改操作

// 插入数据
String insertSql = "insert into user(name,age) values('小明',20)";
int rows = stmt.executeUpdate(insertSql);
System.out.println("影响行数:"+rows);

// 修改数据
String updateSql = "update user set age=21 where name='小明'";
stmt.executeUpdate(updateSql);

// 删除数据
String delSql = "delete from user where name='小明'";
stmt.executeUpdate(delSql);

12.5 PreparedStatement预编译对象

防止SQL注入,执行效率更高,推荐日常使用

import java.sql.PreparedStatement;

String sql = "select * from user where id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,1);
ResultSet rs = pstmt.executeQuery();

12.6 事务管理

多条SQL要么全部执行成功,要么全部回滚,保证数据一致性

try {
    conn.setAutoCommit(false); // 关闭自动提交
    // 执行多条数据库操作
    conn.commit(); // 提交事务
} catch (Exception e) {
    conn.rollback(); // 异常回滚
}

更多推荐