Java.util.UUID.fromString не проверяет длину

Когда я посмотрел на реализацию java.util.UUID.fromString, я обнаружил, что он не проверяет длину UUID. Есть ли какая-то особая причина для этого? Он проверяет только компоненты, разделенные символом "-".

String[] components = name.split("-");
        if (components.length != 5)
            throw new IllegalArgumentException("Invalid UUID string: "+name);

Должен ли он также вызывать исключение IllegalArgumentException, если длина не равна 36?

В настоящее время без проверки длины числа автоматически добавляются с 0, если меньше, чем длина компонента или сдвинуты, если больше. Недостатком является то, что если вы ввели строку UUID с отсутствующей цифрой, она принимается как действительная и добавляется с 0. Это трудно отлаживать.

Например, этот "12345678-1234-1234-1234-123456789ab" становится "12345678-1234-1234-1234-0123456789ab". Обратите внимание, что добавлено '0'? И этот "12345678-1234-1234-1234-123456789abcd" становится "12345678-1234-1234-1234-23456789abcd" с удаленным "1".

Чтобы сделать это еще дальше, строка "1-2-3-4-5" также будет считаться действительной и станет "00000001-0002-0003-0004-000000000005".

Изменить: Чтобы уточнить мой вопрос, является ли это ошибкой или сделано для того, чтобы следовать стандарту или принципу?

Ответы

Ответ 1

Только оригинальные авторы UUID-класса могут рассказать вам, почему они решили не проверять длины компонентов в методе fromString, но я подозреваю, что они пытались прислушаться Закон о Postel:

Будьте либеральны в том, что вы принимаете, и консервативны в том, что вы отправляете.

Вы всегда можете проверить ввод на регулярное выражение, подобное этому:

[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}

Ответ 2

Поведение UUID.fromString странно, я не уверен, что это ошибка или нет, но вот что я делаю, чтобы поймать эти ошибки.

public class UUIDUtils {
    public static boolean isValid(String uuid){
        if( uuid == null) return false;
        try {
            // we have to convert to object and back to string because the built in fromString does not have 
            // good validation logic.
            UUID fromStringUUID = UUID.fromString(uuid);
            String toStringUUID = fromStringUUID.toString();
            return toStringUUID.equals(uuid);
        } catch(IllegalArgumentException e) {
            return false;
        }
    }
}

Ответ 3

Здесь решение:

import java.util.UUID
import scala.util.control.Exception._

val uuId: Option[UUID] = allCatch opt UUID.fromString(uuidToTest)
require(uuId.isDefined, "invalid UUID")

Ответ 4

Обязательно проверьте id.equalsIgnoreCase(parsed.toString()), потому что UUID.fromString(id) возвращает строчный регистр, даже если вы передаете id в качестве верхнего регистра.

@Component
public class UuidDtoValidator {

    public boolean isValidUuid(String id) {
        if (isBlank(id)) {
            return false;
        }

        try {
            UUID parsed = UUID.fromString(id);
            if (parsed.equals(new UUID(0, 0))) {
                return false;
            }
            return id.equalsIgnoreCase(parsed.toString());
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}

Ответ 5

Копия ответа ams, но для scala xD

def isValidUuid(uuid: String): Boolean =
    try uuid != null && UUID.fromString(uuid).toString.equals(uuid)
    catch {
      case e: IllegalArgumentException => false
    }