JAVA编程学习记录

记录我的Java学习之路 - 从入门到精通

内部类和匿名内部类

内部类 匿名内部类 面向对象

内部类概念

在A类的内部中若存在一个B类,则B类为内部类,A类是B类的外部类。

public class A { class B { // 内部类 } }

内部类可以调用外部类的方法和属性,外部类需通过创建内部类对象来调用内部类的方法和属性。

外部类.内部类 对象 = new 外部类().new 内部类();

匿名内部类

匿名内部类就是没有名字的内部类,可以简化实现接口的步骤。

实现条件:

必须实现一个父接口或者继承父类。

new 父类或接口 { @Override public void 方法名() { 代码块; } }

使用示例:

// 定义接口 public interface People { void eat(); } // 匿名内部类实现 People xiaoming = new People() { @Override public void eat() { System.out.println("小明需要吃饭。"); } }; xiaoming.eat(); // 通过命名调用

双大括号初始化:

addOption(new HashMap<Integer,String>(){{ put(1, "test"); put(2, "work"); }}, quesId);

第一层括号表示定义了一个匿名内部类,第二层括号表示构造方法。

学习心得:匿名内部类可以快速创建接口实现类,在回调函数和事件处理中非常有用。

Stream流式编程

Stream 函数式编程 集合操作

Stream流的特点

  • 即时计算:流是按需提供,要什么生产什么
  • 一次性使用:流只能遍历一次,遍历完就被消费了
  • 内部迭代:类似直接下命令:全部进行XXX操作

Stream操作分类

中间操作:

  • filter() - 筛选
  • map() - 映射、获取值
  • limit() - 取前几项
  • sorted() - 排序
  • distinct() - 去除重复元素

终端操作:

  • collect() - 收集结果
  • reduce() - 归约操作
  • count() - 统计元素个数

代码示例:

// 归约操作示例 list.stream() .reduce(1, (a, b) -> a * b); // 所有元素相乘 list.stream() .reduce(0, (a, b) -> a + b); // 所有元素相加 // 收集器示例 menu.stream() .collect(summingInt(Dish::getCalories)); // 汇总 menu.stream() .map(Dish::getName) .collect(joining(", ")); // 连接字符串

自定义收集器

public interface Collector<T, A, R>{ Supplier<A> supplier(); BiConsumer<A, T> accumulator(); Function<A, R> finisher(); BinaryOperator<A> combiner(); Set<Characteristics> characteristics(); }

学习心得:Stream API让集合操作更加简洁和高效,函数式编程思想值得深入学习。

并发基础原理

并发编程 CPU缓存 性能优化

并发中缓存的基础原理

CPU缓存结构:

  • 一、二级缓存:在一个核内
  • 三级缓存:整个CPU共享
  • 缓存行大小:CPU缓存每次到内存获取的数据大小为64字节

并发性能问题:

如果不同核缓存了相近数据,核1每次修改其中数据,需要给其他核同步,导致时间开销。

在并发的时候,不同线程操作的变量,如果操作数据在内存中相近,则效率降低;如果操作数据远则效率提高。

缓存行填充优化:

某些MQ的设计中,使用了环形队列,指针变量前后各放了7个Long数据,用于填充56字节数据,加上指针变量就是64字节,使得指针数据在缓存中不可能与其他有效数据处于同一行,提高效率。

// 缓存行填充示例 public class CacheLinePadding { private long p1, p2, p3, p4, p5, p6, p7; // 前填充 private volatile long value; // 实际数据 private long p8, p9, p10, p11, p12, p13, p14; // 后填充 }

并发编程难度层次:

可见性 < 有序性 < 原子性

学习心得:理解CPU缓存机制对于编写高性能并发程序至关重要,合理的内存布局可以显著提升性能。

端口号被占用的解决方案

故障排除 端口管理 系统命令

问题描述

在开发过程中经常遇到端口被占用的情况,导致应用无法启动。

解决步骤

1. 查看占用端口的进程

使用以下命令查看占用8080端口的进程:

netstat -ano|findstr "8080"

这个命令会显示占用端口的进程的PID值。

2. 关闭进程

假设查到的PID是5100,使用以下命令关闭进程:

taskkill -PID 5100 -F

3. 通过PID查看进程详情

如果需要确认进程信息,可以使用:

tasklist|findstr "PID"

常用端口检查命令

# 查看所有端口占用情况 netstat -ano # 查看特定端口 netstat -ano|findstr "端口号" # 查看进程列表 tasklist

学习心得:掌握这些基本的系统命令对于日常开发调试非常有用,能快速解决端口冲突问题。

CTF解题记录

CTF 逆向工程 密码学

解题经验总结

图像处理类题目:

  • 斑马题:扫条形码获取信息
  • 桌面题:改变图形通道获得二维码
  • PNG题:遇到png图片尝试改变通道获得信息

加密解密类:

  • catcatcat:用strings获得密钥、用rabbit解密、用base91解码
  • 凯撒加密:每一位字母根据设置的长度前移K位(26个字母中)
  • Base64隐写:菜狗题中的base64隐写技术

数据分析类:

// 日历题解题思路 01081522291516170310172431-050607132027262728-... // 通过分隔符隔开行,每两个数字按十进制取日期,连接得到图案flag

文件分析类:

  • Webshell题:直接丢到kali用strings,搜fl4g获得
  • PDF题:将pdf转化为word后将图片移开
  • GIF题:先考虑逐帧分析
  • 伪加密:修改压缩包头部信息

编程解题:

// 十六进制处理示例 // 两两分组转十进制,观察出为ascii+128 // 减去128然后十进制转char输出 int value = Integer.parseInt(hex, 16); char result = (char)(value - 128);

学习心得:CTF题目涵盖面很广,需要掌握多种工具和技术,培养敏锐的观察力和逻辑思维能力。