Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics - type deducing

Tags:

java

generics

Consider the following:

 public class GenericTest {
    static void print(int x) {
        System.out.println("Int: " + x);
    }
    static void print(String x) {
        System.out.println("String: " + x);
    }

    static void print(Object x) {
        System.out.println("Object: " + x);
    }

    static <T> void printWithClass(T t) {
        print(t);
    }
    public static void main(String argsp[]) {
        printWithClass("abc");
    }
}

It prints Object: abc. Why doesn't it print String: abc?

like image 534
Shmoopy Avatar asked Feb 16 '12 14:02

Shmoopy


People also ask

How do I restrict a generic type in Java?

Java For Testers Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.

Do generics provide type safety?

By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.

Does Java support type inference?

Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.


2 Answers

This is because of Java type erasure: your

static <T> void printWithClass(T t) {
    print(t);
}

is actually a syntactic sugar on top of

static void printWithClass(Object t) {
    print(t);
}

To be fair, that "syntactic sugar" lets the compiler do some very nice and important checking, but at run-time there is only one copy of the printWithClass method, and it uses java.lang.Object as the type of your variable t.

If you have experienced generics in other languages (C#, C++ templates, Ada) type erasure would come in contrast to what you know, but this is how it works under the cover.

like image 83
Sergey Kalinichenko Avatar answered Oct 19 '22 09:10

Sergey Kalinichenko


Java supports method overriding (dynamic type binding), but not what you are trying to achieve (overloading is static polymorphism and not dynamic).

In order to achieve what you want to achieve in Java, you need double dispatch.

Visitor Pattern should be your friend here.

I have written you a code sample.

public class Test {

    public static void main(String argsp[]) {
        PrintTypeImpl typeImpl = new PrintTypeImpl(new StringType(), new IntType(), new ObjectType());
        typeImpl.accept(new PrintVisitor());
    }

    static final class PrintVisitor implements TypeVisitor {
        public void visit(IntType x) {
            System.out.println("Int: ");
        }

        public void visit(StringType x) {
            System.out.println("String: ");
        }

        public void visit(ObjectType x) {
            System.out.println("Object: ");
        }
    }

    interface TypeVisitor {
        void visit(IntType i);

        void visit(StringType str);

        void visit(ObjectType obj);
    }

    interface PrintType {
        void accept(TypeVisitor visitor);
    }

    static class StringType implements PrintType {
        @Override
        public void accept(TypeVisitor visitor) {
            visitor.visit(this);
        }
    }

    static class ObjectType implements PrintType {
        @Override
        public void accept(TypeVisitor visitor) {
            visitor.visit(this);
        }
    }

    static class IntType implements PrintType {
        @Override
        public void accept(TypeVisitor visitor) {
            visitor.visit(this);
        }
    }

    static final class PrintTypeImpl implements PrintType {

        PrintType[] type;

        private PrintTypeImpl(PrintType... types) {
            type = types;
        }

        @Override
        public void accept(TypeVisitor visitor) {
            for (int i = 0; i < type.length; i++) {
                type[i].accept(visitor);
            }
        }
    }

}
like image 34
Scorpion Avatar answered Oct 19 '22 09:10

Scorpion