Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

JavaWorld Daily Brew

Java Q&A

Java Q&A is my platform for answering all kinds of technical questions related to Java.


Customizing Swing's File Chooser

 

The javax.swing.JFileChooser class describes a Swing component for choosing files, usually via its int showOpenDialog(Component parent) and int showSaveDialog(Component parent) methods. In this post, I enumerate various ways to customize a file chooser.

Creating and Showing File Choosers

Q: How do I create and show a file chooser?

A: Before you can customize a file chooser, you need to know how to create one and then show it. Create a file chooser by instantiating JFileChooser via one of its constructors, such as JFileChooser(), which initializes the file chooser to the user's default directory.

After creating a file chooser, show it by invoking one of JFileChooser's show-prefixed methods, such as the aforementioned showOpenDialog() and showSaveDialog(). Listing 1 presents a small application that demonstrates these tasks.

import java.awt.EventQueue;
import java.awt.GridLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class FCDemo extends JFrame
{
   JFileChooser fc = new JFileChooser();

   public FCDemo(String title)
   {
      super(title);
      setDefaultCloseOperation(EXIT_ON_CLOSE);

      JPanel pnl = new JPanel();
      pnl.setLayout(new GridLayout(2, 1));

      JButton btn = new JButton("JFileChooser.showOpenDialog() Demo");
      ActionListener al;
      al = new ActionListener()
           {
              @Override
              public void actionPerformed(ActionEvent ae)
              {
                 switch (fc.showOpenDialog(FCDemo.this))
                 {
                    case JFileChooser.APPROVE_OPTION:
                       JOptionPane.showMessageDialog(FCDemo.this, "Selected: "+
                                                     fc.getSelectedFile(),
                                                     "FCDemo",
                                                     JOptionPane.OK_OPTION);
                       break;

                    case JFileChooser.CANCEL_OPTION:
                       JOptionPane.showMessageDialog(FCDemo.this, "Cancelled",
                                                     "FCDemo",
                                                     JOptionPane.OK_OPTION);
                       break;
                 
                    case JFileChooser.ERROR_OPTION:
                       JOptionPane.showMessageDialog(FCDemo.this, "Error",
                                                     "FCDemo",
                                                     JOptionPane.OK_OPTION);
                 }
              }
           };
      btn.addActionListener(al);
      pnl.add(btn);

      btn = new JButton("JFileChooser.showSaveDialog() Demo");
      al = new ActionListener()
           {
              @Override
              public void actionPerformed(ActionEvent ae)
              {
                 switch (fc.showSaveDialog(FCDemo.this))
                 {
                    case JFileChooser.APPROVE_OPTION:
                       JOptionPane.showMessageDialog(FCDemo.this, "Selected: "+
                                                     fc.getSelectedFile(),
                                                     "FCDemo",
                                                     JOptionPane.OK_OPTION);
                       break;

                    case JFileChooser.CANCEL_OPTION:
                       JOptionPane.showMessageDialog(FCDemo.this, "Cancelled",
                                                     "FCDemo",
                                                     JOptionPane.OK_OPTION);
                       break;
                 
                    case JFileChooser.ERROR_OPTION:
                       JOptionPane.showMessageDialog(FCDemo.this, "Error",
                                                     "FCDemo",
                                                     JOptionPane.OK_OPTION);
                 }
              }
           };
      btn.addActionListener(al);
      pnl.add(btn);

      setContentPane(pnl);

      pack();
      setVisible(true);
   }

   public static void main(String[] args)
   {
      Runnable r = new Runnable()
                   {
                      @Override
                      public void run()
                      {
                         new FCDemo("FileChooser Demo");
                      }
                   };
      EventQueue.invokeLater(r);
   }
}

Listing 1: Creating and showing open and save file choosers

Listing 1 reveals a simple pattern for working with open and save file choosers: instantiate JFileChooser, invoke showOpenDialog() or showSaveDialog() to display an appropriate modal dialog box for the chooser, and test the return value against one of these constants:

  • JFileChooser.CANCEL_OPTION: the user clicked the Cancel button or closed the dialog box
  • JFileChooser.APPROVE_OPTION: the user clicked the approve (e.g., Open or Save) button
  • JFileChooser.ERROR_OPTION: an internal error occurred

