A private final array field is still an array that someone can mutate. Final prevents assignment of a different reference; it doesn't freeze the referenced object. If a constructor stores an outside array directly, the caller can change your object's state after construction. Copy at the boundary when the object needs an independent snapshot.
The output boundary matters too. A getter that returns an internal array gives the caller a writable path back into the object. Return a copy when callers should own their results. Collections.unmodifiableList blocks writes through that view but still reflects changes to its backing list, so copy first when the requirement is a snapshot. Validation belongs at construction as well: a Window with private final endpoints can establish a range invariant once and rely on it for later calculations.