University of Oxford

Computing Services

Java 5 catches up with C#

Author Barry Cornelius Date 1st December 2005; first created: 7th August 2004

Contents

1. Introduction

Introduction Introduction

2. The evolution of Java

The evolution of Java The evolution of Java The evolution of Java The evolution of Java

3. Using the Scanner class for keyboard input

3.1. The problem

The problem The problem The problem

3.2. Simple uses of the Scanner class

Simple uses of the Scanner class

3.3. Other details about the Scanner class

The class Scanner allows you easily to associate a variable with one of a number of different input streams such as the keyboard, a file or a string:

0047:       Scanner tScannerKeyboard   = new Scanner(System.in);
0048:       Scanner tScannerInputFile  = new Scanner(new File("input.txt"));
0049:       Scanner tScannerSomeString = new Scanner(tSomeString);

You can then apply methods such as nextInt to read a value from the input stream. Here, an unchecked exception java.util.InputMisMatchException will be thrown if the next token is not an int.

To avoid the possibility of this exception occurring, a method like hasNextInt can be used to determine if the next value is an int, as shown in this program:

0067: import java.util.Scanner;                                    // Analyse.java
0068: public class Analyse
0069: {
0070:    public static void main(String[] pArgs)
0071:    {
0072:       Scanner tScanner = new Scanner(System.in);
0073:       System.out.print("Type in a value: ");
0074:       if (tScanner.hasNextInt()) {
0075:          int tFirst = tScanner.nextInt();
0076:          System.out.println("Got an int: " + tFirst);
0077:       }
0078:       else if (tScanner.hasNextDouble()) {
0079:          double tFirst = tScanner.nextDouble();
0080:          System.out.println("Got a double: " + tFirst);
0081:       }
0082:       else {
0083:          String tFirst = tScanner.nextLine();
0084:          System.out.println("Got a string: " + tFirst);
0085:       }
0086:    }
0087: }

3.4. Reading more than one value from a line

The Scanner class also helps when you want the user to be able to type more than one value on a line. Suppose we want to read in an age, a height and the number of children. So the data might be something like:

42 1.85 2
Before Java 5, you would need to use something like StringTokenizer to break apart a line into separate items (often called tokens):
0100:       String tLine = tKeyboard.readLine();
0101:       StringTokenizer tTokens = new StringTokenizer(tLine);
0102:       String tAgeString = tTokens.nextToken();
0103:       int tAge = Integer.parseInt(tAgeString);
0104:       String tHeightString = tTokens.nextToken();
0105:       double tHeight = Double.parseDouble(tHeightString);
0106:       String tNumberOfChildrenString = tTokens.nextToken();
0107:       int tNumberOfChildren = Integer.parseInt(tNumberOfChildrenString);

However, the nextXXX methods of the Scanner class can cope with several items being on the same line. So the data:

42 1.85 2
can be read by the following code:
0120:       int tAge = tScanner.nextInt();
0121:       double tHeight = tScanner.nextDouble();
0122:       int tNumberOfChildren = tScanner.nextInt();

By default, tokens are assumed to be separated by whitespace. However, you can easily arrange for the scanner to use delimiters other than whitespace.

3.5. More about the Scanner class

4. Enhanced for statement

4.1. Details about the change

Details about the change Details about the change

4.2. When can you use it?

When can you use it?

5. Autoboxing and auto-unboxing

5.1. Using an ArrayList

Using an ArrayList Using an ArrayList Using an ArrayList

5.2. Storing an int in an ArrayList

Storing an int in an ArrayList

5.3. Java 5 provides autoboxing and auto-unboxing

5.4. Avoiding overuse of autoboxing and auto-unboxing

6. Methods with a variable number of parameters

6.1. The problem

6.2. The details of the change

Suppose there is a method called iEvaluate that expects as arguments a double and any number of ints. Here are some examples of a call of this method:

0214:       double tResult = iEvaluate(2.7, 25, 2, -5, 42, -10);
0215:       System.out.println(tResult);
0216:       tResult = iEvaluate(4.2, 42);
0217:       System.out.println(tResult);
0218:       tResult = iEvaluate(4.2);
0219:       System.out.println(tResult);

