Home > Articles > Programming > Java

This chapter is from the book

Catching Exceptions

You now know how to throw an exception. It is pretty easy. You throw it and you forget it. Of course, some code has to catch the exception. Catching exceptions requires more planning.

If an exception occurs that is not caught anywhere, the program will terminate and print a message to the console, giving the type of the exception and a stack trace. Graphics programs (both applets and applications) catch exceptions, print stack trace messages, and then go back to the user interface processing loop. (When you are debugging a graphically based program, it is a good idea to keep the console available on the screen and not minimized.)

To catch an exception, you set up a try/catch block. The simplest form of the try block is as follows:


try
{
   code
   more code
   more code
}
catch (ExceptionType e)
{
   handler for this type
}

If any of the code inside the try block throws an exception of the class specified in the catch clause, then

  1. The program skips the remainder of the code in the try block;

  2. The program executes the handler code inside the catch clause.

If none of the code inside the try block throws an exception, then the program skips the catch clause.

If any of the code in a method throws an exception of a type other than the one named in the catch clause, this method exits immediately. (Hopefully, one of its callers has already coded a catch clause for that type.)

To show this at work, we show some fairly typical code for reading in text:


public void read(String filename)
{
   try
   {
      InputStream in = new FileInputStream(filename);
      int b;
      while ((b = in.read()) !=-1)
      {
         process input
      }
   }
   catch (IOException exception)
   {
      exception.printStackTrace();
   }
}

Notice that most of the code in the try clause is straightforward: it reads and processes lines until we encounter the end of the file. As you can see by looking at the Java API, there is the possibility that the read method will throw an IOException. In that case, we skip out of the entire while loop, enter the catch clause and generate a stack trace. For a toy program, that seems like a reasonable way to deal with this exception. What other choice do you have?

Often, the best choice is to do nothing at all and simply pass the exception on to the caller. If an error occurs in the read method, let the caller of the read method worry about it! If we take that approach, then we have to advertise the fact that the method may throw an IOException.


public void read(String filename) throws IOException
{
   InputStream in = new FileInputStream(filename);
   int b;
   while ((b = in.read()) !=-1)
   {
      process input
   }
}

Remember, the compiler strictly enforces the throws specifiers. If you call a method that throws a checked exception, you must either handle it or pass it on.

Which of the two is better? As a general rule, you should catch those exceptions that you know how to handle and propagate those that you do not know how to handle. When you propagate an exception, you must add a throws specifier to alert the caller that an exception may be thrown.

Look at the Java API documentation to see what methods throw which exceptions. Then decide whether you should handle them or add them to the throws list. There is nothing embarrassing about the latter choice. It is better to direct an exception to a competent handler than to squelch it.

Please keep in mind that there is one exception to this rule, as we mentioned earlier. If you are writing a method that overrides a superclass method that throws no exceptions (such as paintComponent in JComponent), then you must catch each checked exception in the method's code. You are not allowed to add more throws specifiers to a subclass method than are present in the superclass method.

Catching exceptions is almost the same in Java and in C++. Strictly speaking, the analog of

catch (Exception e) // Java

is

catch (Exception& e) // C++

There is no analog to the C++ catch (...). This is not needed in Java because all exceptions derive from a common superclass.

Catching Multiple Exceptions

You can catch multiple exception types in a try block and handle each type differently. You use a separate catch clause for each type as in the following example:


try
{
   code that might throw exceptions
}
catch (MalformedURLException e1)
{
   emergency action for malformed URLs
}
catch (UnknownHostException e2)
{
   emergency action for unknown hosts
}
catch (IOException e3)
{
   emergency action for all other I/O problems
}

The exception object (e1, e2, e3) may contain information about the nature of the exception. To find out more about the object, try

e3.getMessage()

to get the detailed error message (if there is one), or

e3.getClass().getName()

to get the actual type of the exception object.

Rethrowing and Chaining Exceptions

You can throw an exception in a catch clause. Typically, you do this because you want to change the exception type. If you build a subsystem that other programmers use, it makes a lot of sense to use an exception type that indicates a failure of the subsystem. An example of such an exception type is the ServletException. The code that executes a servlet may not want to know in minute detail what went wrong, but it definitely wants to know that the servlet was at fault.

