You are previewing Learning Java, 4th Edition.

Learning Java, 4th Edition

Cover of Learning Java, 4th Edition by Daniel Leuck... Published by O'Reilly Media, Inc.
  1. Learning Java
  2. Preface
    1. Who Should Read This Book
    2. New Developments
      1. New in This Edition (Java 6 and 7)
    3. Using This Book
    4. Online Resources
    5. Conventions Used in This Book
    6. Using Code Examples
    7. Safari® Books Online
    8. How to Contact Us
    9. Acknowledgments
  3. 1. A Modern Language
    1. Enter Java
      1. Java’s Origins
      2. Growing Up
    2. A Virtual Machine
    3. Java Compared with Other Languages
    4. Safety of Design
      1. Simplify, Simplify, Simplify...
      2. Type Safety and Method Binding
      3. Incremental Development
      4. Dynamic Memory Management
      5. Error Handling
      6. Threads
      7. Scalability
    5. Safety of Implementation
      1. The Verifier
      2. Class Loaders
      3. Security Managers
    6. Application and User-Level Security
    7. A Java Road Map
      1. The Past: Java 1.0–Java 1.6
      2. The Present: Java 7
      3. The Future
      4. Availability
  4. 2. A First Application
    1. Java Tools and Environment
    2. Configuring Eclipse and Creating a Project
      1. Importing the Learning Java Examples
    3. HelloJava
      1. Classes
      2. The main() Method
      3. Classes and Objects
      4. Variables and Class Types
      5. HelloComponent
      6. Inheritance
      7. The JComponent Class
      8. Relationships and Finger Pointing
      9. Package and Imports
      10. The paintComponent() Method
    4. HelloJava2: The Sequel
      1. Instance Variables
      2. Constructors
      3. Events
      4. The repaint() Method
      5. Interfaces
    5. HelloJava3: The Button Strikes!
      1. Method Overloading
      2. Components
      3. Containers
      4. Layout
      5. Subclassing and Subtypes
      6. More Events and Interfaces
      7. Color Commentary
      8. Static Members
      9. Arrays
      10. Our Color Methods
    6. HelloJava4: Netscape’s Revenge
      1. Threads
      2. The Thread Class
      3. The Runnable Interface
      4. Starting the Thread
      5. Running Code in the Thread
      6. Exceptions
      7. Synchronization
  5. 3. Tools of the Trade
    1. JDK Environment
    2. The Java VM
    3. Running Java Applications
      1. System Properties
    4. The Classpath
      1. javap
    5. The Java Compiler
    6. JAR Files
      1. File Compression
      2. The jar Utility
      3. The pack200 Utility
    7. Policy Files
      1. The Default Security Manager
      2. The policytool Utility
      3. Using a Policy File with the Default Security Manager
  6. 4. The Java Language
    1. Text Encoding
      1. Javadoc Comments
    3. Types
      1. Primitive Types
      2. Reference Types
      3. A Word About Strings
    4. Statements and Expressions
      1. Statements
      2. Expressions
    5. Exceptions
      1. Exceptions and Error Classes
      2. Exception Handling
      3. Bubbling Up
      4. Stack Traces
      5. Checked and Unchecked Exceptions
      6. Throwing Exceptions
      7. try Creep
      8. The finally Clause
      9. Try with Resources
      10. Performance Issues
    6. Assertions
      1. Enabling and Disabling Assertions
      2. Using Assertions
    7. Arrays
      1. Array Types
      2. Array Creation and Initialization
      3. Using Arrays
      4. Anonymous Arrays
      5. Multidimensional Arrays
      6. Inside Arrays
  7. 5. Objects in Java
    1. Classes
      1. Accessing Fields and Methods
      2. Static Members
    2. Methods
      1. Local Variables
      2. Shadowing
      3. Static Methods
      4. Initializing Local Variables
      5. Argument Passing and References
      6. Wrappers for Primitive Types
      7. Autoboxing and Unboxing of Primitives
      8. Variable-Length Argument Lists
      9. Method Overloading
    3. Object Creation
      1. Constructors
      2. Working with Overloaded Constructors
      3. Static and Nonstatic Initializer Blocks
    4. Object Destruction
      1. Garbage Collection
      2. Finalization
      3. Weak and Soft References
    5. Enumerations
      1. Enum Values
      2. Customizing Enumerations
  8. 6. Relationships Among Classes
    1. Subclassing and Inheritance
      1. Shadowed Variables
      2. Overriding Methods
      3. Special References: this and super
      4. Casting
      5. Using Superclass Constructors
      6. Full Disclosure: Constructors and Initialization
      7. Abstract Methods and Classes
    2. Interfaces
      1. Interfaces as Callbacks
      2. Interface Variables
      3. Subinterfaces
    3. Packages and Compilation Units
      1. Compilation Units
      2. Package Names
      3. Class Visibility
      4. Importing Classes
    4. Visibility of Variables and Methods
      1. Basic Access Modifiers
      2. Subclasses and Visibility
      3. Interfaces and Visibility
    5. Arrays and the Class Hierarchy
      1. ArrayStoreException
    6. Inner Classes
      1. Inner Classes as Adapters
      2. Inner Classes Within Methods
  9. 7. Working with Objects and Classes
    1. The Object Class
      1. Equality and Equivalence
      2. Hashcodes
      3. Cloning Objects
    2. The Class Class
    3. Reflection
      1. Modifiers and Security
      2. Accessing Fields
      3. Accessing Methods
      4. Accessing Constructors
      5. What About Arrays?
      6. Accessing Generic Type Information
      7. Accessing Annotation Data
      8. Dynamic Interface Adapters
      9. What Is Reflection Good For?
    4. Annotations
      1. Using Annotations
      2. Standard Annotations
      3. The apt Tool
  10. 8. Generics
    1. Containers: Building a Better Mousetrap
      1. Can Containers Be Fixed?
    2. Enter Generics
      1. Talking About Types
    3. “There Is No Spoon”
      1. Erasure
      2. Raw Types
    4. Parameterized Type Relationships
      1. Why Isn’t a List<Date> a List<Object>?
    5. Casts
    6. Writing Generic Classes
      1. The Type Variable
      2. Subclassing Generics
      3. Exceptions and Generics
      4. Parameter Type Limitations
    7. Bounds
      1. Erasure and Bounds (Working with Legacy Code)
    8. Wildcards
      1. A Supertype of All Instantiations
      2. Bounded Wildcards
      3. Thinking Outside the Container
      4. Lower Bounds
      5. Reading, Writing, and Arithmetic
      6. <?>, <Object>, and the Raw Type
      7. Wildcard Type Relationships
    9. Generic Methods
      1. Generic Methods Introduced
      2. Type Inference from Arguments
      3. Type Inference from Assignment Context
      4. Explicit Type Invocation
      5. Wildcard Capture
      6. Wildcard Types Versus Generic Methods
    10. Arrays of Parameterized Types
      1. Using Array Types
      2. What Good Are Arrays of Generic Types?
      3. Wildcards in Array Types
    11. Case Study: The Enum Class
    12. Case Study: The sort() Method
    13. Conclusion
  11. 9. Threads
    1. Introducing Threads
      1. The Thread Class and the Runnable Interface
      2. Controlling Threads
      3. Death of a Thread
    2. Threading an Applet
      1. Issues Lurking
    3. Synchronization
      1. Serializing Access to Methods
      2. Accessing class and instance Variables from Multiple Threads
      3. The wait() and notify() Methods
      4. Passing Messages
      5. ThreadLocal Objects
    4. Scheduling and Priority
      1. Thread State
      2. Time-Slicing
      3. Priorities
      4. Yielding
    5. Thread Groups
      1. Working with ThreadGroups
      2. Uncaught Exceptions
    6. Thread Performance
      1. The Cost of Synchronization
      2. Thread Resource Consumption
    7. Concurrency Utilities
      1. Executors
      2. Locks
      3. Synchronization Constructs
      4. Atomic Operations
    8. Conclusion
  12. 10. Working with Text
    1. Text-Related APIs
    2. Strings
      1. Constructing Strings
      2. Strings from Things
      3. Comparing Strings
      4. Searching
      5. Editing
      6. String Method Summary
      7. StringBuilder and StringBuffer
    3. Internationalization
      1. The java.util.Locale Class
      2. Resource Bundles
    4. Parsing and Formatting Text
      1. Parsing Primitive Numbers
      2. Tokenizing Text
    5. Printf-Style Formatting
      1. Formatter
      2. The Format String
      3. String Conversions
      4. Primitive and Numeric Conversions
      5. Flags
      6. Miscellaneous
    6. Formatting with the java.text Package
      1. MessageFormat
    7. Regular Expressions
      1. Regex Notation
      2. The java.util.regex API
  13. 11. Core Utilities
    1. Math Utilities
      1. The java.lang.Math Class
      2. Big/Precise Numbers
      3. Floating-Point Components
      4. Random Numbers
    2. Dates and Times
      1. Working with Calendars
      2. Time Zones
      3. Parsing and Formatting with DateFormat
      4. Printf-Style Date and Time Formatting
    3. Timers
    4. Collections
      1. The Collection Interface
      2. Iterator
      3. Collection Types
      4. The Map Interface
      5. Collection Implementations
      6. Hash Codes and Key Values
      7. Synchronized and Unsynchronized Collections
      8. Read-Only and Read-Mostly Collections
      9. WeakHashMap
      10. EnumSet and EnumMap
      11. Sorting Collections
      12. A Thrilling Example
    5. Properties
      1. Loading and Storing
      2. System Properties
    6. The Preferences API
      1. Preferences for Classes
      2. Preferences Storage
      3. Change Notification
    7. The Logging API
      1. Overview
      2. Logging Levels
      3. A Simple Example
      4. Logging Setup Properties
      5. The Logger
      6. Performance
    8. Observers and Observables
  14. 12. Input/Output Facilities
    1. Streams
      1. Basic I/O
      2. Character Streams
      3. Stream Wrappers
      4. Pipes
      5. Streams from Strings and Back
      6. Implementing a Filter Stream
    2. File I/O
      1. The Class
      2. File Streams
      3. RandomAccessFile
      4. Resource Paths
    3. The NIO File API
      1. FileSystem and Path
      2. NIO File Operations
      3. Directory Operations
      4. Watching Paths
    4. Serialization
      1. Initialization with readObject()
      2. SerialVersionUID
    5. Data Compression
      1. Archives and Compressed Data
      2. Decompressing Data
      3. Zip Archive As a Filesystem
    6. The NIO Package
      1. Asynchronous I/O
      2. Performance
      3. Mapped and Locked Files
      4. Channels
      5. Buffers
      6. Character Encoders and Decoders
      7. FileChannel
      8. Scalable I/O with NIO
  15. 13. Network Programming
    1. Sockets
      1. Clients and Servers
      2. author="pat” timestamp="20120926T110720-0500” comment="one of those sections I hate to get rid of but is less relevant in terms of the example... should probably find a more modern example...”The DateAtHost Client
      3. The TinyHttpd Server
      4. Socket Options
      5. Proxies and Firewalls
    2. Datagram Sockets
      1. author="pat” timestamp="20120926T141346-0500” comment="I actually rewrote this as a standalone client but then decided to leave it as an applet”The HeartBeat Applet
      2. InetAddress
    3. Simple Serialized Object Protocols
      1. A Simple Object-Based Server
    4. Remote Method Invocation
      1. Real-World Usage
      2. Remote and Nonremote Objects
      3. An RMI Example
      4. RMI and CORBA
    5. Scalable I/O with NIO
      1. Selectable Channels
      2. Using Select
      3. LargerHttpd
      4. Nonblocking Client-Side Operations
  16. 14. Programming for the Web
    1. Uniform Resource Locators (URLs)
    2. The URL Class
      1. Stream Data
      2. Getting the Content as an Object
      3. Managing Connections
      4. Handlers in Practice
      5. Useful Handler Frameworks
    3. Talking to Web Applications
      1. Using the GET Method
      2. Using the POST Method
      3. The HttpURLConnection
      4. SSL and Secure Web Communications
      5. URLs, URNs, and URIs
    4. Web Services
      1. XML-RPC
      2. WSDL
      3. The Tools
      4. The Weather Service Client
  17. 15. Web Applications and Web Services
    1. Web Application Technologies
      1. Page-Oriented Versus “Single Page” Applications
      2. JSPs
      3. XML and XSL
      4. Web Application Frameworks
      5. Google Web Toolkit
      6. HTML5, AJAX, and More...
    2. Java Web Applications
      1. The Servlet Lifecycle
      2. Servlets
      3. The HelloClient Servlet
      4. The Servlet Response
      5. Servlet Parameters
      6. The ShowParameters Servlet
      7. User Session Management
      8. The ShowSession Servlet
      9. The ShoppingCart Servlet
      10. Cookies
      11. The ServletContext API
      12. Asynchronous Servlets
    3. WAR Files and Deployment
      1. Configuration with web.xml and Annotations
      2. URL Pattern Mappings
      3. Deploying HelloClient
      4. Error and Index Pages
      5. Security and Authentication
      6. Protecting Resources with Roles
      7. Secure Data Transport
      8. Authenticating Users
      9. Procedural Authorization
    4. Servlet Filters
      1. A Simple Filter
      2. A Test Servlet
      3. Declaring and Mapping Filters
      4. Filtering the Servlet Request
      5. Filtering the Servlet Response
    5. Building WAR Files with Ant
      1. A Development-Oriented Directory Layout
      2. Deploying and Redeploying WARs with Ant
    6. Implementing Web Services
      1. Defining the Service
      2. Our Echo Service
      3. Using the Service
      4. Data Types
    7. Conclusion
  18. 16. Swing
    1. Components
      1. Peers and Look-and-Feel
      2. The MVC Framework
      3. Painting
      4. Enabling and Disabling Components
      5. Focus, Please
      6. Other Component Methods
      7. Layout Managers
      8. Insets
      9. Z-Ordering (Stacking Components)
      10. The revalidate() and doLayout() Methods
      11. Managing Components
      12. Listening for Components
      13. Windows, Frames and Splash Screens
      14. Other Methods for Controlling Frames
      15. Content Panes
      16. Desktop Integration
    2. Events
      1. Event Receivers and Listener Interfaces
      2. Event Sources
      3. Event Delivery
      4. Event Types
      5. The java.awt.event.InputEvent Class
      6. Mouse and Key Modifiers on InputEvents
      7. Focus Events
    3. Event Summary
      1. Adapter Classes
      2. Dummy Adapters
    4. The AWT Robot!
    5. Multithreading in Swing
  19. 17. Using Swing Components
    1. Buttons and Labels
      1. HTML Text in Buttons and Labels
    2. Checkboxes and Radio Buttons
    3. Lists and Combo Boxes
    4. The Spinner
    5. Borders
    6. Menus
    7. Pop-Up Menus
      1. Component-Managed Pop Ups
    8. The JScrollPane Class
    9. The JSplitPane Class
    10. The JTabbedPane Class
    11. Scrollbars and Sliders
    12. Dialogs
      1. File Selection Dialog
      2. The Color Chooser
  20. 18. More Swing Components
    1. Text Components
      1. The TextEntryBox Application
      2. Formatted Text
      3. Filtering Input
      4. Validating Data
      5. Say the Magic Word
      6. Sharing a Data Model
      7. HTML and RTF for Free
      8. Managing Text Yourself
    2. Focus Navigation
      1. Trees
      2. Nodes and Models
      3. Save a Tree
      4. Tree Events
      5. A Complete Example
    3. Tables
      1. A First Stab: Freeloading
      2. Round Two: Creating a Table Model
      3. Round Three: A Simple Spreadsheet
      4. Sorting and Filtering
      5. Printing JTables
    4. Desktops
    5. Pluggable Look-and-Feel
    6. Creating Custom Components
      1. Generating Events
      2. A Dial Component
      3. Model and View Separation
  21. 19. Layout Managers
    1. FlowLayout
    2. GridLayout
    3. BorderLayout
    4. BoxLayout
    5. CardLayout
    6. GridBagLayout
      1. The GridBagConstraints Class
      2. Grid Coordinates
      3. The fill Constraint
      4. Spanning Rows and Columns
      5. Weighting
      6. Anchoring
      7. Padding and Insets
      8. Relative Positioning
      9. Composite Layouts
    7. Other Layout Managers
    8. Absolute Positioning
  22. 20. Drawing with the 2D API
    1. The Big Picture
    2. The Rendering Pipeline
    3. A Quick Tour of Java 2D
      1. Filling Shapes
      2. Drawing Shape Outlines
      3. Convenience Methods
      4. Drawing Text
      5. Drawing Images
      6. The Whole Iguana
    4. Filling Shapes
      1. Solid Colors
      2. Color Gradients
      3. Textures
      4. Desktop Colors
    5. Stroking Shape Outlines
    6. Using Fonts
      1. Font Metrics
    7. Displaying Images
      1. The Image Class
      2. Image Observers
      3. Scaling and Size
    8. Drawing Techniques
      1. Double Buffering
      2. Limiting Drawing with Clipping
      3. Offscreen Drawing
    9. Printing
  23. 21. Working with Images and Other Media
    1. Loading Images
      1. ImageObserver
      2. MediaTracker
      3. ImageIcon
      4. ImageIO
    2. Producing Image Data
      1. Drawing Animations
      2. BufferedImage Anatomy
      3. Color Models
      4. Creating an Image
      5. Updating a BufferedImage
    3. Filtering Image Data
      1. How ImageProcessor Works
      2. Converting an Image to a BufferedImage
      3. Using the RescaleOp Class
      4. Using the AffineTransformOp Class
    4. Saving Image Data
    5. Simple Audio
    6. Java Media Framework
  24. 22. JavaBeans
    1. What’s a Bean?
      1. What Constitutes a Bean?
    2. The NetBeans IDE
      1. Installing and Running NetBeans
    3. Properties and Customizers
    4. Event Hookups and Adapters
      1. Taming the Juggler
      2. Molecular Motion
    5. Binding Properties
      1. Constraining Properties
    6. Building Beans
      1. The Dial Bean
      2. Design Patterns for Properties
    7. Limitations of Visual Design
    8. Serialization Versus Code Generation
    9. Customizing with BeanInfo
      1. Getting Properties Information
    10. Handcoding with Beans
      1. Bean Instantiation and Type Management
      2. Working with Serialized Beans
      3. Runtime Event Hookups with Reflection
    11. BeanContext and BeanContextServices
    12. The Java Activation Framework
    13. Enterprise JavaBeans and POJO-Based Enterprise Frameworks
  25. 23. Applets
    1. The Politics of Browser-Based Applications
    2. Applet Support and the Java Plug-in
    3. The JApplet Class
      1. Applet Lifecycle
      2. The Applet Security Sandbox
      3. Getting Applet Resources
      4. The <applet> Tag
      5. Attributes
      6. Parameters
      7. ¿Habla Applet?
      8. The Complete <applet> Tag
      9. Loading Class Files
      10. Packages
      11. appletviewer
    4. Java Web Start
    5. Conclusion
  26. 24. XML
    1. The Butler Did It
    2. A Bit of Background
      1. Text Versus Binary
      2. A Universal Parser
      3. The State of XML
      4. The XML APIs
      5. XML and Web Browsers
    3. XML Basics
      1. Attributes
      2. XML Documents
      3. Encoding
      4. Namespaces
      5. Validation
      6. HTML to XHTML
    4. SAX
      1. The SAX API
      2. Building a Model Using SAX
      3. XMLEncoder/Decoder
    5. DOM
      1. The DOM API
      2. Test-Driving DOM
      3. Generating XML with DOM
      4. JDOM
    6. XPath
      1. Nodes
      2. Predicates
      3. Functions
      4. The XPath API
      5. XMLGrep
    7. XInclude
      1. Enabling XInclude
    8. Validating Documents
      1. Using Document Validation
      2. DTDs
      3. XML Schema
      4. The Validation API
    9. JAXB Code Binding and Generation
      1. Annotating Our Model
      2. Generating a Java Model from an XML Schema
      3. Generating an XML Schema from a Java Model
    10. Transforming Documents with XSL/XSLT
      1. XSL Basics
      2. Transforming the Zoo Inventory
      3. XSLTransform
      4. XSL in the Browser
    11. Web Services
    12. The End of the Book
  27. A. The Eclipse IDE
    1. The IDE Wars
    2. Getting Started with Eclipse
      1. Importing the Learning Java Examples
    3. Using Eclipse
      1. Getting at the Source
      2. The Lay of the Land
      3. Running the Examples
      4. Building the Ant-Based Examples
      5. Loner Examples
    4. Eclipse Features
      1. Coding Shortcuts
      2. Autocorrection
      3. Refactoring
      4. Diffing Files
      5. Organizing Imports
      6. Formatting Source Code
    5. Conclusion
  28. B. BeanShell: Java Scripting
    1. Running BeanShell
    2. Java Statements and Expressions
      1. Imports
    3. BeanShell Commands
    4. Scripted Methods and Objects
      1. Scripting Interfaces and Adapters
    5. Changing the Classpath
    6. Learning More . . .
  29. Glossary
  30. Index
  31. About the Authors
  32. Colophon
  33. Copyright