Compile Listing 1 (javac FCDemo.java) and run the application (java FCDemo). Figure 1 shows the resulting user interface, which presents buttons for creating/showing open and save file choosers.

Click either button to reveal the appropriate file chooser.
Figure 1: Click either button to reveal the appropriate file chooser.

For example, click the JFileChooser.showSaveDialog() Demo button to display the save file chooser. Figure 2 reveals the resulting dialog box.

You can also cancel the file chooser by clicking the X button on the titlebar.
Figure 2: You can also cancel the file chooser by clicking the X button on the titlebar.

Showing Directories Only

Q: Is it possible to have a file chooser show directories only?

A: Yes, you can configure a file chooser to show directories only. Alternatively, you can configure it to show files only. The default setting is to show directories and files.

JFileChooser declares a void setFileSelectionMode(int mode) method that lets you tell a file chooser to show directories, files, or both. Pass one of JFileChooser's DIRECTORIES_ONLY, FILES_ONLY, or FILES_AND_DIRECTORIES constants to mode.

For example, you could configure Listing 1's file chooser to show directories only, by placing the following line in the constructor before creating the user interface:

fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

Additional selection methods
JFileChooser offers an int getFileSelectionMode() method that returns the current selection mode. It also offers boolean isFileSelectionEnabled() to determine if the current selection mode allows files to be selected, boolean isDirectorySelectionEnabled() to determine if the current selection mode allows directories to be selected, void setMultiSelectionEnabled(boolean b) to allow multiple selections, and boolean isMultiSelectionEnabled() to determine if multiple selections are allowed -- JFileChooser defaults to single selections.

Changing Open/Save File Chooser Approve Button Text

Q: Can I change the approve button text for an open or save file chooser?

A: You can specify approve button text for an open or save file chooser, but the text doesn't always appear when the chooser is displayed. Consider the following code fragment for an open file chooser -- the code fragment for a save file chooser is similar:

fc.setApproveButtonText("OPEN...");
switch (fc.showOpenDialog(FCDemo.this))

This code fragment employs JFileChooser's void setApproveButtonText(String approveButtonText) method to set the approve button's text to OPEN....

If you merge fc.setApproveButtonText("OPEN..."); into Listing 1, compile the source code, and run the application; and if you click the button to display the open file chooser, you should observe Figure 3.

The approve button's text has been changed to OPEN....
Figure 3: The approve button's text has been changed to OPEN....

However, if you tried to do the analogous thing with the save file chooser, you would still observe Figure 2's dialog box the first time you displayed the save file chooser.

You might think that JFileChooser contains a bug. However, an investigation of the source code proves otherwise. Consider the following code fragment, which reveals the contents of the showOpenDialog() and showSaveDialog() methods:

public int showOpenDialog(Component parent) throws HeadlessException 
{
   setDialogType(OPEN_DIALOG);
   return showDialog(parent, null);
}

public int showSaveDialog(Component parent) throws HeadlessException 
{
   setDialogType(SAVE_DIALOG);
   return showDialog(parent, null);
}

Each method first invokes void setDialogType(int dialogType) to specify the kind of dialog box to display before invoking int showDialog(Component parent, String approveButtonText), which does the actual work of creating and displaying the dialog box.

The following code fragment reveals the setDialogType() method:

public void setDialogType(int dialogType) 
{
   if (this.dialogType == dialogType) 
   {
      return;
   }
   if (!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || 
       dialogType == CUSTOM_DIALOG)) 
   {
      throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType);
   }
   int oldValue = this.dialogType;
   this.dialogType = dialogType;
   if (dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) 
   {
      setApproveButtonText(null);
   }
   firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType);
}

