You would still have null, but only when asked for and checked explicitly.
In Kotlin, for example, you mark something with a question mark to say that it can be null, which forces you to check for null before using it:
val entityOrPossiblyNull: Entity? = Entity.fetch(id)
if (entityOrPossiblyNull == null) {
doSomething()
}
else {
// The compiler knows that the variable is not null in this branch,
// so this assignment is OK.
val entityForSure: Entity = entityOrPossiblyNull
doSomethingWithEntity(entityForSure)
}
The real problem isn't null itself, it's that in most languages that have it, null inhabits all types (or at least all reference types).
Different languages solve this problem in different ways. Many languages get rid of null entirely, and use option types in its place. Other languages, like Kotlin, fix it in the type system, by differentiating between e.g. String and nullable String (spelled String? in Kotlin) .
https://medium.com/@hinchman_amanda/null-pointer-references-...
https://www.infoq.com/presentations/Null-References-The-Bill...
https://www.quora.com/Why-was-the-Null-Pointer-Exception-in-...
https://www.lucidchart.com/techblog/2015/08/31/the-worst-mis...