Chapter:Interfaces - Creating an anonymous class - Exercises

From Juneday education
Jump to: navigation, search

The previous chapter on anonymous classes was mostly for reading! We do however have some exercises for you if you feel like it - it would also help us a lot if you give us feedback on what you think about them.

We recommend that you read this: Oracle tutorial - Anonymous classes and also all links for further reading on the previous page and this one.

Exercises on Creating an anonymous class (not yet official)

Q1

Let's continue with the class (TestAnonymous) from the previous chapter. Download the java file TestAnonymous.java.

Compile the class and execute it (just as in the previous chapter):

$ javac TestAnonymous.java && java TestAnonymous
Unsorted: 
[CEPA, bepa, APA, ABBA, DEPA, Baba]
Sorted disregarding case:
[ABBA, APA, Baba, bepa, CEPA, DEPA]
Sorted using String's default compareTo:
[ABBA, APA

Take some seconds to reflect on what you've just learned about creating an anonymous class with the following code:

Collections.sort(strings, new Comparator<String>(){
        @Override
        public int compare(String first, String other){
          return first.toLowerCase().compareTo(other.toLowerCase());
        }
      });

Can we see any trace of this? Try the following ls -al:

$ ls 
'TestAnonymous$1.class'   TestAnonymous.class   TestAnonymous.java

What do you think TestAnonymous$1.class represents?

Expand using link to the right to see a suggested solution/answer.

The class file TestAnonymous$1.class is actually the compiled version of the class we anonymously created.

Q2

Let's inspect this class file a bit, using the tool javap. Try the following:

$ javap TestAnonymous\$1.class

You should see something like:

$ javap TestAnonymous\$1.class 
Compiled from "TestAnonymous.java"
final class TestAnonymous$1 implements java.util.Comparator<java.lang.String> {
  TestAnonymous$1();
  public int compare(java.lang.String, java.lang.String);
  public int compare(java.lang.Object, java.lang.Object);
}

Try to explain what "TestAnonymous$1 implements java.util.Comparator<java.lang.String>" means.

Expand using link to the right to see a suggested solution/answer.

You're actually seeing the class you created anonymously. javac created the class, with the name TestAnonymous$1 for you.

Q3

Now, it is your time to do some coding. Create a class (in a separate file) called ReversedStringComparator that has a compareTo method like this:

  public int compare(String first, String other) {
    return other.toLowerCase().compareTo(first.toLowerCase());
  }

The class should be possible to use as a comparator for Strings.

Expand using link to the right to see a suggested class implementation.

public class ReversedStringComparator {
  
  public int compare(String first, String other) {
    return other.toLowerCase().compareTo(first.toLowerCase());
  }

}

Compile the class:

$ javac ReversedStringComparator.java

All fine? Well, yes and no. Yes since it compiles fine. But no, since the class (as our suggestion looks) is not complete. We wanted to use the class as a comparator of strings so we need to tell javac that we are iimplementing the Comparator interface. But first, lets try using @Override, like this:

public class ReversedStringComparator {
  
  @Override
  public int compare(String first, String other) {
    return other.toLowerCase().compareTo(first.toLowerCase());
  }

}

Compile again:

$ javac ReversedStringComparator.java ReversedStringComparator.java:3: error: method does not override or implement a method from a supertype
  @Override
  ^
1 error

Uh oh.... why? With @Override we're asking javac to make sure that we're overriding (an existing) method called compare which we do not since we're inheriting from Object which has no such method and we're implementing NO interfaces. Solution? .... Well if we want to use this class as a Comparator we need to specify that we're implementing this interface:

import java.util.Comparator;

public class ReversedStringComparator implements Comparator<String> {
  
  @Override
  public int compare(String first, String other) {
    return other.toLowerCase().compareTo(first.toLowerCase());
  }

}

Ok, let's compile:

$ javac ReversedStringComparator.java

Q4

Let's use the class above (ReversedStringComparator) in the class TestAnonymous. Add a call to sort using a new TestAnonymous object as comparator. Here's a snippet from the file TestAnonymous.java:

    System.out.println("Sorted disregarding case:");
    System.out.println(strings);
    Collections.sort(strings);
    System.out.println("Sorted using String's default compareTo:");
    System.out.println(strings);

    Collections.sort(strings, new ReversedStringComparator());
    System.out.println("Sorted using ReversedStringComparator:");
    System.out.println(strings);

The class should be possible to use as a comparator for Strings.

Expand using link to the right to see a suggested class implementation.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class TestAnonymous {

  public static void main(String[] args) {
    ArrayList<String> strings = new ArrayList<>();
    strings.add("CEPA");
    strings.add("bepa");
    strings.add("APA");
    strings.add("ABBA");
    strings.add("DEPA");
    strings.add("Baba");
    System.out.println("Unsorted: ");
    System.out.println(strings);
    Collections.sort(strings, new Comparator<String>() {
        @Override
        public int compare(String first, String other) {
          return first.toLowerCase().compareTo(other.toLowerCase());
        }
      });
    System.out.println("Sorted disregarding case:");
    System.out.println(strings);

    Collections.sort(strings);
    System.out.println("Sorted using String's default compareTo:");
    System.out.println(strings);

    Collections.sort(strings, new ReversedStringComparator());
    System.out.println("Sorted using ReversedStringComparator:");
    System.out.println(strings);

  }
}

Compile and execute:

$ javac *.java
$ java TestAnonymous 
Unsorted: 
[CEPA, bepa, APA, ABBA, DEPA, Baba]
Sorted disregarding case:
[ABBA, APA, Baba, bepa, CEPA, DEPA]
Sorted using String's default compareTo:
[ABBA, APA, Baba, CEPA, DEPA, bepa]
Sorted using ReversedStringComparator:
[DEPA, CEPA, bepa, Baba, APA, ABBA]

Ok, the new class seems to be sorting in reverse. Fantastic guys. Nobel prize just around the corner? No. But let's ponder a bit. We have now created a separate class ReversedStringComparator that can sort a list alphabetically (or lexicographically as some would put it). OK, big deal? Well, it's not. But in the next question you should do the same (order reversed) using an anonymous class.

Q5

Let's use the code that does the job from the previous exercise:

  @Override
  public int compare(String first, String other) {
    return other.toLowerCase().compareTo(first.toLowerCase());
  }

OK, if we would like to go a bit further you could say that this code is what matters:

    return other.toLowerCase().compareTo(first.toLowerCase());

...and we agree. But for now the method is what we want to use in an anonymous class. So let's replace the following (rather new) code in the TestAnonymous class:

    Collections.sort(strings, new ReversedStringComparator());
    System.out.println("Sorted using ReversedStringComparator:");
    System.out.println(strings);

with an anonymous class.

Do you remember the syntax?

Expand using link to the right to see a suggested class implementation.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class TestAnonymous {

  public static void main(String[] args) {
    ArrayList<String> strings = new ArrayList<>();
    strings.add("CEPA");
    strings.add("bepa");
    strings.add("APA");
    strings.add("ABBA");
    strings.add("DEPA");
    strings.add("Baba");
    System.out.println("Unsorted: ");
    System.out.println(strings);
    Collections.sort(strings, new Comparator<String>() {
        @Override
        public int compare(String first, String other) {
          return first.toLowerCase().compareTo(other.toLowerCase());
        }
      });
    System.out.println("Sorted disregarding case:");
    System.out.println(strings);
    Collections.sort(strings);
    System.out.println("Sorted using String's default compareTo:");
    System.out.println(strings);

    /* Using separate class 
       Collections.sort(strings, new ReversedStringComparator());
       System.out.println("Sorted using ReversedStringComparator:");
       System.out.println(strings);
     */
    
    Collections.sort(strings, new Comparator<String>() {
        @Override
        public int compare(String first, String other) {
          return other.toLowerCase().compareTo(first.toLowerCase());
        }
      });
    System.out.println("Sorted using another anonymous class:");
    System.out.println(strings);

  }
}

Links

Source code for the exercises' suggested solutions

A version of the file TestAnonymous.java with all the above changes can be downloaded from: TestAnonymous.java. If you would like a verison of the ReversedStringComparator class, download it from here: ReversedStringComparator.java.

Further reading

Where to go next

Next page is: Interfaces_-_Rules_and_syntax

« PreviousBook TOCNext »