There are two things to note about this method. Taken together, they explain why you cannot always change the open or save file chooser's approve button text:

  • When dialogType equals OPEN_DIALOG or SAVE_DIALOG, setApproveButtonText(null); is executed to cancel any previously specified approve button text, which results in the default text being shown.
  • This method first tests dialogType to see if it equals the current dialog type, returning (and not executing setApproveButtonText(null); to erase previously specified text for the approve button, ensuring that only the default text is shown) when this is the case.

    The value passed to dialogType equals this.dialogType when you call showOpenDialog() at startup. This is due to passing OPEN_DIALOG to the dialogType parameter when showOpenDialog() invokes setDialogType(), and due to the dialogType field being initialized to OPEN_DIALOG (private int dialogType = OPEN_DIALOG;). This expression is also true on successive calls to showOpenDialog() or showSaveDialog() after switching from the open dialog box to the save dialog box (and vice versa).

The previous discussion provides a solution for changing the approve button text and making sure this text appears each time either the open or save file chooser is displayed. This solution is demonstrated below for the open file chooser:

fc.setDialogType(JFileChooser.OPEN_DIALOG);
switch (fc.showDialog(FCDemo.this, "OPEN..."))

First invoke setDialogType() to ensure that any registered property change listeners are notified. Then invoke showDialog(), passing the approve button text as the second argument to this method.

You'll notice that OPEN... or SAVE... appears on the dialog box's titlebar as well as on the approve button. If you want different text on the titlebar, invoke JFileChooser's void setDialogTitle(String dialogTitle) method, as demonstrated below:

fc.setDialogType(JFileChooser.SAVE_DIALOG);
fc.setDialogTitle("Save");
switch (fc.showDialog(FCDemo.this, "SAVE..."))

Installing File Filters

Q: I want the user to select text files only (i.e., files with a .txt extension). How do I accomplish this task?

A: JFileChooser offers a void setFileFilter(FileFilter filter) method that lets you set the file filter used by the file chooser to filter out files from the user's view. The companion FileFilter getFileFilter() method returns the current file filter.

The abstract javax.swing.filechooser.FileFilter class declares a boolean accept(File f) method that returns true to accept the file described by f or false to reject it. The companion String getDescription() method returns a description of the file filter.

The following code fragment shows you how to create a file filter to accept text files only, and register this filter with the file chooser:

fc.setFileFilter(new FileFilter()
                 {
                    @Override
                    public boolean accept(File file)
                    {
                       return file.getName().toUpperCase().equals(".TXT");
                    }

                    @Override
                    public String getDescription()
                    {
                       return ".txt files";
                    }
                 });

You can easily integrate this feature into Listing 1's FCDemo.java source code. Simply place it in the constructor before creating the user interface.

If you run the aforementioned application, you'll notice that you can also select all files. If you don't want to give the user this choice, you can remove it by passing false to JFileChooser's void setAcceptAllFileFilterUsed(boolean b) method, as follows:

fc.setAcceptAllFileFilterUsed(false); // remove the accept-all (.*) file filter

After compiling the refactored source code and running the resulting application, either file chooser should let you select .txt files only. Figure 4 shows you what this looks like in the context of the open file chooser.

The user can select .txt files only.
Figure 4: The user can select .txt files only.

You'll probably find it difficult to navigate the directory structure because you won't be able to see any directories. You can overcome this problem by changing accept()'s expression to the following:

return file.getName().toUpperCase().equals(".TXT")||file.isDirectory();

A more capable file filter
The javax.swing.filechooser.FileNameExtensionFilter class extends FileFilter to let you specify an array of file extensions to test against. For example, FileFilter filter = new FileNameExtensionFilter("JPEG file", "jpg", "jpeg"); lets you test against .jpg and .jpeg extensions.

Installing Choosable File Filters

Q: How do I install multiple file filters?

A: The setFileFilter() method lets you install a single file filter. If you want to support multiple file extensions, you could do so by extending the single FileFilter's methods, as follows:

fc.setFileFilter(new FileFilter()
                 {
                    @Override
                    public boolean accept(File file)
                    {
                       return file.getName().toUpperCase().equals(".TXT")||
                              file.getName().toUpperCase().equals(".DOC");
                    }

                    @Override
                    public String getDescription()
                    {
                       return ".txt files or .doc files";
                    }
                 });

Although this technique works, it's awkward, especially when the number of supported extensions increases. Instead, the user should be able to select a specific extension from the Files of Type drop-down list of extensions.

