Primitives, which include integers, strings, doubles, arrays, and other low-level language elements, are generic because many people use them. Classes, on the other hand, may be as specific as you need them to be because you create them for specific purposes. In many cases, classes provide a simpler and more natural way to model things than primitives. In addition, once you create a class, you'll often discover that other code in a system belongs in that class.
Fowler and Beck [F] explain how Primitive Obsession manifests itself when code relies too much on primitives. This typically occurs when you haven't yet seen how a higher-level abstraction can clarify or simplify your code. Fowler's refactorings include many of the most common solutions for addressing this problem. This book builds on those solutions and offers more.
If a primitive value controls logic in a class and the primitive value isn't type-safe (i.e., clients can assign it to an unsafe or incorrect value), consider applying Replace Type Code with Class (286). The result will be code that is type-safe and capable of being extended by new behavior (something you can't do with a primitive).
If an object's state transitions are controlled by complex conditional logic that uses primitive values, you can use Replace State-Altering Conditionals with State (166). The result will be numerous classes to represent each state and simplified state transition logic.
If complicated conditional logic controls which algorithm to run and that logic relies on primitive values, consider applying Replace Conditional Logic with Strategy (129).
If you implicitly create a tree structure using a primitive representation, such as a string, your code may be difficult to work with, prone to errors, and/or filled with duplication. Applying Replace Implicit Tree with Composite (178) will reduce these problems.
If many methods of a class exist to support numerous combinations of primitive values, you may have an implicit language. If so, consider applying Replace Implicit Language with Interpreter (269).
If primitive values exist in a class only to provide embellishments to the class's core responsibility, you may want to use Move Embellishment to Decorator (144).
Finally, even if you have a class, it may still be too primitive to make life easy for clients. This may be the case if you have a Composite [DP] implementation that is tricky to work with. You can simplify how clients build the Composite by applying Encapsulate Composite with Builder (96).