Here is how you can catch an exception and rethrow it.


try
{
   access the database
}
catch (SQLException e)
{
   throw new ServletException("database error: " + e.getMessage());
}

Here, the ServletException is constructed with the message text of the exception. As of JDK 1.4, you can do better than that and set the original exception as the "cause" of the new exception:


try
{
   access the database
}
catch (SQLException e)
{
   Throwable se = new ServletException("database error");
   se.setCause(e);
   throw se;
}

When the exception is caught, the original exception can be retrieved:

Throwable e = se.getCause();

This wrapping technique is highly recommended. It allows you to throw high-level exceptions in subsystems without losing the details of the original failure.

The wrapping technique is also useful if a checked exception occurs in a method that is not allowed to throw a checked exception. You can catch the checked exception and wrap it into a runtime exception.

A number of exception classes, such as ClassNotFoundException, InvocationTargetException, and RuntimeException, have had their own chaining schemes. As of JDK 1.4, these have been brought into conformance with the "cause" mechanism. You can still retrieve the chained exception in the historical way or just call getCause. Unfortunately, the chained exception most commonly used by application programmers, SQLException, has not been retrofitted.

The finally Clause

When your code throws an exception, it stops processing the remaining code in your method and exits the method. This is a problem if the method has acquired some local resource that only it knows about and if that resource must be cleaned up. One solution is to catch and rethrow all exceptions. But this solution is tedious because you need to clean up the resource allocation in two places, in the normal code and in the exception code.

Java has a better solution, the finally clause. Here we show you how to properly dispose of a Graphics object. If you do any database programming in Java, you will need to use the same techniques to close connections to the database. As you will see in Chapter 4 of Volume 2, it is very important to close all database connections properly, even when exceptions occur.

The code in the finally clause executes whether or not an exception was caught. In the following example, the program will dispose of the graphics context under all circumstances.


Graphics g = image.getGraphics();
try
{
   // 1
   code that might throw exceptions
   // 2
}
catch (IOException e)
{
   // 3
   show error dialog
   // 4
}
finally
{
   // 5
   g.dispose();
}
// 6

Let us look at the three possible situations in which the program will execute the finally clause.

  1. The code throws no exceptions. In this event, the program first executes all the code in the try block. Then, it executes the code in the finally clause. Afterwards, execution continues with the first statement after the try block. In other words, execution passes through points 1, 2, 5, and 6.

  2. The code throws an exception that is caught in a catch clause, in our case, an IOException. For this, the program executes all code in the try block, up to the point at which the exception was thrown. The remaining code in the try block is skipped. The program then executes the code in the matching catch clause, then the code in the finally clause.

    If the catch clause does not throw an exception, then the program executes the first line after the try block. In this scenario, execution passes through points 1, 3, 4, 5, and 6.

    If the catch clause throws an exception, then the exception is thrown back to the caller of this method, and execution passes through points 1, 3, and 5 only.

  3. The code throws an exception that is not caught in any catch clause. For this, the program executes all code in the try block until the exception is thrown. The remaining code in the try block is skipped. Then, the code in the finally clause is executed, and the exception is thrown back to the caller of this method. Execution passes through points 1 and 5 only.

You can use the finally clause without a catch clause. For example, consider the following try statement:


Graphics g = image.getGraphics();
try
{
   code that might throw exceptions
}
finally
{
   g.dispose();
}

The g.dispose() command in the finally clause is executed whether or not an exception is encountered in the try block. Of course, if an exception is encountered, it is rethrown and must be caught in another catch clause.

In fact, as explained in the following tip, we think it is a very good idea to use the finally clause in this way.

We strongly suggest that you decouple try/catch and try/finally blocks. This makes your code far less confusing. For example,


InputStream in = ...;
try
{
   try
   {
      code that might throw exceptions
   }
   finally
   {
      in.close();
   }
}
catch (IOException e)
{
   show error dialog
}

The inner try block has a single responsibility: to make sure that the input stream is closed. The outer try block has a single responsibility: to ensure that errors are reported. Not only is this solution clearer, it is also more functional: errors in the finally clause are reported.

A finally clause can yield unexpected results when it contains return statements. Suppose you exit the middle of a try block with a return statement. Before the method returns, the contents of the finally block are executed. If the finally block also contains a return statement, then it masks the original return value. Consider this contrived example:

public static int f(int n)
{
   try
   {
      int r = n * n;
      return r;
   }
   finally
   {
      if (n == 2) return 0;
   }
}

If you call f(2), then the try block computes r = 4 and executes the return statement. However, the finally clause is executed before the method actually returns. The finally clause causes the method to return 0, ignoring the original return value of 4.

Sometimes the finally clause gives you grief, namely if the cleanup method can also throw an exception. A typical case is closing a stream. (See Chapter 12 for more information on streams.) Suppose you want to make sure that you close a stream when an exception hits in the stream processing code.


InputStream in = ...;
try
{
   code that might throw exceptions
}
catch (IOException e)
{
   show error dialog
}
finally
{
   in.close();
}

Now suppose that the code in the try block throws some exception other than an IOException that is of interest to the caller of the code. The finally block executes, and the close method is called. That method can itself throw an IOException! When it does, then the original exception is lost and the IOException is thrown instead. That is very much against the spirit of exception handling.

It is always a good idea—unfortunately not one that the designers of the InputStream class chose to follow—to throw no exceptions in cleanup operations such as dispose, close, and so on, that you expect users to call in finally blocks.

There is one fundamental difference between C++ and Java with regard to exception handling. Java has no destructors; thus, there is no stack unwinding as in C++. This means that the Java programmer must manually place code to reclaim resources in finally blocks. Of course, because Java does garbage collection, there are far fewer resources that require manual deallocation.

Analyzing Stack Trace Elements

A stack trace is a listing of all pending method calls at a particular point in the execution of a program. You have almost certainly seen stack trace listings—they are displayed whenever a Java program terminates with an uncaught exception.

The stack trace only traces back to the statement that throws the exception, not necessarily to the root cause of the error.

Before JDK 1.4, you could access the text description of a stack trace by calling the printStackTrace method of the Throwable class. Now you can call the getStackTrace method to get an array of StackTraceElement objects that you can analyze in your program. For example,


Throwable t = new Throwable();
StackTraceElement[] frames = t.getStackTrace();
for (StackTraceElement frame : frames)
   analyze frame

The StackTraceElement class has methods to obtain the file name and line number, as well as the class and method name, of the executing line of code. The toString method yields a formatted string containing all of this information.

JDK 5.0 adds the static Thread.getAllStackTraces method that yields the stack traces of all threads. Here is how you use that method:


Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
for (Thread t : map.keySet())
{
   StackTraceElement[] frames = map.get(t);
   analyze frames
}

See Volume 2 for more information on threads and the Map interface.

Example 11-1 prints the stack trace of a recursive factorial function. For example, if you compute factorial(3), the printout is

factorial(3):
StackTraceTest.factorial(StackTraceTest.java:8)
StackTraceTest.main(StackTraceTest.java:23)
factorial(2):
StackTraceTest.factorial(StackTraceTest.java:8)
StackTraceTest.factorial(StackTraceTest.java:14)
StackTraceTest.main(StackTraceTest.java:23)
factorial(1):
StackTraceTest.factorial(StackTraceTest.java:8)
StackTraceTest.factorial(StackTraceTest.java:14)
StackTraceTest.factorial(StackTraceTest.java:14)
StackTraceTest.main(StackTraceTest.java:23)
return 1
return 2
return 6

Example 11-1. StackTraceTest.java

 1. import java.util.*;
 2.
 3. /**
 4.    A program that displays a trace feature of a recursive
 5.    method call.
   6. */
   7. public class StackTraceTest
   8. {
   9.    /**
   10.       Computes the factorial of a number
   11.       @param n a nonnegative integer
   12.       @return n! = 1 * 2 * . . . * n
   13.    */
   14.    public static int factorial(int n)
   15.    {
   16.       System.out.println("factorial(" + n + "):");
   17.       Throwable t = new Throwable();
   18.       StackTraceElement[] frames = t.getStackTrace();
   19.       for (StackTraceElement f : frames)
   20.          System.out.println(f);
   21.       int r;
   22.       if (n <= 1) r = 1;
   23.       else r = n * factorial(n - 1);
   24.       System.out.println("return " + r);
   25.       return r;
   26.    }
   27.
   28.    public static void main(String[] args)
   29.    {
   30.       Scanner in = new Scanner(System.in);
   31.       System.out.print("Enter n: ");
   32.       int n = in.nextInt();
   33.       factorial(n);
   34.    }
   35. }
   
api_icon.gif
   java.lang.Throwable 1.0
   
  • Throwable(Throwable cause) 1.4

  • Throwable(String message, Throwable cause) 1.4

    construct a Throwable with a given cause.

  • Throwable initCause(Throwable cause) 1.4

    sets the cause for this object or throws an exception if this object already has a cause. Returns this.

  • Throwable getCause() 1.4

    gets the exception object that was set as the cause for this object, or null if no cause was set.

  • StackTraceElement[] getStackTrace() 1.4

    gets the trace of the call stack at the time this object was constructed.

api_icon.gif
   java.lang.Exception 1.0
   
  • Exception(Throwable cause) 1.4

  • Exception(String message, Throwable cause)

    construct an Exception with a given cause.

api_icon.gif
   java.lang.RuntimeException 1.0
   
  • RuntimeException(Throwable cause) 1.4

  • RuntimeException(String message, Throwable cause) 1.4

    construct a RuntimeException with a given cause.

api_icon.gif
   java.lang.StackTraceElement 1.4
   
  • String getFileName()

    gets the name of the source file containing the execution point of this element, or null if the information is not available.

  • int getLineNumber()

    gets the line number of the source file containing the execution point of this element, or −1 if the information is not available.

  • String getClassName()

    gets the fully qualified name of the class containing the execution point of this element.

  • String getMethodName()

    gets the name of the method containing the execution point of this element. The name of a constructor is <init>. The name of a static initializer is <clinit>. You can't distinguish between overloaded methods with the same name.

  • boolean isNativeMethod()

    returns true if the execution point of this element is inside a native method.

  • String toString()

    returns a formatted string containing the class and method name and the file name and line number, if available.

Taking a Final Look at Java Error and Exception Handling

Example 11-2 deliberately generates a number of different errors and catches various exceptions (see Figure 11-2).

11fig02.jpgFigure 11-2 A program that generates exceptions

Try it out. Click on the buttons and see what exceptions are thrown.

As you know, a programmer error such as a bad array index throws a RuntimeException. An attempt to open a nonexistent file triggers an IOException. Perhaps surprisingly, floating-point computations such as dividing by 0.0 or taking the square root of −1 do not generate exceptions. Instead, they yield the special "infinity" and "not a number" values that we discussed in Chapter 3. However, integer division by 0 throws an ArithmeticException.

We trap the exceptions that the actionPerformed methods throw in the fireActionPerformed method of the radio buttons and display them in the text field. However, the actionPerformed method is declared to throw no checked exceptions. Thus, the handler for the "No such file" button must catch the IOException.

If you click on the "Throw unknown" button, an UnknownError object is thrown. This is not a subclass of Exception, so our program does not catch it. Instead, the user interface code prints an error message and a stack trace to the console.

Example 11-2. ExceptTest.java

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import javax.swing.*;
  4. import java.io.*;
  5.
  6. public class ExceptTest
  7. {
  8.    public static void main(String[] args)
  9.    {
 10.       ExceptTestFrame frame = new ExceptTestFrame();
 11.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 12.       frame.setVisible(true);
 13.    }
 14. }
 15.
 16. /**
 17.    A frame with a panel for testing various exceptions
 18. */
 19. class ExceptTestFrame extends JFrame
 20. {
 21.    public ExceptTestFrame()
 22.    {
 23.       setTitle("ExceptTest");
 24.       ExceptTestPanel panel = new ExceptTestPanel();
 25.       add(panel);
 26.       pack();
 27.    }
 28. }
 29.
 30. /**
 31.    A panel with radio buttons for running code snippets
 32.    and studying their exception behavior
 33. */
 34. class ExceptTestPanel extends Box
 35. {
 36.    public ExceptTestPanel()
 37.    {
 38.       super(BoxLayout.Y_AXIS);
 39.       group = new ButtonGroup();
 40.
 41.       // add radio buttons for code snippets
 42.
 43.       addRadioButton("Integer divide by zero", new
 44.          ActionListener()
 45.          {
 46.             public void actionPerformed(ActionEvent event)
 47.             {
 48.                a[1] = 1 / (a.length - a.length);
 49.             }
 50.          });
 51.
 52.       addRadioButton("Floating point divide by zero", new
 53.          ActionListener()
 54.          {
 55.             public void actionPerformed(ActionEvent event)
 56.             {
 57.                a[1] = a[2] / (a[3] - a[3]);
 58.             }
 59.          });
 60.
 61.       addRadioButton("Array bounds", new
 62.          ActionListener()
 63.          {
 64.             public void actionPerformed(ActionEvent event)
 65.             {
 66.                a[1] = a[10];
 67.             }
 68.          });
 69.
 70.       addRadioButton("Bad cast", new
 71.          ActionListener()
 72.          {
 73.             public void actionPerformed(ActionEvent event)
 74.             {
 75.                a = (double[])event.getSource();
 76.             }
 77.          });
 78.
 79.       addRadioButton("Null pointer", new
 80.          ActionListener()
 81.          {
 82.             public void actionPerformed(ActionEvent event)
 83.             {
 84.                event = null;
 85.                System.out.println(event.getSource());
 86.             }
 87.          });
 88.
 89.       addRadioButton("sqrt(-1)", new
 90.          ActionListener()
 91.          {
 92.             public void actionPerformed(ActionEvent event)
 93.             {
 94.                a[1] = Math.sqrt(-1);
 95.             }
 96.          });
 97.
 98.       addRadioButton("Overflow", new
 99.          ActionListener()
100.          {
101.             public void actionPerformed(ActionEvent event)
102.             {
103.                a[1] = 1000 * 1000 * 1000 * 1000;
104.                int n = (int) a[1];
105.             }
106.          });
107.
108.       addRadioButton("No such file", new
109.          ActionListener()
110.          {
111.             public void actionPerformed(ActionEvent event)
112.             {
113.                try
114.                {
115.                   InputStream in = new FileInputStream("woozle.txt");
116.                }
117.                catch (IOException e)
118.                {
119.                   textField.setText(e.toString());
120.                }
121.             }
122.          });
123.
124.       addRadioButton("Throw unknown", new
125.          ActionListener()
126.          {
127.             public void actionPerformed(ActionEvent event)
128.             {
129.                throw new UnknownError();
130.             }
131.          });
132.
133.       // add the text field for exception display
134.       textField = new JTextField(30);
135.       add(textField);
136.    }
137.
138.    /**
139.       Adds a radio button with a given listener to the
140.       panel. Traps any exceptions in the actionPerformed
141.       method of the listener.
142.       @param s the label of the radio button
143.       @param listener the action listener for the radio button
144.    */
145.    private void addRadioButton(String s, ActionListener listener)
146.    {
147.       JRadioButton button = new JRadioButton(s, false)
148.          {
149.             // the button calls this method to fire an
150.             // action event. We override it to trap exceptions
151.             protected void fireActionPerformed(ActionEvent event)
152.             {
153.                try
154.                {
155.                   textField.setText("No exception");
156.                   super.fireActionPerformed(event);
157.                }
158.                catch (Exception e)
159.                {
160.                   textField.setText(e.toString());
161.                }
162.             }
163.          };
164.
165.       button.addActionListener(listener);
166.       add(button);
167.       group.add(button);
168.    }
169.
170.    private ButtonGroup group;
171.    private JTextField textField;
172.    private double[] a = new double[10];
173. }

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020