JFileChooser provides void addChoosableFileFilter(FileFilter filter) for appending a file filter to this drop-down list. The following code fragment demonstrates:

fc.addChoosableFileFilter(new FileFilter()
                                {
                                   @Override
                                   public boolean accept(File file)
                                   {
                                      return file.getName().toUpperCase().
                                             equals(".DOC");
                                   }

                                   @Override
                                   public String getDescription()
                                   {
                                      return ".doc files";
                                   }
                                });

This code fragment appends a file filter for viewing .doc files to the list of choosable file filters. This list will include any file filter installed via setFileFilter() and the accept-all (.*) file filter unless uninstalled (e.g., fc.setAcceptAllFileFilterUsed(false);).

Additional choosable file filter methods
JFileChooser's boolean removeChoosableFileFilter(FileFilter f) method removes filter f; FileFilter[] getChoosableFileFilters() returns an array of appended filters; and void resetChoosableFileFilters() resets the choosable file filter list to its starting state.

Customizing File Views

Q: I'd like to display a small icon beside each filename in the file chooser window. Is this possible?

A: Yes, you can display a small icon beside each of the filenames in a file chooser window. To accomplish this task, you first need to extend the javax.swing.filechooser.FileView class.

FileView is an abstract class that provides user interface information for a java.io.File object. This class provides an Icon getIcon(File f) method that you can override to return a suitable javax.swing.Icon for the specified File object.

After instantiating your FileView subclass, pass it to JFileChooser's void setFileView(FileView fileView) method to register this file view with the file chooser. The companion FileView getFileView() method returns the current file view.

Listing 2 presents the contents of a file view that provides icons for BMP, GIF, JPEG, and PNG files.

import java.io.File;

import javax.swing.Icon;
import javax.swing.ImageIcon;

import javax.swing.filechooser.FileView;

public class ImageFileView extends FileView
{
   private Icon bmpicon, gificon, jpgicon, pngicon;

   // Create ImageFileView to serve as a viewer for file icons.

   ImageFileView()
   {
      // Preload icons for the file view. The getClass().getResource()
      // construct is used so that an application can be packaged into a JAR 
      // file and still obtain these images.

      bmpicon = new ImageIcon(getClass().getResource("images/bmpicon.gif")); 
      gificon = new ImageIcon(getClass().getResource("images/gificon.gif"));
      jpgicon = new ImageIcon(getClass().getResource("images/jpgicon.gif"));
      pngicon = new ImageIcon(getClass().getResource("images/pngicon.gif"));
   }

   // Return a description of the file's type. The look and feel determines
   // what to do with this description (including a null description).

   @Override
   public String getTypeDescription(File f)
   {
      String s = f.getName();
      int i = s.lastIndexOf('.');
      if (i > 0 && i < s.length()-1)
      {
         String ext = s.substring(i+1).toLowerCase();
         if (ext.equals("bmp"))
            return "BMP Image";
         else
         if (ext.equals("gif"))
            return "GIF Image";
         else
         if (ext.equals("jpeg") || ext.equals("jpg"))
            return "JPEG Image";
         else
         if (ext.equals("png"))
            return "PNG Image";
      }
      return null;
   }

   // Return the icon that associates with the file's type. If null returns, a
   // default icon is used.

   @Override
   public Icon getIcon(File f)
   {
      String s = f.getName();
      int i = s.lastIndexOf('.');

      if (i > 0 && i < s.length()-1)
      {
         String ext = s.substring(i+1).toLowerCase();
         if (ext.equals("bmp"))
            return bmpicon;
         else
         if (ext.equals("gif"))
            return gificon;
         else
         if (ext.equals("jpeg") || ext.equals("jpg"))
            return jpgicon;
         else
         if (ext.equals("png"))
            return pngicon;
      }
      return null;
   }

   // Return the file's name minus its extension for files with the bmp, gif,
   // jpeg, jpg, or png extensions.
   
   @Override
   public String getName(File f)
   {         
      String s = f.getName();
      int i = s.lastIndexOf('.');

      if (i > 0 && i < s.length()-1)
      {
         String ext = s.substring(i+1).toLowerCase();
         if (ext.equals("bmp") || ext.equals("gif") ||
            ext.equals("jpeg") || ext.equals("jpg") || ext.equals("png"))
            return s.substring(0, i);
      }
      return null;
   }

