Java for C# Programmers 2: String, Console, Enum

Strings

C# has string, Java has String.

Strings are handled similar in both languages. In both cases, strings are class types and are immutable: String methods which seem at first to change the underlying object do not change this object, but create a new one and return the new one.

Escaping in string literals is the similar as in C#. Java knows

  • "\t, \n" and the like.
  • "\u20ac" for unicode characters.
  • Java understands "\065" as the octal value 065. This is not available in C#.
  • Java has no equivalent to the @ prefix for string constants. But it understands slashes as path separators, also on Windows.
  • Java does not understand "\x123" where 123 is interpreted as hex value.

Both languages have got also mutable string-like classes. C# has StringBuilder (not thread-safe). Java has StringBuilder (not thread-safe) and StringBuffer (thread-safe).

Like in C#, indexOf returns -1 if the searched string is not found.

string s = "abc";
int n = s.IndexOf("c", 7); // n = -1, no exception  

Gotcha: In Java, string comparison with == does not compare the contents. In C# it does. In Java, you have to use the function equals(..) to compare the contents of strings.

String Formatting

Java supports the old and well known C string formatters. C# doesn’t.

System.out.printf("Creating date: %02d.%02d.%04d", 10, 4, 2014); 
        // 10.04.2014

String s = String.format(">%6.2f<", 3.14159265359);  
        // s is  >  3,14< in Germany.
        // Yes, like in C#, the locale is used for formatting.

s = String.format(Locale.ENGLISH, ">%6.2f<", 3.141592);  
        // s is >  3.14<.

String Parsing

// Java
int i = Integer.parseInt("22"); 
int j = Integer.parseInt("ab");  // NumberFormatException

Java does not have TryParse functions.

Console

Output to Stdout

Output to stdout is done via System.out.print*.

System.out.println();           // only newline
System.out.println("abc");      // abc + newline
System.out.print("abc");        // abc without newline
System.out.print("abc\n");      // abc + newline
System.out.print("a" + "bc" + "\n");      // abc + newline

Java does not support C#-like formatted printing with {0} and {1} and so on. Instead, it supports formatted printing with a C-like printf function with some extensions. I'm giving some examples here but won't go into details.

System.out.printf("'%d'", 3);       //  '3'
System.out.printf("'%3x'", 10);     //  '  a'
System.out.printf("'%03d'", 3);     //  '003'
     String[][] z = {
            { "Name", "Anna" },
            { "Age", "27" },
            { "Sex", "Female" },
     };
     for (String[] s : z) 
         System.out.printf("%-5s:%7s", s[0], s[1]);

     // This prints:

    Name :  Anna
    Age  :     19
    Sex  : Female

Find a tutorial of Java's string formatting possibilities with printf and format there: http://docs.oracle.com/javase/tutorial/essential/io/formatting.html. And find the full format string syntax here:
http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax.

Input From Stdin

        System.out.print("\nEnter your weight:");
        double weight = sc.nextDouble();
        sc.nextLine(); // needed to consume the enter-key  
                       // left by the input of the double 

        System.out.print("\nEnter your name:");
        String name = sc.nextLine();

        System.out.print("\nEnter your size in cm:");
        int size = sc.nextInt();

        System.out.printf("\nWeight: %g   Name: %s   Size: %d", 
            weight, name, size);

Gotcha: After

Scanner sc = new Scanner(System.in);
sc.close();
sc = new Scanner(System.in);
sc.nextInt();

you'll get an NoSuchElementException in the last line. It is because sc.close() closes not only the Scanner, but also the System.in stream. Which cannot be reopened. So if you want to have a Scanner in your program which is bound to System.in, you can not close it if you may need it any time later in the same program.

Enums

There are enums in both languages, but there are huge differences. In C#, enums are implemented very similar to C and C++, as some special integers. They are derived from type Enum which is derived from one of the integer value types.