And here is a possible iEvaluate method:

0221:    private static double iEvaluate(double pFactor, int... pValues)
0222:    {
0223:       int tSum = 0;
0224:       for (int tValue : pValues)
0225:          tSum += tValue;
0226:       return tSum/pFactor;      
0227:    }

The int... signifies that the remaining arguments are ints. Within the method, this parameter behaves like an array and so the method can use a foreach loop.

7. The printf method

7.1. A new class for formatted printing

Java 5 introduces a new class called java.util.Formatter. The API documentation for this class is at [31]. It says: ‘Formatted printing for the Java language is heavily inspired by C's printf. Although the format strings are similar to C, some customizations have been made to accommodate the Java language and exploit some of its features. Also, Java formatting is more strict than C's; for example, if a conversion is incompatible with a flag, an exception will be thrown. In C inapplicable flags are silently ignored. The format strings are thus intended to be recognizable to C programmers but not necessarily completely compatible with those in C.’

7.2. Some examples of the use of printf

Here are some examples of the use of printf:

0242:       System.out.printf("%3d %1.2f%n%d%n", 
0243:                         tAge, tHeight, tNumberOfChildren);
0244:       String tFormat = 
0245:             "Age is %d, height is %f%nNo. of children is %d%n";
0246:       System.out.printf(tFormat, tAge, tHeight, tNumberOfChildren);
0247:       Calendar tNow = Calendar.getInstance();
0248:       System.out.printf("%tT%n", tNow);  
0249:       System.out.printf("%tY-%tm-%td%n", tNow, tNow, tNow);
0250:       System.out.printf("%tH:%<tM:%<tS%n", tNow);

The above code produces output like the following:

0253:  42 1.85
0254: 2
0255: Age is 42, height is 1.850000
0256: No. of children is 2
0257: 08:03:39
0258: 2004-08-12
0259: 08:03:39

The printf method used above is from the java.io.PrintStream package.

8. Methods with covariant return types

8.1. The problem

The problem The problem

8.2. Java 5 introduces covariant return types

8.3. Changes to the clone method

9. Enumeration types

9.1. The problem

9.2. Java 5 has enumeration types

Java 5 has enumeration types Java 5 has enumeration types

9.3. The methods provided by java.lang.Enum

The methods provided by java.lang.Enum

9.4. The classes EnumSet and EnumMap

You can use the new class java.util.EnumSet to create a set of enums and the new class java.util.EnumMap to create a map that uses enums as keys.

Here is some code illustrating two uses of EnumSet:

0472:       Day tToday = Day.Wednesday;
0473:       Day[] tDayValues = Day.values();
0474:       for (int tDayNumber = Day.Tuesday.ordinal();
0475:                tDayNumber<=Day.Thursday.ordinal(); tDayNumber++)
0476:       {
0477:          Day tDay = tDayValues[tDayNumber];
0478:          System.out.println(tDay + " " + tDay.compareTo(tToday));
0479:       }
0480:       for (Day tDay : EnumSet.range(Day.Tuesday, Day.Thursday))
0481:       {
0482:          System.out.println(tDay + " " + tDay.compareTo(tToday));
0483:       }
0484:       for (Day tDay : Day.values())
0485:       {
0486:          if (tDay.toString().length()==6)
0487:          {
0488:             System.out.println(tDay + " is a 6 letter day");
0489:          }
0490:       }
0491:       for (Day tDay : Day.values())
0492:       {
0493:          if (EnumSet.of(Day.Sunday, Day.Monday, Day.Friday).contains(tDay))
0494:          {
0495:             System.out.println(tDay + " is a 6 letter day");
0496:          }
0497:       }

The above code produces the output:

0511: Tuesday -1
0512: Wednesday 0
0513: Thursday 1
0514: Tuesday -1
0515: Wednesday 0
0516: Thursday 1
0517: Sunday is a 6 letter day
0518: Monday is a 6 letter day
0519: Friday is a 6 letter day
0520: Sunday is a 6 letter day
0521: Monday is a 6 letter day
0522: Friday is a 6 letter day

9.5. Providing fields and methods in an enum type

