Recommendation: Use Wrapper Types for POJO Fields and Avoid Default Values to Prevent Common Pitfalls
The article advises that POJO class attributes should always use wrapper types without preset default values, illustrating several pitfalls such as null‑overridden defaults during Jackson deserialization, BeanUtils copy failures, MyBatis dynamic SQL issues, and RPC/API default‑value bugs.
Recommendation: POJO class attributes should always be wrapper types and should not have any default values.
When developers assign default values to POJO fields—either explicitly for wrapper types or implicitly for primitive types—various subtle bugs can arise.
Pitfall 1: Deserialization may allow null to overwrite default values.
Using Jackson, a JSON payload with {"id":null,"name":null,"address":""} will cause the id field, which had a default of 0L , to become null after deserialization, losing the intended default.
package com.renzhikeji.demo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.builder.ToStringBuilder;
public class Demo {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
String json = "{\"id\":null,\"name\":null,\"address\":\"\"}";
POJO value = mapper.readValue(json, POJO.class);
System.out.println(value);
}
public static class POJO {
private Long id = 0L;
private String name;
private String address = "";
// getters and setters omitted for brevity
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("name", name)
.append("address", address)
.toString();
}
}
}Pitfall 2: Converting between POJO and DTO can throw exceptions when types differ.
Spring's BeanUtils.copyProperties fails when a primitive field in the target DTO expects a non‑null value but the source POJO provides a wrapper type set to null .
package com.renzhikeji.demo;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.beans.BeanUtils;
public class Demo {
public static void main(String[] args) throws JsonProcessingException {
POJO pojo = new POJO();
pojo.setId(null);
DTO dto = new DTO();
BeanUtils.copyProperties(pojo, dto);
System.out.println(dto);
}
public static class POJO {
private Long id = 0L;
private String name;
private String address = "";
// getters and setters omitted
}
public static class DTO {
private long id = 0L;
private String name;
private String address = "";
// getters and setters omitted
}
}Pitfall 3: MyBatis dynamic SQL may lose its intended logic.
If a POJO field has a default value but the dynamic SQL checks for != null , the default value prevents the if clause from executing, causing incorrect query conditions.
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>Pitfall 4: API or RPC interfaces returning default numeric values can mask errors.
When a billing RPC returns a rate field as 0.0 (the default for a primitive double) instead of null , calculations may proceed with a zero rate, leading to unnoticed zero‑charge incidents.
Conclusion
Using wrapper types without preset defaults eliminates these hidden bugs and makes null‑related failures explicit, improving code reliability.
Cognitive Technology Team
Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.