Ⅰ. 基础篇——语言本身与核心 API

一、导语

JAVA体系专栏,帮您从头开始梳理知识点,方便新手串联有价值的学习,老手按需复习。让我们体验一下打怪升级般的学习吧。好了,废话不多说。做好了开始发车喽!


1、IO 与 NIO

java.io

字节流:
InputStream
/
OutputStream
。字符流:
Reader
/
Writer
。序列化:
Serializable
 接口。
java.nio

Buffer
:数据容器。
Channel
:双向数据传输。
Selector
:多路复用 I/O。
NIO.2(Java 7+):
Path

Files

AsynchronousFileChannel

练习

使用 
FileInputStream
/
FileOutputStream
 复制大文件。基于 
Selector
 和 
SocketChannel
 实现简单聊天室。



import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
 
public class FileCopy {
    public static void main(String[] args) {
        String sourcePath = "source.txt";
        String targetPath = "target.txt";
        
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourcePath));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetPath))) {
            
            byte[] buffer = new byte[1024];
            int bytesRead;
            
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            
            System.out.println("文件复制完成。");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
 
public class ChatServer {
    private Selector selector;
    private ServerSocketChannel serverChannel;
    private static final int PORT = 8080;
 
    public ChatServer() throws IOException {
        selector = Selector.open();
        serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress(PORT));
        serverChannel.configureBlocking(false);
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器已启动,监听端口:" + PORT);
    }
 
    public void run() throws IOException {
        while (true) {
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
 
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    accept(key);
                } else if (key.isReadable()) {
                    read(key);
                }
                keyIterator.remove();
            }
        }
    }
 
    private void accept(SelectionKey key) throws IOException {
        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
        SocketChannel sc = ssc.accept();
        sc.configureBlocking(false);
        sc.register(selector, SelectionKey.OP_READ);
        System.out.println("新客户端连接:" + sc.getRemoteAddress());
    }
 
    private void read(SelectionKey key) throws IOException {
        SocketChannel sc = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = sc.read(buffer);
        if (bytesRead == -1) {
            sc.close();
            System.out.println("客户端断开连接:" + sc.getRemoteAddress());
            return;
        }
        buffer.flip();
        byte[] data = new byte[bytesRead];
        buffer.get(data);
        String message = new String(data);
        System.out.println("收到消息:" + message);
        broadcast(message, sc);
    }
 
    private void broadcast(String message, SocketChannel sender) throws IOException {
        for (SelectionKey key : selector.keys()) {
            if (key.channel() instanceof SocketChannel && key.channel() != sender) {
                SocketChannel receiver = (SocketChannel) key.channel();
                receiver.write(ByteBuffer.wrap(message.getBytes()));
            }
        }
    }
 
    public static void main(String[] args) throws IOException {
        ChatServer server = new ChatServer();
        server.run();
    }
}


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
 
public class ChatClient {
    private SocketChannel socketChannel;
    private static final String SERVER_ADDRESS = "localhost";
    private static final int PORT = 8080;
 