Providing fields and methods in an enum type Providing fields and methods in an enum type

9.6. Associating values with each enum value

Associating values with each enum value Associating values with each enum value

9.7. Is an enum type a class type?

9.8. Differences from C#

9.9. More about enumeration types

10. Annotating code with metadata

10.1. Adding annotations to programs

Adding annotations to programs

10.2. Declaring annotation types

10.3. The use of java.lang.Override

The use of java.lang.Override The use of java.lang.Override The use of java.lang.Override The use of java.lang.Override

10.4. Annotations for Web Services

Annotations for Web Services Annotations for Web Services

10.5. Other annotations

The Java Community Process (JSR 250) has also produced ‘annotations for common semantic concepts in the J2SE and J2EE platforms that apply across a variety of individual technologies. With the addition of JSR 175 ... we envision that various JSRs will use annotations to enable a declarative style of programming’. See [34] for more details of JSR 250.

11. Parameterized types and methods

11.1. The problem

The problem The problem The problem

11.2. Java 5 provides parameterized types

Java 5 provides parameterized types Java 5 provides parameterized types Java 5 provides parameterized types Java 5 provides parameterized types Java 5 provides parameterized types

11.3. Using a parameterized type for a parameter

The type List<Shape> can be used just like any other type. So we can produce methods that have this as their return type, or a method that has this as the type of one of its parameters:

0860:    private static void printList1(List<Shape> pList)
0861:    {
0862:       Iterator<Shape> tIterator = pList.iterator();
0863:       while (tIterator.hasNext())
0864:       {
0865:          Shape tShape = tIterator.next();
0866:          System.out.println("X is " + tShape.getX());
0867:       }
0868:    }

However, with Java 5, many of the uses of Iterator should be replaced by a foreach statement. So the above can be simplified to:

0869:    private static void printList2(List<Shape> pList)
0870:    {
0871:       for (Shape tShape : pList)
0872:       {
0873:          System.out.println("X is " + tShape.getX());
0874:       }
0875:    }

Things get interesting when you want to write a method that works for any homogeneous list: a list of shapes, a list of strings, and so on. The new notation:

List<?>
has to be used: it means a List where each element is of some unknown type. Here it is in action:
0876:    private static void printList3(List<?> pList)
0877:    {
0878:       Iterator<?> tIterator = pList.iterator();
0879:       while (tIterator.hasNext())
0880:       {
0881:          Object tObject = tIterator.next();
0882:          System.out.println(tObject);
0883:       }
0884:    }

Once again, this can be simplified to:

0885:    private static void printList4(List<?> pList)
0886:    {
0887:       for (Object tObject : pList)
0888:       {
0889:          System.out.println(tObject);
0890:       }
0891:    }

Suppose instead you want to provide a method that works only for a List where the element type is the type Shape or any of its subclasses. You may be tempted to use one of the methods given earlier, a method that has a parameter of type List<Shape>. However, a class that implements the interface List<Circle> cannot be used as an argument to this method. Instead we can use:

0892:    private static void printList5(List<? extends Shape> pList)
0893:    {
0894:       for (Shape tShape : pList)
0895:       {
0896:          System.out.println("X is " + tShape.getX());
0897:       }
0898:    }
This can be used with an object of a class that implements List<Shape>, an object of a class that implements List<Circle>, and so on.

11.4. Java 5 also has parameterized methods

Besides parameterized interface types and parameterized class types, Java 5 also permits parameterized methods. So the last two examples can be rewritten as:

0899:    private static <GType> void printList6(List<GType> pList)
0900:    {
0901:       for (GType tGType : pList)
0902:       {
0903:          System.out.println(tGType);
0904:       }
0905:    }
0906:    private static <GShape extends Shape> void printList7(List<GShape> pList)
0907:    {
0908:       for (GShape tGShape : pList)
0909:       {
0910:          System.out.println("X is " + tGShape.getX());
0911:       }
0912:    }

11.5. Defining our own parameterized type

Besides using the parameterized types that are in the APIs, we could define our own parameterized type. Suppose we want a collection object that remembers seven things: as soon as you add more than seven items, it forgets about something that has already been stored. Below there is a class called LimitedMemory that can be used to represent such an object.

