1

I just have learned that there is a problem with generic types in Java. The problem occurs if I want to write a method that uses a generic class. With the explicit specification of a type I will lose the flexibility that generic classes offer to me. I also cant use "Object" for the generic data type in the Method. But why not? "Object" is the basic class of every class in Java and this language has polymorphism so why this doesnt work?

Own Example to demonstrate:

Triplet.java

public class Triplet <T> {
    public T a, b, c;

    Triplet(T a, T b, T c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Triplet<String> triplet = new Triplet<>("Hello", "Guten Tag", "Bonjour");
        printPartsOfTriplet(triplet);
    }

    static void printPartsOfTriplet(Triplet<Object> triplet) {
        System.out.println(triplet.a);
        System.out.println(triplet.b);
        System.out.println(triplet.c);
    }
}

Error Message

Main.java:4: error: incompatible types: Triplet<String> cannot be converted to Triplet<Object>
        printPartsOfTriplet(triplet);
                            ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
Henry Weinert
  • 261
  • 3
  • 13
  • 3
    Let's say it worked. What happens when your `printPartsOfTriplet` method decides to set `triplet.a` to a non-string object? It's a `Triplet`, so that's allowed. But after the method completes, `Main` still has a reference to it, and thinks it's a `Triplet`. So, it could do `String x = triplet.a;` - but oops, that's not actually a string. – Blorgbeard Nov 16 '17 at 17:16

3 Answers3

2

Add a generic argument in the method static too, replace Object for a type variable:

public class Triplet <T> {
    public T a, b, c;

    Triplet(T a, T b, T c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public static void main(String[] args) {
        Triplet<String> triplet = new Triplet<String>("Hello", "Guten Tag", "Bonjour");
        printPartsOfTriplet(triplet);
    }

    static void printPartsOfTriplet(Triplet<?> triplet) {
       System.out.println(triplet.a);
       System.out.println(triplet.b);
       System.out.println(triplet.c);
    }



}

}

or a valid variant:

static <A> void printPartsOfTriplet(Triplet<A> triplet) {
    System.out.println(triplet.a);
    System.out.println(triplet.b);
    System.out.println(triplet.c);
}

here static <A> void printPartsOfTriplet(Triplet<A> triplet) you are saying "give me any Triplet<A>, it means a Triple with type A (not given yet), and I will print its values.

here static void printPartsOfTriplet(Triplet<Object> triplet) you are saying give me a Triplet<Object> ( a Triplet of type Object (a fixed type), and I will print its values (each one is an Object)). But Object type is not == String type, so, that gives you an error

developer_hatch
  • 15,898
  • 3
  • 42
  • 75
2

You need to use a wildcard.

static void printPartsOfTriplet(Triplet<?> triplet) {
    System.out.println(triplet.a);
    System.out.println(triplet.b);
    System.out.println(triplet.c);
}

There's a very simple rule here—the type of the variable declaration must match the type you pass to the actual object type.

http://www.thejavageek.com/2013/08/27/generics-polymorphism-with-generics/

2

Just to contribute to Damian's answer.

Your method called printPartsOfTriplet should probably be replaced to stay inside the Triplet class and then you should use the same generic type T to print it.

the owner of the information should handle the processing in major cases.