The setter’s body code is purposefully allowed to do whatever it wants. It could access the field before assigning it. It might never even assign the field at all. So, for example, if it accesses the field before assigning it, the field would not be initialized yet.
In the end, it probably comes down to current flow analysis not being powerful enough to guarantee the field gets initialized before access.
If you consider how this class is compiled into jvm byte code, it becomes very clear. Personally I don’t like explanations that use the jvm as an excuse, though it shows how this could be a complex problem to solve.