Cover
contents
preface
A few basics
1.1 Reflection’s value proposition
1.2 Enter George the programmer
1.2.1 Choosing reflection
1.2.2 Programming a reflective solution
1.3 Examining running programs
1.4 Finding a method at runtime
1.5 Representing types with class objects
1.5.1 Representing primitive types
1.5.2 Representing interfaces
1.5.3 Representing array types
1.6 Understanding method objects
1.6.1 Using dynamic invocation
1.6.2 Using primitives with dynamic invocation
1.6.3 Avoiding invocation pitfalls
1.7 Diagramming for reflection
1.8 Navigating the inheritance hierarchy
1.8.1 Introspecting the inheritance hierarchy
1.8.2 Exposing some surprises
1.8.3 Another reflective circularity
1.9 Summary
Accessing fields reflectively
2.1 Serializing objects
2.1.1 Serializing to XML
2.1.2 Choosing reflection
2.1.3 Designing serialization with reflection
2.2 Finding fields at runtime
2.3 Understanding field objects
2.4 Getting and setting field values
2.5 Examining modifiers
2.5.1 Introducing Member
2.5.2 Interface introspection pitfall
2.5.3 Introspecting for instance variables
2.6 Accessing nonpublic members
2.7 Working with arrays
2.8 Serialization: putting it all together
2.8.1 Serializing each component
2.8.2 Serializing instance variables
2.9 Using reflective serialization
2.10 Summary
Dynamic loading and reflective construction
3.1 George’s deployment problem
3.1.1 Designing with patterns
3.1.2 Programming a reflective solution
3.1.3 Enhancing the factory method with reflection
3.1.4 Combining benefits of delegation and reflection
3.2 Loading classes dynamically
3.2.1 Basics of forName
3.2.2 Getting array classes
3.2.3 Primitives and forName
3.3 Constructing objects reflectively
3.3.1 Reflective construction basics
3.3.2 Using constructor objects
3.3.3 Constructing arrays reflectively
3.4 Designing for dynamic loading
3.4.1 Disadvantages of reflective construction with arguments
3.4.2 Initializing through an interface
3.5 Implementing deserialization
3.5.1 Initiating deserialization
3.5.2 Constructing the instances
3.5.3 Restoring the object structure
3.6 George’s serialization: limitations
3.6.1 No interaction with readObject or writeObject
3.6.2 No handling of final instance variables
3.6.3 Only no-argument constructors
3.6.4 No handling of illegal XML characters
3.6.5 Performance
3.7 Summary
Using Java dynamic proxy
4.1 Working with proxies
4.2 George’s tracing problem
4.3 Exploring Proxy
4.3.1 Understanding invocation handlers
4.3.2 Handling the methods of Object
4.4 Implementing a tracing proxy
4.5 A note on factories
4.6 Chaining proxies
4.6.1 Structuring invocation handlers for chaining
4.6.2 Implementing a synchronized proxy
4.6.3 Chaining the two proxies
4.7 Stubbing interfaces for unit testing
4.7.1 Examining stubs
4.7.2 Design for stubbing with Proxy
4.7.3 Implementation of stubbing with Proxy
4.8 Generating SOAP remote proxies
4.9 Pitfalls of using Proxy
4.10 Summary
Call stack introspection
5.1 George’s logging problem
5.2 Performing call stack introspection
5.3 Logging with call stack introspection
5.4 Pitfalls
5.5 Class invariant checking
5.6 Summary
Using the class loader
6.1 George’s test problem
6.2 Essentials of ClassLoader
6.2.1 Understanding the delegation model
6.2.2 Programming a simple class loader
6.2.3 Reinitializing static fields: a solution
6.3 Multiple namespaces
6.4 Dynamic class replacement
6.4.1 Designing for replacement
6.4.2 Implementing replacement
6.4.3 Simplifying assumptions
6.5 Additional considerations
6.5.1 Security
6.5.2 Don’t reinvent the wheel
6.5.3 Modifying bytecode in a class loader
6.5.4 When not to invent a specialized class loader
6.5.5 Additional examples
6.5.6 Endorsed Standards Override
6.6 Summary
Reflective code generation
Reflective code generation
7.1 Generating HelloWorld.java
7.2 Class-to-class transformation framework
7.2.1 C2C
7.2.2 Args
7.2.3 C2CConstructor
7.2.4 C2CTransformation
7.3 Example: extent management
7.4 C2IdentitySubclassOfC and its subclasses
7.5 UQueue
7.6 Using the framework
7.7 Relation to Aspect-Oriented Programming
7.8 Summary
Design patterns
8.1 Singleton
8.2 Decorator class-to-class transformations
8.3 Proxy (again)
8.4 Another composition feature
8.5 Problematic issues in writing class-to-class transformations
8.6 Summary
Evaluating performance
Evaluating performance
9.1 Categorizing performance impact
9.2 Using microbenchmarks
9.3 Benchmarking two ways to use Proxy
9.4 Understanding Amdahl’s Law
9.5 Applying Amdahl’s Law
9.6 Summary
Reflecting on the future
10.1 Looking forward: Java 1.5
10.1.1 JSR 14-Generics
10.1.2 JSR 175-Annotation Facility
10.1.3 JSR 201-Language extensions
10.1.4 Impact of Java 1.5 on reflective code
10.2 Looking forward: competition for Java reflection
10.2.1 C#
10.2.2 Python
10.2.3 Smalltalk
10.2.4 CLOS
10.2.5 Ruby
10.2.6 Perl
10.3 Looking forward: Aspect-Oriented Programming
10.4 Looking forward: your career
Reflection and metaobject protocols
A.1 Reflection
A.2 Reflective object-oriented programming
A.3 Inheritance
A.4 Metaobject protocols
A.5 Metaclasses
A.6 Class-to-class transformations
Handling compilation errors in the “Hello world!” program
UML
glossary
references
index