O'Reilly logo

Generic Methods

Thus far in this chapter, we’ve talked about generic types and the implementation of generic classes. Now, we’re going to look at a different kind of generic animal: generic methods. Generic methods essentially do for individual methods what type parameters do for generic classes. But as we’ll see, generic methods are smarter and can figure out their parameter types from their usage context without having to be explicitly parameterized. (In reality, of course, it is the compiler that does this.) Generic methods can appear in any class (not just generic classes) and are very useful for a wide variety of applications.

First, let’s quickly review the way that we’ve seen regular methods interact with generic types. We’ve seen that generic classes can contain methods that use type variables in their arguments and return types in order to adapt themselves to the parameterization of the class. We’ve also mentioned that generic types themselves can be used in most of the places that any other type can be used. So methods of generic or nongeneric classes can use generic types as argument and return types as well. Here are examples of those usages:

    // Not generic methods

    class GenericClass< T > {
         // method using generic class parameter type
        public void T cache( T entry ) { ... }
    class RegularClass {
         // method using concrete generic type
        public List<Date> sortDates( List<Date> dates ) { ... }
        // method using wildcard generic type
        public List<?> reverse( List<?> dates ) { ... }

The cache() method in GenericClass accepts an argument of the parameter type T and also returns a value of type T. The sortDates() method, which appears in the nongeneric example class, works with a concrete generic type, and the reverse() method works with a wildcard instantiation of a generic type. These are examples of methods that work with generics, but they are not true generic methods.

Generic Methods Introduced

Like generic classes, generic methods have a parameter type declaration using the <> syntax. This syntax appears before the return type of the method:

    // generic method
    <T> T cache( T entry ) { ... }

This cache() method looks very much like our earlier example, except that it has its own parameter type declaration that defines the type variable T. This method is a generic method and can appear in either a generic or nongeneric class. The scope of T is limited to the method cache() and hides any definition of T in any enclosing generic class. As with generic classes, the type T can have bounds:

    <T extends Entry & Cacheable > T cache( T entry ) { ... }

Unlike a generic class, it does not have to be instantiated with a specific parameter type for T before it is used. Instead, it infers the parameter type T from the type of its argument, entry. For example:

    BlogEntry newBlogEntry = ...;
    NewspaperEntry newNewspaperEntry = ...;

    BlogEntry oldEntry = cache( newBlogEntry );
    NewspaperEntry old = cache( newNewspaperEntry );

Here, our generic method cache() inferred the type BlogEntry (which we’ll presume for the sake of the example is a type of Entry and Cacheable). BlogEntry became the type T of the return type and may have been used elsewhere internally by the method. In the next case, the cache() method was used on a different type of Entry and was able to return the new type in exactly the same way. That’s what’s powerful about generic methods: the ability to infer a parameter type from their usage context. We’ll go into detail about that next.

Another difference with generic class components is that generic methods may be static:

    class MathUtils {
        public static <T extends Number> T max( T x, T y ) { ... }

Constructors for classes are essentially methods, too, and follow the same rules as generic methods, minus the return type.

Type Inference from Arguments

In the previous section, we saw a method infer its type from an argument:

    <T> T cache( T entry ) { ... }

But what if there is more than one argument? We saw just that situation in our last snippet, the static generic method max( x, y ). All looks well when we give it two identical types:

    Integer max = MathUtils.max( new Integer(1), new Integer( 2 ) ) ;

But what does it make of the arguments in this invocation?

    MathUtils.max( new Integer(1), new Float( 2 ) ) ;

In this case, the Java compiler does something really smart. It climbs up the argument type parent classes, looking for the nearest common supertype. Java also identifies the nearest common interfaces implemented by both of the types. It identifies that both the Integer and the Float types are subtypes of the Number type. It also recognizes that each of these implements (a certain generic instantiation of) the Comparable interface. Java then effectively makes this combination of types the parameter type of T for this method invocation. The resulting type is, to use the syntax of bounds, Number & Comparable. What this means to us is that the result type T is assignable to anything matching that particular combination of types.

    Number max = MathUtils.max( new Integer(1), new Float( 2 ) );
    Comparable max = MathUtils.max( new Integer(1), new Float( 2 ) );

In English, this statement says that we can work with our Integer and our Float at the same time only if we think of them as Numbers or Comparables, which makes sense. The return type has become a new type, which is effectively a Number that also implements the Comparable interface.

This same inference logic works with any number of arguments. But to be useful, the arguments really have to share some important common supertype or interface. If they don’t have anything in common, the result will be their de facto common ancestor, the Object type. For example, the nearest common supertype of a String and a List is Object along with the Serializeable interface. There’s not much a method could do with a type lacking real bounds anyway.

Type Inference from Assignment Context

We’ve seen a generic method infer its parameter type from its argument types. But what if the type variable isn’t used in any of the arguments or the method has no arguments? Suppose the method only has a parametric return type:

    <T> T foo() { ... }

You might guess that this is an error because the compiler would appear to have no way of determining what type we want. But it’s not! The Java compiler is smart enough to look at the context in which the method is called. Specifically, if the result of the method is assigned to a variable, the compiler tries to make the type of that variable the parameter type. Here’s an example. We’ll make a factory for our Trap objects:

    <T> Trap<T> makeTrap() { return new Trap<T>(); }

    // usage
    Trap<Mouse> mouseTrap = makeTrap();
    Trap<Bear> bearTrap = makeTrap();

The compiler has, as if by magic, determined what kind of instantiation of Trap we want based on the assignment context.

Before you get too excited about the possibilities, there’s not much you can do with a plain type parameter in the body of that method. For example, we can’t create instances of any particular concrete type T, so this limits the usefulness of factories. About all we can do is the sort of thing shown here, where we create instances of generics parameterized correctly for the context.

Furthermore, the inference only works on assignment to a variable. Java does not try to guess the parameter type based on the context if the method call is used in other ways, such as to produce an argument to a method or as the value of a return statement from a method. In those cases, the inferred type defaults to type Object. (See the section for a solution.)

Explicit Type Invocation

Although it should not be needed often, a syntax does exist for invoking a generic method with specific parameter types. The syntax is a bit awkward and involves a class or instance object prefix, followed by the familiar angle bracket type list, placed before the actual method invocation. Here are some examples:

    Integer i = MathUtilities.<Integer>max( 42,  42 );
    String s = fooObject.<String>foo( "foo" );
    String s = this.<String>foo( "foo" );

The prefix must be a class or object instance containing the method. One situation where you’d need to use explicit type invocation is if you are calling a generic method that infers its type from the assignment context, but you are not assigning the value to a variable directly. For example, if you wanted to pass the result of our makeTrap() method as a parameter to another method, it would otherwise default to Object.

Wildcard Capture

Generic methods can do one more trick for us involving taming wildcard instantiations of generic types. The term wildcard capture refers to the fact that generic methods can work with arguments whose type is a wildcard instantiation of a type, just as if the type were known:

    <T> Set<T> listToSet( List<T> list ) {
        Set<T> set = new HashSet<T>();
        set.addAll( list );
        return set;

    // usage
    List<?> list = new ArrayList<Date>();
    Set<?> set = listToSet( list );

The result of these examples is that we converted an unknown instantiation of List to an unknown instantiation of Set. The type variable T represents the actual type of the argument, list, for purposes of the method body. The wildcard instantiation must match any bounds of the method parameter type. But because we can work with the type variable only through its bounds types, the compiler is free to refer to it by this new name, T, as if it were a known type. That may not seem very interesting, but it is useful because it allows methods that accept wildcard instantiations of types to delegate their work to other generic methods.

Another way to look at this is that generic methods are a more powerful alternative to methods using wildcard instantiations of types. We’ll do a little comparison next.

Wildcard Types Versus Generic Methods

You’ll recall that trying to work with an object through a wildcard instantiation of its generic type limits us to “reading” the object. We cannot “write” types to the object because its parameter type is unknown. In contrast, because generic methods can infer or “capture” an actual type for their arguments, they allow us to do a lot more with broad ranges of types than we could with wildcard instantiations alone.

For example, suppose we wanted to write a utility method that swaps the first two elements of a list. Using wildcards, we’d like to write something like this:

    // Bad implementation
    List<?> swap( List<?> list ) {
        Object tmp = list.get(0);
        list.set( 0, list.get(1) ); // error, can't write
        list.set( 1, tmp ); // error, can't write
        return list;

But we are not allowed to call the set() method of our list because we don’t know what type it actually holds. We are really stuck and there isn’t much we can do. But the corresponding generic method gives us a real type to hang our hat:

    <T> List<T> swapGeneric( List<T> list ) {
        T tmp = list.get( 0 );
        list.set( 0, list.get(1) );
        list.set( 1, tmp );
        return list;

Here, we are able to declare a variable of the correct (inferred) type and write using the set() methods appropriately. It would seem that generic methods are the only way to go here. But there is a third path. Wildcard capture, as described in the previous section, allows us to delegate our wildcard version of the method to our actual generic method and use it as if the type were inferred, even though it’s open-ended:

    List<?> swap( List<?> list ) {
        return swapGeneric( list ); // delegate to generic form

Here, we delegated to the generic version.

The best content for your career. Discover unlimited learning on demand for around $1/day.