It is assumed that all the objects that are to be stored in a LimitedMemory object are all of the same type. For this reason, it is written as a parameterized class type. Rather than use E, I have chosen to use the name GType.

One other thing: it is also assumed that each object has a value, and so each object is of a class that implements the Valuable interface. The code below introduces one type that meets these constraints; it is the type Name.

0914: public interface Valuable                                   // Valuable.java
0915: {
0916:    public int value();
0917: }

0918: public class Name implements Valuable                           // Name.java
0919: {
0920:    private String iString;
0921:    public Name(String pString)
0922:    {
0923:       iString = pString;
0924:    }
0925:    public String toString()
0926:    {
0927:       return iString;
0928:    }
0929:    public int value()
0930:    {
0931:       return iString.length();
0932:    }
0933: }

0934: import java.util.ArrayList;                            // LimitedMemory.java
0935: import java.util.Iterator;
0936: import java.util.Random;
0937: public class LimitedMemory <GType extends Valuable> 
0938:       implements Iterable<GType>
0939: {
0940:    private static final int iCapacity = 7; 
0941:    private ArrayList<GType> iArrayList;
0942:    private Random iRandom;
0943:    public LimitedMemory()
0944:    {
0945:       iArrayList = new ArrayList<GType>(iCapacity);
0946:       iRandom = new Random();
0947:    }
0948:    public void add(GType pGType)
0949:    {
0950:       if (iArrayList.size()<iCapacity)
0951:          iArrayList.add(pGType);
0952:       else
0953:          iArrayList.set(iRandom.nextInt(iCapacity), pGType);
0954:    }
0955:    public String toString()
0956:    {
0957:       return iArrayList.toString();
0958:    }
0959:    public int value()
0960:    {
0961:       int tSum = 0;
0962:       for (GType tGType : iArrayList)
0963:       {
0964:          tSum += tGType.value();
0965:       }
0966:       return tSum;
0967:    }
0968:    public Iterator<GType> iterator()
0969:    {
0970:       return iArrayList.iterator();
0971:    }
0972: }

Here are two fragments of code that use a LimitedMemory object:

0978:       LimitedMemory<Name> tLimitedMemory = new LimitedMemory<Name>();
0979:       tLimitedMemory.add(new Name("jim"));
0980:       tLimitedMemory.add(new Name("bert"));
1031:       iMyPrintln(tLimitedMemory);
1032:       System.out.println(" " + tLimitedMemory.value());
1033:       LimitedMemory<Name> tLimitedMemory2 = new LimitedMemory<Name>();
1034:       tLimitedMemory2.add(new Name("jim"));
1035:       tLimitedMemory2.add(new Name("bert"));
1036:       tLimitedMemory2.add(new Name("jill"));
1037:       System.out.println(iBiggestCost(tLimitedMemory, tLimitedMemory2));

The above code uses the following subsidiary methods:

1039:    private static void iMyPrintln(LimitedMemory<Name> pLimitedMemory)
1040:    {
1041:       System.out.print("+");
1042:       for (Name tName : pLimitedMemory)
1043:       {
1044:          System.out.print(tName + "+");
1045:       }
1046:       System.out.println();
1047:    }
1048:    private static 
1049:       <GType1 extends Valuable, GType2 extends Valuable> 
1050:          int iBiggestCost(
1051:             LimitedMemory<GType1> pLimitedMemory1,
1052:             LimitedMemory<GType2> pLimitedMemory2)
1053:    {
1054:       return Math.max(pLimitedMemory1.value(), pLimitedMemory2.value());
1055:    }

11.6. More about parameterized types and methods

See [5], [21], [1], [11], [12] and [16] for other information about parameterized types and methods.

12. Conclusions

Conclusions Conclusions

13. And finally