   // Return an individual file's description.

   @Override
   public String getDescription(File f)
   {
      // Let the look and feel figure out the description.

      return null;
   }

   // Determine if a directory is traversable.

   @Override
   public Boolean isTraversable(File f)
   {
      // Let the look and feel determine if the directory is traversable.

      return null;
   }
}

Listing 2: Describing an image file view

You can easily integrate this feature into Listing 1's FCDemo.java source code. Simply place the following line in the constructor before creating the user interface:

fc.setFileView(new ImageFileView());

After compiling the refactored source code and running the resulting application, you should see image icons for BMP, GIF, JPEG, and PNG files in both the open and save file choosers. Figure 5 gives you an idea of what you might see.

The highlighted file entry shows the dimensions of its JPG icon.
Figure 5: The highlighted file entry shows the dimensions of its JPG icon.

Providing an Image Viewer Accessory

Q: Does JFileChooser provide a feature for previewing the content of image or other files?

A: Yes, JFileChooser supports the concept of an accessory, which is a javax.swing.JComponent instance that can be integrated into the file chooser's user interface to present file previews or another feature.

Extend JComponent to describe the new component, instantiate the resulting component class, and pass it to JFileChooser's void setAccessory(JComponent newAccessory) method to register the component with the file chooser.

Dynamically changing accessories
To dynamically change accessories to reflect the current application context, invoke JFileChooser's JComponent getAccessory() method to obtain the current accessory and then invoke setAccessory() to install the new accessory. You can restore the previous accessory by reinvoking setAccessory() with its instance.

Listing 3 presents the contents of an image preview accessory.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.io.File;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFileChooser;

public class ImagePreview extends JComponent implements PropertyChangeListener
{
   // Dimensions of image preview's preferred size.

   final static int WIDTH = 150;
   final static int HEIGHT = 100;

   // Reference to ImageIcon whose image is displayed in accessory area. If
   // null reference, nothing is displayed in accessory area.

   private ImageIcon icon;

   // Create ImagePreview component to serve as a file chooser accessory.

   public ImagePreview(JFileChooser fc)
   {
      // Register a property change listener with the file chooser so that
      // the ImagePreview component is made aware of file chooser events (such
      // as a user selecting a file).

      fc.addPropertyChangeListener(this);

      // Set the ImagePreview's dimensions to accommodate image thumbnails.
      // The specified values determine the overall size of the file chooser.

      setPreferredSize(new Dimension(WIDTH, HEIGHT));
   }

   // Paint the ImagePreview component in response to a repaint() method call.

   @Override
   protected void paintComponent(Graphics g)
   {
      // When this method is called, the background has already been painted.
      // If icon is null, do nothing. This action causes the current image
      // thumbnail to disappear when the user selects a directory, for example.

      if (icon != null)
      {
         // Paint a white background behind the pixels so that a GIF image's
         // transparent pixel causes white (instead of gray or whatever color
         // is appropriate for this look and feel) to show through.

         Graphics2D g2d = (Graphics2D) g;
         Rectangle bounds = new Rectangle(0, 0, icon.getIconWidth(),
                                          icon.getIconHeight());
         g.setColor(Color.white);
         g2d.fill(bounds);

         // Paint the image -- (0, 0) is the image's upper-left corner, and
         // the upper-left corner of the accessory area.

         icon.paintIcon(this, g, 0, 0);
      }
   }

   // Respond to property change events sent to this ImagePreview component by
   // the file chooser.

   @Override
   public void propertyChange(PropertyChangeEvent e)
   {                
      // Extract property name from event object.

      String propName = e.getPropertyName();

      // Erase any displayed image if user moves up the directory hierarchy.
                      
      if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(propName))
      {
         icon = null;
         repaint();
         return;
      }                  

      // Display selected file. If a directory is selected, erase any
      // displayed image.

