Generic Constructors in Java
Just as a method can have its own type parameter, so can a constructor. A generic constructor accepts an argument of any type at the moment the object is built, uses it, and then doesn't keep that type around: the class itself stays non-generic. It's a rare feature, but it explains how type parameters attach to exactly the code that needs them.
A Constructor That Accepts Any Type
public class Labels {
static class Label {
private final String text;
<T> Label(T value) {
text = value + " (" + value.getClass().getSimpleName() + ")";
}
String text() { return text; }
}
public static void main(String[] args) {
System.out.println(new Label(42).text());
System.out.println(new Label("Srihitha").text());
System.out.println(new Label(3.5).text());
}
}42 (Integer)
Srihitha (String)
3.5 (Double)How it works
<T> Label(T value)declares a type parameter on the constructor, before its name.- Each
new Label(...)call infersTfrom its argument:Integer,String,Double. - The constructor turns the value into text and stores only a
String. The classLabelis not generic: you writeLabel, neverLabel<Integer>.
Generic Constructor vs Generic Class
Generic class Box<T> | Generic constructor <T> Label(T v) | |
|---|---|---|
| The type is part of the object | Yes: Box<String> vs Box<Integer> | No: every object is just a Label |
| Fields can use the type | Yes | No; the type is gone after construction |
| Typical use | Containers, pairs, results | Accepting flexible input that's converted at once |
A class can be generic and have a generic constructor with a different parameter, but that's unusual and hard to read.
Common Mistakes
Writing new Label<Integer>(42). Label isn't generic; the constructor's type is inferred.
Trying to keep the value in a field of type T. T exists only inside the constructor.
Confusing it with the diamond. new Box<>(...) infers a generic class's type; a generic constructor infers its own.
Practice
- Easy: Write a class
Printablewith a generic constructor that stores"[" + value + "]"as a string, and create it with three different types. - Harder: Rewrite
Labelto use a static generic factory methodLabel.of(...)instead, and compare how the calls read.
Key Takeaways
Was this tutorial helpful?