14. References

  1. Maria Lucia Barron-Estrada and Ryan Stansifer, 'A Comparison of Generics in Java and C#', http://www.cs.fit.edu/~mbarron/papers/ACM03.pdf
  2. Joshua Bloch, 'Effective Java', Addison Wesley, 2001, 0-201-31105-8.
  3. Joshua Bloch, 'New Language Features for Ease of Development in the Java 2 Platform, Standard Edition 1.5: A Conversation with Joshua Bloch', http://java.sun.com/features/2003/05/bloch_qa.html
  4. Joshua Bloch and Neal Gafter, 'Forthcoming Java Programming Language Features', http://www.cse.ogi.edu/class/cse529/slides/Tiger%20lang%20sldies%201_up.pdf
  5. Gilad Bracha, 'Generics in the Java Programming Language', http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
  6. Barry Cornelius, 'Understanding Java', Addison Wesley, 2001, 0-201-71107-9.
  7. Barry Cornelius, 'A Taste of C#', http://www.barrycornelius.com/papers/a.taste.of.csharp/
  8. Barry Cornelius, 'Comparing .NET with Java', http://www.barrycornelius.com/papers/comparing.dotnet.with.java/
  9. Barry Cornelius, 'Web Services using Axis', http://www.barrycornelius.com/papers/web.services.using.axis/
  10. Barry Cornelius, 'Web Services using .NET', http://www.barrycornelius.com/papers/web.services.using.dotnet/
  11. Bruce Eckel, 'Generics Aren't', http://mindview.net/WebLog/log-0050
  12. Bruce Eckel, 'Latent Typing', http://mindview.net/WebLog/log-0051
  13. Bruce Eckel, 'Java Issues & Directions', http://mindview.net/WebLog/log-0055
  14. Bruce Haddon, 'The Java Tiger Release', http://www.cs.colorado.edu/events/colloquia/docs/tiger.pdf
  15. Benedict Heal, 'Taming the Tiger', http://noops.prismtechnologies.com/talks/52/Event_075.ppt
  16. Anders Hejlsberg, 'Generics in C#, Java, and C++', http://www.artima.com/intv/genericsP.html
  17. JSR 181, 'Web Services Metadata for the Java Platform', http://jcp.org/en/jsr/detail?id=181
  18. Jeff Langr, 'Typesafe Enum: Using enum in J2SE 1.5 (Tiger)', http://www.langrsoft.com/articles/enum.html
  19. John Lewis and William Loftus, 'Java Software Solutions: Foundations of Program Design (3rd edition)', Addison Wesley, 2003, 0-201-78129-8.
  20. John Lewis and William Loftus, 'Java Software Solutions: Foundations of Program Design (4th edition)', Addison Wesley, 2004, 0-321-26979-9.
  21. Brett McLaughlin and David Flanagan, 'Java 1.5 Tiger: A Developer's Notebook', O'Reilly, 2004, 0-596-00738-8.
  22. Microsoft, 'Web Services Description Language (WSDL) Explained', http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwebsrv/html/wsdlexplained.asp
  23. Matt Quail, 'Groking Enum (aka Enum<E extends Enum<E>>)', http://madbean.com/blog/2004/3/
  24. Robert Stroud, 'The Evolution of Java', http://www.ics.ltsn.ac.uk/events/jicc8/JICCstroud JDK1.5.pdf
  25. Sun Microsystems, 'Java 2 SDK, Standard Edition, Version 1.5.0 Summary of New Features and Enhancements', http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html
  26. Sun Microsystems, '[Changes to the] Java Programming Language', http://java.sun.com/j2se/1.5.0/docs/guide/language/
  27. Sun Microsystems, 'Getting Started with the Annotation Processing Tool (apt)', http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
  28. Sun Microsystems, 'A Typesafe Enum Facility for the Java Programming Language', http://www.jcp.org/aboutJava/communityprocess/jsr/tiger/enum.html
  29. Sun Microsystems, 'Enums', http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
  30. Sun Microsystems, 'API documentation for the Enum class', http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Enum.html
  31. Sun Microsystems, 'API documentation for the Formatter class', http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html
  32. Sun Microsystems, 'API documentation for the Scanner class', http://java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.html
  33. JSR 14, 'Add Generic Types to the Java Programming Language', http://jcp.org/en/jsr/detail?id=14
  34. JSR 250, 'Common Annotations for the Java Platform', http://jcp.org/en/jsr/detail?id=250



Date 1st December 2005; first created: 7th August 2004 Author Barry Cornelius.
This page is copyrighted