      if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(propName))
      {
         // Extract selected file's File object.

         File file = (File) e.getNewValue();

         // If file is null, a directory was selected -- the user is moving
         // between directories. In response, any displayed image in the
         // accessory area must be erased.

         if (file == null)
         {
            icon = null;
            repaint();
            return;
         }

         // Obtain the selected file's icon.

         icon = new ImageIcon(file.getPath());

         // The ImageIcon constructor invokes a Toolkit getImage() method to
         // obtain the image identified by file.getPath(). The image is read
         // from the file unless the image (together with file path/name
         // information) has been cached (for performance reasons). Suppose
         // the user has specified the name of a file and that file does not
         // exist. Toolkit's getImage() method will return an Image with the
         // width and height each set to -1. The "image" associated with this
         // Image will be cached. Suppose the user activates the open file
         // chooser and selects the file to which the image was saved. The
         // previous ImageIcon() constructor will execute, but the image
         // will not be read from the file -- it will be read from the cache
         // (with -1 as the width and as the height). No image will appear in 
         // the preview window; the user will be confused. The solution to
         // this problem is to test the Image's width for -1. If this value
         // is present, Image's flush() method is called on the Image, and a
         // new ImageIcon is created. Internally, Toolkit's getImage() method
         // will read the image from the file -- not from the cache.

         if (icon.getIconWidth() == -1)
         {
            icon.getImage().flush();
            icon = new ImageIcon(file.getPath());
         }

         // Scale icon to fit accessory area if icon too big.

         if (icon.getIconWidth() > WIDTH)
            icon = new ImageIcon(icon.getImage().getScaledInstance (WIDTH, -1,
                                                          Image.SCALE_DEFAULT));

         // Display image.

         repaint();
      }
   }
}

Listing 3: Describing an image preview accessory

Listing 3 is fairly self-explanatory. This image preview component will display a small thumbnail of the currently selected image file (JPEG, GIF, PNG, and a few other formats), or will display nothing when the file isn't an image file.

An interesting aspect of this component is that it registers itself as a property change listener with the file chooser so that it's made aware of file chooser events, especially the "directory changed" and "selected file changed" events.

You can easily integrate this feature into Listing 1's FCDemo.java source code. Simply place the following line in the constructor before creating the user interface:

fc.setAccessory(new ImagePreview(fc));

After compiling the refactored source code and running the resulting application, you should see image previews for both the open and save file choosers. Figure 6 gives you an idea of what you might see.

Select an image file to see its preview.
Figure 6: Select an image file to see its preview.

Displaying Information from a Directory Service or from Another Data Source

Q: Can I customize JFileChooser to display information from a directory service or from another data source?

A: You can customize JFileChooser to display information from a directory service or from another data source, such as a database management system. JFileChooser's javax.swing.filechooser.FileSystemView class is the key to making this happen.

JFileChooser doesn't interact directly with a filesystem. Instead, it interacts indirectly via a FileSystemView object, which interacts with the filesystem via File objects.

FileSystemView declares a FileSystemView getFileSystemView() class method, which provides a view of the local filesystem. JFileChooser invokes this method unless you provide an alternate FileSystemView.

You can provide an alternate FileSystemView by extending this class, instantiating the subclass, and passing the instance to a JFileChooser constructor that takes a FileSystemView instance, such as JFileChooser(FileSystemView fsv).

setFileSystemView() and getFileSystemView()
You can also set the FileSystemView instance by invoking JFileChooser's void setFileSystemView(FileSystemView fsv) method, and return the current FileSystemView instance by invoking JFileChooser's FileSystemView getFileSystemView() method.

Check out Justin Hill's Customizing JFileChooser article for an example that extends JFileChooser to display information from a generic directory service.

Code

You can download this post's code here. Code was developed and tested with JDK 7u6 on a Windows 7 platform.

How much do you know about the Java language and platform? I've developed a 150-question quiz to help you assess your Java knowledge level. Below is an example question:

Which one of the following is not a Javadoc tag?

(a) @author
(b) {@link}
(c) @serialField
(d) @arg

This quiz is organized into interleaved true/false and multiple choice categories, and focuses on Java Platform, Standard Edition (SE) 1 through Java SE 7.

The quiz is available for Amazon Kindle devices only. Check out Amazon's The BIG Java Quiz to obtain a copy.