This chapter described the following problem: We have aBox
class, written to be generally useful so it deals withObject
s. We need an instance that takes onlyInteger
s. The comments say that onlyInteger
s go in, so the programmer knows this (or should know it), but the compiler doesn't know it. This means that the compiler can't catch someone erroneously adding aString
. When we read the value and cast it to anInteger
we'll get an exception, but that's not ideal since the exception may be far removed from the bug in both space and time:
- Debugging may be difficult, as the point in the code where the exception is thrown may be far removed from the point in the code where the error is located.
- It's always better to catch bugs when compiling than when running.
Specifically, you learned that generic type declarations can include one or more type parameters; you supply one type argument for each type parameter when you use the generic type. You also learned that type parameters can be used to define generic methods and constructors. Bounded type parameters limit the kinds of types that can be passed into a type parameter; they can specify an upper bound only. Wildcards represent unknown types, and they can specify an upper or lower bound. During compilation, type erasure removes all generic information from a generic class or interface, leaving behind only its raw type. It is possible for generic code and legacy code to interact, but in many cases the compiler will emit a warning telling you to recompile with special flags for more details.
For additional information on this topic, see Generics by Gilad Bracha.