In Java, enumerations are also derived from a type called Enum, but this is a class, a reference type. There are no traces of underlying integers like in C#.

Like classes, enums can be defined in an own source file, as a subtype of another class or as a non-public type in a source file with another public type.

public enum Fruit { BANANA, ORANGE, APPLE, LEMON, PEAR };

or

public class A 
{
    enum SortOrder { ASCENDING, DESCENDING };
}

or

public class A 
{
   ...
}
enum Erinyes { Alecto, Megaera, Tisiphone };

The main methods of Enum are shown here.

Fruit a = Fruit.BANANA;
System.out.println(a.name());       
    // -> BANANA    name()  is not overridable
System.out.println(a.toString());   
    // -> BANANA    toString() is overridable

Fruit b = Fruit.valueOf("APPLE");   // Create an enum from its name  
System.out.println(b.name());       // APPLE    

// Create an enum from its name, 2nd possibility:

Fruit c = Enum.valueOf(Fruit.class, "ORANGE");  

// The ordinal() value is used to sort enums. 
// You cannot change the ordinal value
// aside of by changing the order in the definition. 
System.out.printf("%s:%d\n", c, c.ordinal());   // ORANGE:1
System.out.println(a.compareTo(b));             // -2     

for(Fruit i: Fruit.values())        
    System.out.printf("%s:%d ", i.name(), i.ordinal());  
    // -> BANANA:0 ORANGE:1 APPLE:2 LEMON:3 PEAR:4

// In contrast to Java's behaviour for strings, 
// the == operator for enums does what you expect.         

Fruit d = Fruit.ORANGE, e = Fruit.ORANGE;
if(d == e)
    System.out.println("==");       // ==
if(d.equals(e))
    System.out.println("equal");    // equal

Fruit k = Fruit.valueOf("Grapple"); // IllegalArgumentException    

Flags

In C#, you can define and use a set of flags like this:

[Flags]
enum Spices { None, Salt=1, Pepper=2, Chili=4, Paprika=8 };

void Main() 
{
    Spices x = Spices.Salt | Spices.Pepper;
    Console.WriteLine(x);               // Salt, Pepper
}

This is not possible in Java. In Java, you have to use a set of enums to represent flags. The type EnumSet is designed for that.

enum Spices { SALT, PEPPER, CHILI };

EnumSet s = EnumSet.noneOf(Spices.class);   // s is empty. 
s = EnumSet.allOf(Spices.class);  // s is (SALT | PEPPER | CHILI)

s = EnumSet.of(Spices.PAPRIKA, Spices.CHILI);   // s is (PEPPER | CHILI)

s = EnumSet.complementOf(s);                    // s is (SALT)

EnumSet z = EnumSet.copyOf(s);          // z is (SALT) 
System.out.println(z);                          // [SALT]

Enum With Methods, Properties And Constructors

You can add methods and properties to an enum like to any ordinary class. You can override virtual methods and you can add constructors. You cannot create an enum that is derived from another enum.

public enum Flavors { SWEET, SOUR, SPICY };

public enum Fruit 
{ 
    BANANA(EnumSet.of(Flavors.SWEET)),
    ORANGE(EnumSet.of(Flavors.SWEET, Flavors.SOUR)),
    LEMON(EnumSet.of(Flavors.SOUR));

    private Fruit(EnumSet flavors)
    {
        this.flavors = flavors;
    }

    @Override
    public String toString()
    {
        return name().toLowerCase() + flavors.toString();
    }

    public String toGerman()
    {
        switch(name())
        {
            case "BANANA":
                return "Banane";
            case "ORANGE":
                return "Orange";
            case "LEMON":
                return "Zitrone";
        }
        return null;
    }

    private EnumSet flavors;
};

System.out.println(Fruit.BANANA.toString());   // banana[SWEET]    

System.out.println(Fruit.ORANGE);              // orange[SWEET, SOUR]

System.out.println(Fruit.LEMON.toGerman());    // Zitrone