นากต้นฉบับใช้ไม้ฉากสีอำพันวัดขอบซ้ายและขอบขวาของก้อนข้อมูลก่อนตัดช่วง

Java Objects.checkFromToIndex: ตรวจช่วงครึ่งเปิดก่อนแตะ Array

พี่โชว์Engineering

โค้ด slice แบบ from <= to && to <= length ดูง่าย แต่พอมีค่าติดลบ ช่วงว่าง หรือ convention ว่าขอบขวารวมไหม ความผิดพลาดแบบ off-by-one ก็โผล่ Objects.checkFromToIndex รวมกฎช่วงครึ่งเปิด [from, to) ไว้ใน standard library และคืน from เมื่อผ่าน จึงใช้ใน expression ได้ครับ

import java.util.Arrays;
import java.util.Objects;

public class Main {
    static byte[] slice(byte[] source, int from, int to) {
        Objects.checkFromToIndex(from, to, source.length);
        return Arrays.copyOfRange(source, from, to);
    }

    public static void main(String[] args) {
        byte[] data = {10, 20, 30, 40};
        assert Arrays.equals(slice(data, 1, 3), new byte[] {20, 30});
        assert slice(data, 2, 2).length == 0 : "empty range is valid";

        boolean rejected = false;
        try {
            slice(data, 3, 5);
        } catch (IndexOutOfBoundsException expected) {
            rejected = true;
        }
        assert rejected : "range beyond length must fail";
        System.out.println("range validation verified");
    }
}

เลือกฟังก์ชันให้ตรงสัญญา

checkIndex(index, length) ตรวจตำแหน่งเดียวในช่วง [0, length) ส่วน checkFromToIndex(from, to, length) ตรวจช่วงครึ่งเปิด และ checkFromIndexSize(from, size, length) เหมาะเมื่อ protocol ส่ง offset กับจำนวน byte มาโดยตรง เลือกแบบที่ตรง input เพื่อลด arithmetic ที่เราเขียนเอง

ช่วงว่าง from == to ถูกต้องและมีประโยชน์กับ parser ส่วน from > to, ค่าติดลบ หรือ to > length จะโยน IndexOutOfBoundsException ก่อนแตะ array สิ่งนี้ช่วยให้ boundary เดียวกันใช้กับ array, buffer และ list adapter ได้สม่ำเสมอ

ถ้า input มาจาก network อย่าส่งข้อความ exception ภายในกลับผู้ใช้โดยตรง แปลงเป็น validation error ที่ปลอดภัยและบันทึกค่าที่จำเป็นแบบไม่รั่ว payload นอกจากนี้ check กับ use ต้องอ้าง length เดียวกัน หาก collection เปลี่ยนพร้อมกันระหว่างสองขั้น การตรวจผ่านไม่ได้รับประกันการเข้าถึงภายหลัง

Recap

  • ใช้ convention [from, to) ให้ตรงกับ Java APIs
  • ช่วงว่างถูกต้อง แต่ลำดับกลับและเกิน length ต้อง fail
  • ใช้ checkFromIndexSize เมื่อ input เป็น offset + size
  • แปลง exception ที่ boundary และระวังข้อมูลเปลี่ยนระหว่าง check/use ครับ