DEV Community

Calin Baenen
Calin Baenen

Posted on

Is there vararg-like generics in Java?

Are there generics that can act like varargs in Java?

E.g.

class Test<...T> {
    private final T[0] val = testarg;
    public Test(T[0] testarg) {
        val = testarg;
    }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (14)

Collapse
siy profile image
Sergiy Yevtushenko

This thing is called "variadic template" in C++ and, unfortunately, is not available in Java. Such a functionality requires implementation of generics as templates while in Java they're implemented using type erasure.

Collapse
baenencalin profile image
Calin Baenen Author

What's a template?
Give me a guide to this C++ godsend.

Collapse
siy profile image
Sergiy Yevtushenko

Well, the real guide would be a thick book like C++ Templates: The Complete Guide. But in brief, this is a technique, which allows the compiler to generate classes at compile time using the description of a generic class as a template. With this approach the compiler creates a new class for every type argument passed to template. For example, if your Java code uses List<String> and List<Integer>, both of these classes are actually the same instance of class List with type of contained element erased at compile time. In C++ same types will result in two different classes, where each class has its own set of methods and possibly different internal layout of the class. There are much more details and both approaches are not so simple, but overall high level picture looks as described above. By the way, if you're really interested in gaining more knowledge about C++ templates, the book mentioned above is one of the best among those dedicated to the topic.

Collapse
alainvanhout profile image
Alain Van Hout • Edited

Do you mean something like the following?

class Test<T, U, V>
Enter fullscreen mode Exit fullscreen mode
Collapse
baenencalin profile image
Calin Baenen Author

Yes. But, just like varargs, I want the user to enter as many as needed.

Collapse
alainvanhout profile image
Alain Van Hout

The user can’t input actual types, so I don’t see how that could be done.

Thread Thread
baenencalin profile image
Calin Baenen Author

Well, aren't "Types" just classes? Even primitives TYPES are classes, too.

When you use a generic, doesn't it just send the reference of the class to the variable?

class Test<T> { // T is our generic.

    public Test(T value /* T is a reference to the class. */) {/* code... */}

}

Test<String> test = new Test<>(); // T in this instance is Test is a reference to String.
Enter fullscreen mode Exit fullscreen mode

?

Is this true, or no?

Thread Thread
alainvanhout profile image
Alain Van Hout

I'm talking about the actual user input, not the developer.

With regard to your example, in Java that variable will be an object of type Test, which at compile time will have verified to use the type String in all cases where T is used in the general definition of the class. So no, no reference of the class is sent to the variable.

Thread Thread
baenencalin profile image
Calin Baenen Author

What if I use String.class?

Thread Thread
alainvanhout profile image
Alain Van Hout

String.class is a object representing the String type. But that's not what is needed here.

Think of it like this: if you have a generic box, a banana box and an apple box, then you can't transform a generic box into a banana box by throwing a banana at it. The banana needs to conceptually be in the picture when the box its design is created.

Thread Thread
baenencalin profile image
Calin Baenen Author • Edited

Okay.

Thanks.
Cheers.

Collapse
zoedreams profile image
☮️✝️☪️🕉☸️✡️☯️

no.

TL;DR;

... is basically just shorthand for an array of like types.

by allowing would create an unsafe operation which could potentially allow for buffer overflows or other nasty things.

docs.oracle.com/javase/tutorial/ja...

you can however recursively call the parent object using an anonymous type of <?> which then injects the next type in the array of reflected types into the root. I would advise against that due to circular dependency.

Collapse
baenencalin profile image
Calin Baenen Author

Oh. Is there any way I can include more than one, but a never finite amount of generics (safely)?

I really want to use it for something like this:

class Container<...T> {
    public Container(String[] names, Object[] values) {

        int pos = 0;
        for(String name : names) {
            Class Type = T[pos]; // T-POS!?!?
            /* Code to make a fake class ere */
            pos++;
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

Having something like that'd be cool.

Thanks for you answer.
Cheers.

Collapse
zoedreams profile image
☮️✝️☪️🕉☸️✡️☯️

nope you can only have one, and it has to be the first one.

you can not use T like an object, it is just a reference to what type you can cast object to,,

T obj = values[pos] // or names[
Enter fullscreen mode Exit fullscreen mode

also you dont need the pos or pos++. i would recommend using a regular for loop with index variables.

what is it your actually trying to do. I am confused with the T[pos]

T is not an object it is the name of object called T.

what is it your actually trying to do?