Поле, содержащее числа и буквы [дубликат]

Подтипирование является инвариантом для параметризованных типов. Даже жесткий класс Dog является подтипом Animal, параметризованный тип List не является подтипом List. Напротив, подтипирование covariant используется массивами, поэтому тип массива Dog[] является подтипом Animal[].

Инвариантный подтипирование гарантирует, что ограничения типа, принудительно выполняемые Java, не нарушены. Рассмотрим следующий код, приведенный @Jon Skeet:

List dogs = new ArrayList(1);
List animals = dogs;
animals.add(new Cat()); // compile-time error
Dog dog = dogs.get(0);

Как указано в @Jon Skeet, этот код является незаконным, поскольку в противном случае он будет нарушать ограничения типа, возвращая кошку, когда ожидается собака.

Поучительно сравнить приведенное выше с аналогичным кодом для массивов.

Dog[] dogs = new Dog[1];
Object[] animals = dogs;
animals[0] = new Cat(); // run-time error
Dog dog = dogs[0];

Код является законным. Тем не менее, выбрасывает исключение хранилища . Массив носит свой тип во время выполнения таким образом, JVM может обеспечить безопасность типов ковариантного подтипирования.

Чтобы понять это далее, давайте посмотрим на байт-код, сгенерированный javap класса ниже:

import java.util.ArrayList;
import java.util.List;

public class Demonstration {
    public void normal() {
        List normal = new ArrayList(1);
        normal.add("lorem ipsum");
    }

    public void parameterized() {
        List parameterized = new ArrayList<>(1);
        parameterized.add("lorem ipsum");
    }
}

Используя команду javap -c Demonstration, это показывает следующий байт-код Java:

Compiled from "Demonstration.java"
public class Demonstration {
  public Demonstration();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return

  public void normal();
    Code:
       0: new           #2                  // class java/util/ArrayList
       3: dup
       4: iconst_1
       5: invokespecial #3                  // Method java/util/ArrayList."":(I)V
       8: astore_1
       9: aload_1
      10: ldc           #4                  // String lorem ipsum
      12: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      17: pop
      18: return

  public void parameterized();
    Code:
       0: new           #2                  // class java/util/ArrayList
       3: dup
       4: iconst_1
       5: invokespecial #3                  // Method java/util/ArrayList."":(I)V
       8: astore_1
       9: aload_1
      10: ldc           #4                  // String lorem ipsum
      12: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      17: pop
      18: return
}

Обратите внимание, что переведенный код тел метода идентичен. Компилятор заменил каждый параметризованный тип на erasure . Это свойство имеет решающее значение, поскольку оно не нарушает совместимость в обратном направлении.

В заключение, безопасность во время выполнения невозможна для параметризованных типов, поскольку компилятор заменяет каждый параметризованный тип его стиранием. Это делает параметризованные типы не более чем синтаксическим сахаром.

7
задан nad2000 18 April 2013 в 03:04
поделиться

1 ответ

Да, вы можете. MySQL поддерживает regex ( http://dev.mysql.com/doc/refman/5.6/en/regexp.html ), и для проверки данных вы должны использовать триггер, поскольку MySQL не поддерживает ограничение CHECK (вы всегда можете перейти на PostgreSQL в качестве альтернативы :). NB! Имейте в виду, что хотя MySQL имеет конструкцию ограничения CHECK, к сожалению, MySQL (до сих пор 5.6) не проверяет данные на контрольные ограничения. Согласно http://dev.mysql.com/doc/refman/5.6/en/create-table.html : «Предложение CHECK анализируется, но игнорируется всеми механизмами хранения».

Вы можете добавить контрольное ограничение для телефона столбца:

CREATE TABLE data (
  phone varchar(100)
);

DELIMITER $$
CREATE TRIGGER trig_phone_check BEFORE INSERT ON data
FOR EACH ROW 
BEGIN 
IF (NEW.phone REGEXP '^(\\+?[0-9]{1,4}-)?[0-9]{3,10}$' ) = 0 THEN 
  SIGNAL SQLSTATE '12345'
     SET MESSAGE_TEXT = 'Wroooong!!!';
END IF; 
END$$
DELIMITER ;


INSERT INTO data VALUES ('+64-221221442'); -- should be OK
INSERT INTO data VALUES ('+64-22122 WRONG 1442'); -- will fail with the error: #1644 - Wroooong!!! 

Однако вы не должны полагаться только на MySQL (уровень данных в вашем случае) для проверки данных. Данные должны быть проверены на всех уровнях вашего приложения.

15
ответ дан nad2000 25 August 2018 в 14:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: