Java Errors

Compile Time Errors

Error Messages

This section describes common error messages and how to interpret them. The examples used are very simple and are there only to demonstrate a point, not to be particularly useful. An important point to remember when fixing errors is start with the first few errors, fix them and then try to recompile. Sometimes you find fixing the first couple of errors will fix several others further down in the list - although occasionally it can generate more!

Example 1

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      // calculate the area of a rectangle (width * height)
  6.      int width = 100;
  7.      int height = 50;
  8.  
  9.      System.out.println("The area is " + area);
  10.   }
  11. }

The code above generates the following error message:

  JavaErrors.java:9: cannot resolve symbol
  symbol  : variable area  
  location: class JavaErrors
   System.out.println("The area is " + area);
                                       ^
  1 error

The first thing to do is don't panic. Look at each line of the error message:

Okay. Now we know that we are using the variable area on the given line and that the compiler doesn't recognise it. We can work out that the reason it doesn't recognise it is because we haven't declared it. If we declare the variable, that should fix the problem.

Here's the solution with the new line in bold:

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      // calculate the area of a rectangle (width * height)
  6.      int width = 100;
  7.      int height = 50;
  8.          
  9.      int area = width * height
  10. 
  11.     System.out.println("The area is " + area);
  12.   }
  13. }  

Let's say we make another mistake as we add the new line in the above solution and we forget to include the semicolon. This happens quite often. What's the error message?

  JavaErrors.java:8: ';' expected
      int area = width * height
                               ^

That's pretty easy to understand. Again the first line tells us the filename, the line number, and the error description even says something useful! In this case a semicolon is expected. To make things even clearer it shows us the problem line and indicates with the "^" symbol where the semicolon should be.

Take a look at the next example.

Example 2

  1.  public class JavaErrors
  2.  {
  3.      public static void main(String[] args)
  4.      {
  5.          System.out.println("Hello world!);
  6.      }
  7.  }

The code in example 2 generates the following error messages:

  JavaErrors.java:5: unclosed string literal
      System.out.println("Hello world);
                         ^
  JavaErrors.java:5: ')' expected
      System.out.println("Hello world);
                                       ^
  2 errors

Now we are getting used to the format of the error messages we can see that the error description says unclosed string literal. But what does this mean? In this case all it means is that we have missed the closing quote symbol (").

But what about the second error? Sometimes the java compiler can get confused when certain mistakes are made. This is one of those cases. It is also the reason why you should fix the first few errors first and then try to recompile. If you close the String and recompile you should find you get no errors.

Case Sensitivity & Spelling

Often you will find an error is generated because of a simple typo. Java is case sensitive so it is important you get it right. This type of error is demonstrated in example 3.

Example 3

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      System.out.Println("Hello world!");
  6.    }
  7.  }

The code in example 2 generates the following error message:

  JavaErrors.java:5: cannot resolve symbol
  symbol  : method Println  (java.lang.String)
  location: class java.io.PrintStream
      System.out.Println("Hello world");

OK, it's another cannot resolve symbol but this time the symbol is method Println (java.lang.String). In example 2 it was a variable, but here it is a method. Just briefly look at the location line. It's telling us that we are trying to call the Println method for an object of type java.io.PrintStream. This is a standard java class so we can look at the Java API to see what methods are available.

Back to the error. As before cannot resolve symbol means the java compiler cannot find the symbol it shows you on the symbol line. In this case it cannot find a method called Println for the object out. This is true, there is no such method, what we meant was println with a lowercase p. Fix this and jobs-a-good-un.

You should be aware that a similar error message would have been generated if you had misspelt println.

Wrong Parameters

A related error to the kind described above is calling a method with the wrong parameters. There are several ways in which the parameters may be wrong:

Example 4

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      Integer simpleInt = new Integer(1,2);
  6.      System.out.println(simpleInt);
  7.    }
  8.  }

The code in example 4 generates the following error message:

  JavaErrors.java:5: cannot resolve symbol
  symbol  : constructor Integer  (int,int)
  location: class java.lang.Integer
      Integer simpleInt = new Integer(1,2);
                          ^

Once again it's cannot resolve symbol, and this time the symbol is a constructor. So what can't the compiler find this time? It can't find a constructor in the Integer class that takes two int values. Check the Java API to see what constructors are available. There are at least two:

A constructor which takes one int exists, but a constructor that takes two doesn't, hence the error message. Remove one of the int arguments and the problem will be fixed.

Example 5

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      Integer simpleInt = new Integer(2.5);
  6.      System.out.println("My Integer has a value "+simpleInt);
  7.    }
  8.  }

The code in example 5 generates the following error message:

  JavaErrors.java:5: cannot resolve symbol
  symbol  : constructor Integer  (double)
  location: class java.lang.Integer
      Integer simpleInt = new Integer(2.5);
                          ^

This is similar to the problem with example 4, this time we have the right number of parameters but the one we are passing in is of the wrong type. A constructor which takes a double argument doesn't exist so we get the error message. Change the value 2.5 to 2 and it should fix the problem. But what happens if the value I want to pass to the constructor is held in a variable of type double? How can I convert it to an int? Take a look at casting errors.

Casting Errors

Casting errors can occur when we try to convert a primitive or object of one type into a primitive or object of another type. Some types of conversion just aren't allowed, and if you try to perform an illegal conversion you will get errors.

let's change the code in example 5 above so that the value is held in a primitive double, and we want to create an Integer object using the Integer(int) constructor.

Example 6

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.       double doubleValue = 2.5;
  6.       Integer simpleInt = new Integer(doubleValue);
  7.       System.out.println("My Integer has a value " + simpleInt);
  8.    }
  9.  }

The code in example 6 has the same problem as example 5, and generates a similar error message. We can't pass a double to an Integer constructor, because no such constructor exists! So what can we do? Let's try casting the double to an int. Change the line:

  Integer simpleInt = new Integer(doubleValue);

in example 6 to:

  Integer simpleInt = new Integer((int)doubleValue);

The new bit, the cast, is highlighted in bold. But what happens when you run the program; what will be output for the value of the Integer? Will it be 2.5 or will it be 2?

The int primitive type and the Integer class can only store whole number values. Casting the double to an int causes the value of that double to be truncated (or rounded down) to the nearest int. So in this case the output will be:

  My Integer has a value 2

This is something you have to be careful with when casting from one primitive or object to another. However, it's not normally something that the compiler will warn you about. This sort of problem will be covered later in the section on Runtime Errors.

We haven't actually seen a compile time casting error yet - let's create one.

Example 7

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      int intValue = 100;
  6.      String myString = (String)intValue; 
  6.      System.out.println("The current int value is " + myString);
  7.    }
  8.  }

The (somewhat convoluted) code in example 7 generates the following error message:

  JavaErrors.java:6: inconvertible types
  found   : int
  required: java.lang.String
      String myString = (String)intValue;
                                ^

This looks a bit different (finally something other than cannot resolve symbol!). The error description is inconvertible types, which means that the value we are trying to cast isn't compatible with the type that we are trying to cast it to. There are lots of rules governing casting, but one fundamental principle is that you cannot cast a primitive type to an object type, or vice versa. To get around this problem, we need a means of creating a String object from an int primitive. If you look at the Java API for the String class, you can see that the static method valueOf(int i) does what we want. We can pass an int into the valueOf method and get an appropriate String object back. The code in example 7 then becomes:

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      int intValue = 100;
  6.      String myString = String.valueOf(intValue); 
  6.      System.out.println("The current int value is " + myString);
  7.    }
  8.  }

Runtime Errors

Runtime Exceptions

Java has two types of exceptions, checked and unchecked exceptions. Checked exceptions are the ones that you have to deal with in your code wherever they may occur, either by using a try block, or by including a throws clause in the method signature. Unchecked exceptions are generally those which could occur so frequently in any normal piece of code that it would be impossible to try and handle them. All unchecked exceptions must be direct or indirect subclasses of RuntimeException, this is what tells the compiler that a particular exception is exempt from the rules governing checked exceptions.

If a RuntimeException occurs, it will not normally be handled within the code, and so will cause your program to crash. However, a RuntimeException is usually a sign that there is an error in your code, so you shouldn't try and handle them; instead you should change your program to prevent the exception from occuring. Two of the most common types of RuntimeException are described below.

ArrayIndexOutOfBoundsException

This exception is thrown when the index value used to access an array is not valid. When access the elements of an array, the index value must be between 0 and the size of the array minus one.

Example 8

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      int[] myArray = new int[3];      // an int array with size = 3
  6.      
  7.      myArray[0] = 1;      // OK
  8.      myArray[1] = 2;      // OK
  9.      myArray[2] = 3;      // OK
  10.     myArray[3] = 4;   // Error - index 3 is invalid
  11.   }
  12. }

In the code above, the line:

  myArray[3] = 4;   // Error - index 3 is invalid

will generate an ArrayIndexOutOfBoundsException similar to the following:

  java.lang.ArrayIndexOutOfBoundsException
     at JavaErrors.main(JavaErrors.java:10)

From the above error message, you can determine that the error occurred on line 10 of the file JavaErrors.java. Checking this line, you can see that the index used is equal to the size of the array and is therefore not valid.

NullPointerException

If an object reference is null, it means that no value has yet been assigned to that reference, i.e. it has been declared, but not initialised. To read more about declaration and initialisation, look on the miscellaneous information page.

A NullPointerException occurs if you try to use a null reference as though it were a reference to an actual object, e.g. if you try and call a method for the object.

Example 9

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      int[] myArray = new int[3];      // an int array with size = 3
  6.      int[] anotherArray;              // an array that has been declared, 
  7.                                       // but not initialised, so it's null
  8.      myArray[0] = 1;      // OK
  9.      myArray[1] = 2;      // OK
  10.     myArray[2] = 3;      // OK
  11.    
  12.     anotherArray[0] = 4;   // Error - anotherArray is null
  13.   }
  14. }

The code in example 9 will generate a NullPointerException similar to the following:

  java.lang.NullPointerException
     at JavaErrors.main(JavaErrors.java:12)

The second array variable, named anotherArray, has not been initialised, so attempting to access any of its elements will result in this kind of exception.

If a NullPointerException occurs within your program, look at the line indicated in the error message. Often there will only be one object reference on the line, in which case you know that is the null reference. If there are more references, you need to establish which one is null. Once you have found the null reference, trace the code back to find where it should have been initialised, and fix the problem.

Another common mistake which causes NullPointerExceptions is shown in the next example.

Example 10

  1.  public class JavaErrors
  2.  {
  3.    private String myName;
  4.      
  5.    public JavaErrors()
  6.    {
  7.      String myName = "B.Wilkins";
  8.    }
  9.      
  10.   public int getNameLength()
  11.   {
  12.     return myName.length();
  13.   }
  14.   
  15.   public static void main(String[] args)
  16.   {
  17.     new JavaErrors();
  18.   }
  19. }

The line in italics in example 10 will generate a NullPointerException, but it's actually the line in bold where the mistake has been made. This is a problem with object scope. The String myName is a data member of the class. It has been declared at the top of the class but not initialised. Normally, you would initialise it in the constructor, which is what's supposed to happen here. However, instead of referencing the instance variable myName and initialising it like this:

  myName = "B.Wilkins";

what actually happens in the constructor is rather different. A new variable named myName is declared and initialised. This variable is local to the constructor, so that when the constructor has finished, this variable is lost. At no point is any change made to the instance variable myName, which means that it will still be null when the constructor has finished. Consequently, attempting to call the length() method on line 12 will cause a NullPointerException. The solution is to change line 7 to the one shown above.

Infinite Loops

An infinite loop is a loop that never ends, causing your program to run on and on until you kill it. The compiler cannot detect infinite loops and will not generate any warning messages. It is up to you to prevent them from occurring. Common causes of infinite loops include:

Skipping Code

Skipping code is generally caused by adding a semi-colon at the end of a control statement (if, while, for, etc.,). The resulting code is legal Java, so the compiler won't generate any warnings, but it will not behave how you expect it to.

Example 11

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      int i = Integer.parseInt(args[0]);
  6.    
  7.      if (i > 100);
  8.        System.out.println("Arg value is greater than 100");
  9.    }
  10. }

No matter what command line argument is passed to this program, it will always print the message saying that the value is greater than 100. To understand this, you need to remember the rules for what part of the code is governed by a control statement. If the first non-whitespace character after the control statement is an opening brace, then the statement governs the entire block of code up to the closing brace. Otherwise, the control statement governs the next statement, i.e. up to the first semi-colon. Because the first character after the if statement on line 7 is a semi-colon, the if statement governs the empty statement between the closing parenthesis and the semi-colon, i.e. if the value of i is greater than 100, it does nothing. The following statement is then executed every time, because it is outside the control structure.

N.B. This sort of mistake can also easily generate an infinite loop, as in the example below:

Example 12

  1.  public class JavaErrors
  2.  {
  3.    public static void main(String[] args)
  4.    {
  5.      int i = 0;
  6.    
  7.      while (i < 10);
  8.      {
  9.        System.out.println("i = " + i);
  10.       i++;
  11.     }
  12.   }
  13. }