«نوع جنریک» یک کلاس یا رابط جنریک است که برای نوعها پارامتری شده است. این کار به کامپایلر امکان میدهد تا ایمنی نوع را در کلاس یا رابط اعمال کند.
این رابط غیرجنریک Container را در نظر بگیرید:
class Container {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
چون این رابط نوعهای Object را میپذیرد و برمیگرداند، با هر نوع غیراولیهای کار میکند. اما این کار بیهزینه نیست، چون ممکن است بخشی از کد get را با انتظار Integer فراخوانی کند و بخشی دیگر set را با افزودن String، و در نتیجه یک استثنای زمان اجرا رخ دهد.
یک «کلاس جنریک» و یک «رابط جنریک» قالب زیر را دارند:
class ClassName<T1, T2, ..., Tn> { ... }
interface InterfaceName<T1, T2, ..., Tn> { ... }
بخش پارامترهای نوع، که بعد از اسم کلاس یا رابط میآید و با براکتهای زاویهدار (<>) مشخص میشود، پارامترهای نوع را تعیین میکند؛ یعنی همان متغیرهای نوع T1، T2، ... و Tn. میتوان از این پارامترها در بدنهی کلاس یا رابط استفاده کرد تا ایمنی نوع جنریک به دست آید.
این هم نسخهی جنریک Container است:
class Container<E> {
private E object;
public void set(E object) { this.object = object; }
public E get() { return object; }
}
حالا هنگام ساخت، باید اعلام کنیم که چه نوعی را در خود نگه میدارد و کامپایلر همان محدودیت را اعمال میکند:
// empty <> can infer from context
Container<String> stringContainer = new Container<>();
// compiler knows this is a String, so it is allowed
stringContainer.set("Some string");
// no cast needed, compiler knows it is a String
String result = stringContainer.get();
// this causes a compiler error:
stringContainer.set(42);