1

The following code alows to swap 2 Items of an Object :

public class Box<F, S> {
    F first;
    S second;   

    //Method to swap
    public static <F> void swapItems(Box<F,F> box){

        F temp = box.first;
        box.first = box.second;
        box.second = temp;
    }
}

//The method could also be implemented like this:

    void swapItems() {

        F tmp1 = first;
        S tmp2 = second;
        first = (F) tmp2;
        second = (S) tmp1;
    }

What is the advantage of the generic code? I just don't get it. Could sombody explain this to me? Might the generic one be useful if i call this method on 2 objects?

Smith
  • 25
  • 4
  • 9
    What if the type of F and S are different? – Thiyagu Jun 19 '18 at 16:55
  • If S would be a subclass of F it works (Number & Integer for example). If the types are diffrent i.e. Integer and String it would'nt work. – Smith Jun 19 '18 at 17:07
  • Why would you want to do this? You have a `Box`. You shouldn't care what order the items are in. You should be able to pull the item you care about out of the box. – Makoto Jun 19 '18 at 17:13

3 Answers3

1

The method could also be implemented like this:

No it couldn't. If you swap Box<F, S> you would get Box<S, F>, a different type. With an instance method, you can't just magically change the type of the object on which it is called!

A static method that changes Box<F,S> to Box<S, F> could be something like this:

public static <F, S> Box<S, F> swapItems(Box<F,S> box){

    Box<S, F> newBox = new Box<>();
    newBox.first = box.second;
    newBox.second = box.first;
    return newBox;
}

// usage:
Box<Integer, String> newBox = Box.swapItems(someBox);

An instance method is still possible to write, but you need to return a new box instead of changing the state of this.

public Box<S, F> itemsSwapped(){

    Box<S, F> newBox = new Box<>();
    newBox.first = this.second;
    newBox.second = this.first;
    return newBox;
}

// usage:
Box<Integer, String> newBox = someBox.itemsSwapped();
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • In your example: Is one of the 2 methods more useful than the other one? Why? – Smith Jun 19 '18 at 17:31
  • @Smith You call them differently. See the edit. I prefer the second one. You can choose whichever you think is more readable. – Sweeper Jun 19 '18 at 17:33
1

Your example class is in fact a good example of bad use of generics. A generic Box used to swap items is founded on a misconception.

Might the generic one be useful if i call this method on 2 objects?

That's right (with the code in the question). Generics aren't designed for code reuse or for structuring code. We have methods, packages, and modules for that.

A box of two items that supports swapping order, may be implemented better as follows (although a better-suited name would be Pair, I believe):

class Box<T> {
    private T first;
    private T second;   

    //2-parameter constructor

    public void swapItems(){

        T temp = first;
        first = second;
        second = temp;
    }

    //getters and setters
}

The above class could be used as follows:

Box<String> stringBox = new Box<>("first", "second");
String first = stringBox.getFirst();
String second = stringBox.getSecond();

Or as follows:

Box<Integer> intBox = new Box<>(1, 2);
int first = intBox.getFirst();
int second = intBox.getSecond();

What is the advantage of the generic code?

Assuming you had a class as the one above, then generics would allow you to make a box of different types <T>, with type-safety guaranteed by the compiler, just as shown in the two example uses: the Box class is defined once, but used with "box items" of different types, of which the compiler is aware and for which it helps validate types.

For example, the following incorrect calls would fail (continuing examples above):

String third = intBox.getFirst();

This last (incorrect) statement will fail at compile time, thus enabling faster feedback (as opposed to class cast exceptions at runtime).

Other important notes:

  • Your class declares two distinct type parameters, <F, S>, so you cannot "swap" first and second. The compiler would reject the code as the two types aren't guaranteed to be compatible.
ernest_k
  • 44,416
  • 5
  • 53
  • 99
0

This actually won't even compile, in many cases. For a more concrete example, say your type F is a String, and your type S is an Integer. Then, you'd end up with a swapItems method like this:

public void swapItems(){
    String first = "foo";
    Integer second = 2;
    String tmp1 = first;
    Integer tmp2 = second;
    first = (String) tmp2;
    second = (Integer) tmp1;
}

The compiler will complain: "Inconvertible types; cannot cast java.lang.Integer to java.lang.String".

davidmerrick
  • 1,027
  • 1
  • 10
  • 17