Какие типы данных могут хранить только положительные значения?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие типы данных могут хранить только положительные значения?
Введение
В Java и SQL существуют специальные типы данных, которые по определению могут хранить только неотрицательные (положительные и ноль) значения. Это полезно для поля, которые логически не могут быть отрицательными (возраст, цена, количество и т.д.).
В Java
1. Беззнаковые целочисленные типы
byte (unsigned)
- Размер: 8 бит
- Диапазон: 0 до 255
- Альтернатива:
short(с учётом отрицательных: -128 до 127)
// Java не имеет встроенного unsigned byte
// Но можно использовать:
short age = 25; // может быть отрицательным
byte unsignedAge = 25; // -128 до 127 — НЕ полностью unsigned
// Правильное решение: использовать Integer.toUnsignedInt()
int unsignedValue = Byte.toUnsignedInt((byte) 255); // 255 (не -1)
char
- Размер: 16 бит
- Диапазон: 0 до 65535 (0 до 2^16 - 1)
- Используется для символов Unicode
- Всегда положительный (или ноль)
char age = 25; // хранит число 25
char maxAge = 65535; // максимальное значение
char character = 'A'; // хранит код символа (65)
// Нельзя хранить отрицательные значения
char negativeValue = -1; // ОШИБКА компиляции!
2. Целочисленные типы сограничениями
int и long (с логическим ограничением)
- В Java это подписанные типы
- Но можно использовать методы для работы с unsigned
// java.lang.Integer
int unsignedValue = Integer.toUnsignedString(42); // преобразование
// java.lang.Long
long unsignedLong = Long.parseUnsignedLong("18446744073709551615");
// Java 8+: Integer и Long имеют методы для unsigned
int result = Integer.compareUnsigned(5, 3); // сравнение как unsigned
3. BigInteger (для больших чисел)
// Для очень больших положительных чисел
BigInteger positiveNumber = new BigInteger("999999999999999999999");
// Можно проверить, положительное ли число
if (positiveNumber.signum() > 0) {
System.out.println("Положительное число");
}
// Может быть и отрицательным
BigInteger negativeNumber = new BigInteger("-999999999999999999999");
4. Типы с плавающей точкой (Float, Double)
- Могут быть как положительными, так и отрицательными
- Специальное значение: 0.0 и -0.0 (оба валидны!)
- Могут быть NaN и Infinity
float positive = 3.14f; // положительное
float negative = -3.14f; // отрицательное
float zero = 0.0f; // ноль
float negZero = -0.0f; // отрицательный ноль (редко)
5. Использование аннотаций для ограничений
// Jakarta Validation (раньше javax.validation)
@Positive // строго > 0
@PositiveOrZero // >= 0
@Negative // < 0
@Min(value = 0) // >= значение
@Max(value = 100)
public class User {
@Positive
private Integer age; // не может быть 0 или отрицательным
@PositiveOrZero
private Integer score; // может быть 0 или положительным
@Min(0)
@Max(100)
private Integer percentage; // от 0 до 100
}
В SQL (PostgreSQL, MySQL, SQL Server)
1. PostgreSQL
smallint
- Размер: 2 байта
- Диапазон: -32768 до 32767
- Unsigned: 0 до 65535
CREATE TABLE products (
id SERIAL, -- 4 байта, auto-increment
age SMALLINT, -- -32768 до 32767
quantity SMALLINT, -- логически только положительное
price NUMERIC(10, 2) -- может быть отрицательным
);
int / integer
- Размер: 4 байта
- Диапазон: -2147483648 до 2147483647
- Unsigned: 0 до 4294967295
CREATE TABLE inventory (
product_id INT, -- может быть любым
stock_quantity INT CHECK (stock_quantity >= 0), -- только положительное
price DECIMAL(10, 2) -- может быть отрицательным
);
bigint
- Размер: 8 байт
- Диапазон: -2^63 до 2^63 - 1
- Unsigned: 0 до 2^64 - 1
CREATE TABLE audit_logs (
id BIGSERIAL, -- auto-increment, только положительное
event_count BIGINT CHECK (event_count >= 0)
);
2. MySQL
Истинно unsigned типы
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- 0 до 4294967295
age TINYINT UNSIGNED, -- 0 до 255
score SMALLINT UNSIGNED, -- 0 до 65535
views BIGINT UNSIGNED, -- 0 до 2^64-1
price DECIMAL(10, 2) -- может быть отрицательным
);
-- Попытка вставить отрицательное значение
INSERT INTO users (age) VALUES (-5); -- ERROR 1264!
Сравнение типов в MySQL
-- SIGNED vs UNSIGNED
TINYINT SIGNED: -128 до 127
TINYINT UNSIGNED: 0 до 255
SMALLINT SIGNED: -32768 до 32767
SMALLINT UNSIGNED: 0 до 65535
INT SIGNED: -2147483648 до 2147483647
INT UNSIGNED: 0 до 4294967295
BIGINT SIGNED: -2^63 до 2^63 - 1
BIGINT UNSIGNED: 0 до 2^64 - 1
3. SQL Server
Типы данных
CREATE TABLE products (
product_id INT PRIMARY KEY, -- -2^31 до 2^31-1
quantity INT CHECK (quantity >= 0), -- только положительное
price DECIMAL(10, 2), -- может быть отрицательным
views BIGINT -- большие числа
);
-- SQL Server НЕ имеет встроенного unsigned типа!
-- Нужно использовать CHECK constraint
ALTER TABLE products
ADD CHECK (quantity >= 0 AND quantity <= 2147483647);
Рекомендации
Для Java приложений
// ❌ Плохо: использовать int для всего
public class Product {
private int age; // может быть -5?
private int quantity; // может быть -100?
private int price; // может быть -1000?
}
// ✅ Хорошо: использовать аннотации и правильные типы
public class Product {
@Positive
private Integer age; // не может быть отрицательным
@PositiveOrZero
private Integer quantity; // >= 0
@Positive
private BigDecimal price; // > 0
}
Для БД
-- ❌ Плохо: нет ограничений
CREATE TABLE orders (
id INT PRIMARY KEY,
quantity INT,
price DECIMAL(10, 2)
);
-- ✅ Хорошо: используем типы и ограничения
CREATE TABLE orders (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
quantity INT UNSIGNED NOT NULL, -- только положительное
price DECIMAL(10, 2) NOT NULL
CHECK (price > 0), -- только положительное
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Когда использовать unsigned
✅ ID (автоинкрементные первичные ключи)
✅ Количество товара (inventory)
✅ Возраст (age)
✅ Цена (price)
✅ Просмотры (views)
✅ Лайки (likes)
✅ Рейтинг (rating 0-5)
✅ Процент (0-100)
❌ Температура (может быть отрицательной)
❌ Баланс счёта (может быть отрицательным)
❌ Высота (может быть ниже уровня моря)
❌ Координаты (может быть отрицательной)
Практический пример: Entity с ограничениями
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // можно использовать Long (всегда >= 0 в контексте ID)
@NotBlank
private String name;
@Positive(message = "Age must be positive")
private Integer age; // > 0
@PositiveOrZero(message = "Quantity cannot be negative")
private Integer quantity; // >= 0
@Positive(message = "Price must be greater than 0")
private BigDecimal price; // > 0
@Min(0)
@Max(5)
private Integer rating; // 0 до 5
@PositiveOrZero
private Long views; // >= 0
// Getters and setters
}
// Repository
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
// Только положительные цены
List<Product> findByPriceGreaterThan(BigDecimal minPrice);
// Только товары с положительным количеством
List<Product> findByQuantityGreaterThan(int minQuantity);
}
Вывод
В Java используются char (0-65535) и byte (с методами unsigned для работы). В SQL используются UNSIGNED типы (MySQL, PostgreSQL) или CHECK constraints (SQL Server). Для приложений рекомендуется использовать @Positive и @PositiveOrZero аннотации для валидации данных. Правильный выбор типов и ограничений помогает предотвратить ошибки на уровне базы данных и приложения.