chinabugotech/hutool · error · IllegalArgumentException

[{}] is not a primitive class!

Error message

[{}] is not a primitive class!

What it means

Thrown by the PrimitiveConverter constructor when the class passed in is not a Java primitive type (byte, short, int, long, float, double, char, boolean). The constructor explicitly checks clazz.isPrimitive() and rejects wrapper classes (Integer.class, String.class, etc.) or any reference type. This is a hard precondition — PrimitiveConverter only handles the eight primitive class literals.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java:42

 *
 * @author Looly
 */
public class PrimitiveConverter extends AbstractConverter<Object> {
	private static final long serialVersionUID = 1L;

	private final Class<?> targetType;

	/**
	 * 构造<br>
	 *
	 * @param clazz 需要转换的原始
	 * @throws IllegalArgumentException 传入的转换类型非原始类型时抛出
	 */
	public PrimitiveConverter(Class<?> clazz) {
		if (null == clazz) {
			throw new NullPointerException("PrimitiveConverter not allow null target type!");
		} else if (false == clazz.isPrimitive()) {
			throw new IllegalArgumentException("[" + clazz + "] is not a primitive class!");
		}
		this.targetType = clazz;
	}

	@Override
	protected Object convertInternal(Object value) {
		return PrimitiveConverter.convert(value, this.targetType, this::convertToStr);
	}

	@Override
	protected String convertToStr(Object value) {
		return StrUtil.trim(super.convertToStr(value));
	}

	@Override
	@SuppressWarnings("unchecked")
	public Class<Object> getTargetType() {
		return (Class<Object>) this.targetType;

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Pass the primitive class literal: use int.class, long.class, byte.class, etc. instead of Integer.class, Long.class.
  2. If you hold an arbitrary Class<?>, gate it with clazz.isPrimitive() before constructing PrimitiveConverter.
  3. For wrapper types, use the corresponding NumberConverter or Convert.convert(WrapperType.class, value) directly instead of PrimitiveConverter.
  4. If the class comes from reflection, resolve it to its primitive equivalent via a lookup or check Class.isPrimitive() first and fall back to the wrapper converter.

Example fix

// before
new PrimitiveConverter(Integer.class); // throws

// after
new PrimitiveConverter(int.class);
// or for wrapper types:
Convert.convert(Integer.class, value);
Defensive patterns

Strategy: validation

Validate before calling

if (clazz == null || !clazz.isPrimitive()) {
    // use NumberConverter or other appropriate converter
    throw new IllegalArgumentException("Class must be primitive");
}
new PrimitiveConverter(clazz);

Type guard

static boolean isSupportedPrimitive(Class<?> clazz) {
    return clazz != null && clazz.isPrimitive() && clazz != void.class;
}

Try / catch

try {
    new PrimitiveConverter(targetClass);
} catch (IllegalArgumentException e) {
    // fall back to wrapper conversion
    Convert.convert(wrapperFor(targetClass), value);
}

Prevention

When it happens

Trigger: Directly instantiating 'new PrimitiveConverter(Integer.class)' or 'new PrimitiveConverter(String.class)'. Indirectly triggered when ConverterRegistry or Convert.convert routes a target type to PrimitiveConverter with a non-primitive Class object (e.g., passing Integer.class where int.class was intended, or a custom converter registration mismatch).

Common situations: Passing a wrapper class (Integer.class) instead of the primitive literal (int.class). Dynamically deriving the target Class from reflection (Field.getType() on a generic field) and handing it to the converter without checking isPrimitive(). Custom ConverterRegistry registrations that misroute types.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/b00e73c4ec22ac87. Report an issue: GitHub.