    public ChatClient() throws IOException {
        socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress(SERVER_ADDRESS, PORT));
        System.out.println("已连接到服务器:" + SERVER_ADDRESS + ":" + PORT);
    }
 
    public void start() throws IOException {
        Thread receiveThread = new Thread(() -> {
            try {
                while (true) {
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = socketChannel.read(buffer);
                    if (bytesRead == -1) {
                        break;
                    }
                    buffer.flip();
                    byte[] data = new byte[bytesRead];
                    buffer.get(data);
                    String message = new String(data);
                    System.out.println("收到消息:" + message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        receiveThread.start();
 
        Scanner scanner = new Scanner(System.in);
        while (true) {
            String message = scanner.nextLine();
            if (message.equalsIgnoreCase("exit")) {
                break;
            }
            socketChannel.write(ByteBuffer.wrap(message.getBytes()));
        }
        socketChannel.close();
    }
 
    public static void main(String[] args) throws IOException {
        ChatClient client = new ChatClient();
        client.start();
    }
}

2、 多线程 & 并发

线程创建:继承 
Thread
 或实现 
Runnable
/
Callable
线程池
ExecutorService
(如 
ThreadPoolExecutor
)管理线程生命周期。同步机制

synchronized
 关键字(方法、代码块)。
Lock
 接口(
ReentrantLock

ReadWriteLock
)。
线程安全

volatile
 保证可见性。
AtomicInteger
 等原子类。
ThreadLocal
 线程局部变量。
并发工具

CountDownLatch
:等待多个任务完成。
CyclicBarrier
:多个线程相互等待。
Semaphore
:控制并发访问数。

练习:使用 
ExecutorService
 实现并行网页爬虫,统计各页面关键词频率。



import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
 
public class WebCrawler {
    private static final String[] URLs = {
        "https://example.com",
        "https://test.com",
        "https://demo.com"
    };
    private static final String[] KEYWORDS = {"Java", "Python", "C++"};
    private static final int TIMEOUT = 5; // 秒
 
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        try {
            CompletableFuture<?>[] futures = new CompletableFuture[URLS.length];
            for (int i = 0; i < URLs.length; i++) {
                final int index = i;
                futures[index] = CompletableFuture.supplyAsync(() -> {
                    try {
                        String content = fetchContent(URLS[index]);
                        return countKeywords(content);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                }, executor);
            }
 
            CompletableFuture.allOf(futures).join();
            System.out.println("所有任务完成。");
            printResults(futures);
 
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
            try {
                if (!executor.awaitTermination(TIMEOUT, TimeUnit.SECONDS)) {
                    System.out.println("线程池未在指定时间内关闭。");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
    private static String fetchContent(String url) throws IOException, InterruptedException, TimeoutException {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(TIMEOUT))
                .build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }
 
    private static String countKeywords(String content) {
        return String.join("
", 
            java.util.Arrays.stream(KEYWORDS)
                .map(keyword -> keyword + ": " + 
                    content.split(keyword, -1).length - 1)
                .collect(Collectors.toList()));
    }
 
    private static void printResults(CompletableFuture<?>[] futures) {
        for (CompletableFuture<?> future : futures) {
            try {
                Object result = future.get();
                if (result != null) {
                    System.out.println(result);
                }
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

3、 JVM 基础

内存结构

堆:对象实例。栈:局部变量、方法调用。方法区:类信息、常量池。直接内存:NIO 使用的堆外内存。
垃圾回收
算法:标记‑清除、复制、标记‑整理。收集器:Serial、Parallel、CMS、G1、ZGC。
类加载:加载 → 验证 → 准备 → 解析 → 初始化。诊断工具
jstack
(线程栈)、
jmap
(内存快照)、
jstat
(GC 统计)、VisualVM。

练习:设置 
-Xmx256m -Xms128m
 启动程序,通过 
jstat -gc <pid>
 观察 GC 活动。


4、 注解 & 反射

注解

元注解:
@Target

@Retention

@Documented

@Inherited
。自定义注解:定义并编写处理器(编译时或运行时)。
反射

Class

Method

Field

Constructor
 等反射 API。动态代理:
Proxy.newProxyInstance
 创建接口代理。

练习:定义 
@LogExecutionTime
 注解,通过反射在方法执行前后输出耗时。



import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
    String value() default "";
}


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
 
import java.util.Date;
 
@Aspect
@Component
public class LogExecutionTimeAspect {
    @Around("@annotation(LogExecutionTime)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String annotationValue = getAnnotationValue(joinPoint);
        
        System.out.println(String.format(
            "方法 %s.%s 执行时间: %d ms%s",
            className,
            methodName,
            duration,
            annotationValue.isEmpty() ? "" : " (" + annotationValue + ")"
        ));
        return result;
    }
 
    private String getAnnotationValue(ProceedingJoinPoint joinPoint) {
        LogExecutionTime annotation = joinPoint.getTarget().getClass()
            .getMethod(joinPoint.getSignature().getName(), joinPoint.getArgumentTypes())
            .getAnnotation(LogExecutionTime.class);
        return annotation != null ? annotation.value() : "";
    }
}


import org.springframework.stereotype.Service;
 
@Service
public class ExampleService {
    @LogExecutionTime("示例方法")
    public void exampleMethod() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5、 模块化(Java 9+)

模块描述
module-info.java
 中声明 
requires
(依赖)、
exports
(导出包)。服务加载
provides ... with
 和 
uses
 声明服务。迁移:将传统 JAR 转为模块,解决依赖冲突。

练习:创建 
core

service

web
 三个模块,
web
 依赖 
service

service
 依赖 
core


二、结语

这是一个JAVA体系的系列专栏,下期继续更新Ⅱ. 进阶篇——企业级开发基础,有需要的可以关注一下。前期的体系只是大框架,后续会慢慢补充详细的!

© 版权声明

相关文章

暂无评论

none
暂无评论...