You should either use an interface (not inheritance) or some kind of property mechanic (maybe even something that works like the resource description framework).
So either
interface Colored {
Color getColor();
}
class ColoredBook extends Book implements Colored {
...
}
or
class PropertiesHolder {
<T> extends Property<?>> Optional<T> getProperty( Class<T> propertyClass ) { ... }
<V, T extends Property<V>> Optional<V> getPropertyValue( Class<T> propertyClass ) { ... }
}
interface Property<T> {
String getName();
T getValue();
}
class ColorProperty implements Property<Color> {
public Color getValue() { ... }
public String getName() { return "color"; }
}
class Book extends PropertiesHolder {
}
Clarification (edit):
Simply adding optional fields in the entity class
Especially with the Optional-wrapper(edit: see 4castle's answer) I think this (adding fields in the original entity) is a viable way to add new properties in a small scale. The biggest problem with this approach is that it might work against low coupling.
Imagine your book class is defined in a dedicated project for your domain model. Now you add another project that uses the domain model to do a special task. This task requires an additional property in the book class. Either you end up with inheritance (see below) or you have to change the common domain model to make the new task possible. In the latter case you may end up with a bunch of projects that all depend on their own properties added to the book class while the book class itself in a way depends on these projects, because you are not able to understand the book class without the additional projects.
Why is inheritance problematic when it comes to a way to provide additional properties?
When I see your example class "Book" I think about a domain object that often ends up having many optional fields and subtypes. Just imagine you want to add a property for books that include a CD. There are now four kinds of books: books, books with color, books with CD, books with color and CD. You cannot describe this situation with inheritance in Java.
With interfaces you circumvent this issue. You can easily compose the properties of a specific book class with interfaces. Delegation and composition will make it easy to get exactly the class you want. With inheritance you usually end up with some optional properties in the class that are only there because a sibling class needs them.
Further reading why inheritance is often a problematic idea:
Why is inheritance generally viewed as a bad thing by OOP proponents
JavaWorld: Why extends is evil
The problem with implementing a set of interfaces to compose a set of properties
When you use interfaces for extension everything is fine as long as you have just a small set of them. Especially when your object model is used and extended by other developers e.g. in your company the amount of interfaces will grow. And eventually you end up creating a new official "property-interface" that adds a method your colleagues already used in their project for customer X for a completely unrelated use case - Ugh.
edit: Another important aspect is mentioned by gnasher729. You often want to dynamically add optional properties to an existing object. With inheritance or interfaces you would have to recreate the whole object with another class which is far from optional.
When you expect extensions to your object model to such an extent you will be better off by explicitly modelling the possibility of dynamic extension. I propose something like above where each "extension" (in this case property) has its own class. The class works as namespace and identifier for the extension. When you set the package naming conventions accordingly this way allows an infinite amount of extensions without polluting the namespace for methods in the original entity class.
In game development you often encounter situations where you want to compose behavior and data in many variations. This is why the architecture pattern entity-component-system got pretty popular in game development circles. This is also an interesting approach you might want to look at, when you expect many extensions to your object model.