[{"data":1,"prerenderedAt":130},["ShallowReactive",2],{"qa-\u002Fjava\u002Fgenerics\u002Fwildcards-bounds":3},{"page":4,"siblings":117,"blog":127},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":12,"path":20,"questions":21,"questionsCount":107,"related":108,"seo":109,"seoDescription":110,"stem":111,"subtopic":112,"topic":113,"topicSlug":114,"updated":115,"__hash__":116},"qa\u002Fjava\u002Fgenerics\u002Fwildcards-bounds.md","Wildcards Bounds",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"hard","md","Java","java",{},true,"\u002Fjava\u002Fgenerics\u002Fwildcards-bounds",[22,27,31,35,39,43,47,51,55,59,63,67,71,75,79,83,87,91,95,99,103],{"id":23,"difficulty":24,"q":25,"a":26},"unbounded-wildcard","medium","What is the unbounded wildcard \u003C?> and what does it mean?","The **unbounded wildcard** `\u003C?>` means \"a `List` of **some unknown type**\" —\nyou don't know or care which. It makes a generic method work over collections\nof *any* element type while staying type-safe, unlike a raw type.\n\n```java\nstatic void printAll(List\u003C?> list) {        \u002F\u002F any element type\n  for (Object o : list) System.out.println(o); \u002F\u002F safe: everything is an Object\n}\nprintAll(List.of(1, 2, 3));      \u002F\u002F List\u003CInteger> ok\nprintAll(List.of(\"a\", \"b\"));     \u002F\u002F List\u003CString> ok\n```\n\nBecause the element type is unknown, you **can read elements as `Object`** but\n**can't add** anything (except `null`) — the compiler can't prove your value\nmatches the hidden type. Use `\u003C?>` when the method body doesn't depend on the\nelement type at all.\n",{"id":28,"difficulty":14,"q":29,"a":30},"list-wildcard-vs-object-vs-raw","What is the difference between List\u003C?>, List\u003CObject> and a raw List?","They look similar but behave very differently:\n\n| Declaration | Accepts | Can add? | Type-safe? |\n| ----------- | ------- | -------- | ---------- |\n| `List\u003C?>` | any `List\u003CX>` | only `null` | yes |\n| `List\u003CObject>` | only `List\u003CObject>` | any object | yes |\n| `List` (raw) | any `List` | anything (unchecked) | no — legacy |\n\n```java\nList\u003CString> strs = new ArrayList\u003C>();\nList\u003C?> a = strs;        \u002F\u002F ok — unknown element type\nList\u003CObject> b = strs;   \u002F\u002F compile error — not the same type\nList c = strs;           \u002F\u002F ok but unchecked warnings; defeats generics\n```\n\n`List\u003CObject>` is a concrete type that only matches `List\u003CObject>`. `List\u003C?>`\nmatches *every* parameterization but is read-only. The **raw** `List` exists\nonly for pre-generics compatibility — it disables type checking, so avoid it.\n",{"id":32,"difficulty":24,"q":33,"a":34},"upper-bounded-wildcard","What is an upper-bounded wildcard \u003C? extends T>?","`\u003C? extends T>` means \"some **unknown subtype** of `T`\" — it sets an **upper\nbound**. It's used when you want to **read** `T` values out of a structure but\ndon't need to know the exact subtype.\n\n```java\nstatic double sum(List\u003C? extends Number> nums) { \u002F\u002F Number or any subtype\n  double total = 0;\n  for (Number n : nums) total += n.doubleValue(); \u002F\u002F safe: all are Numbers\n  return total;\n}\nsum(List.of(1, 2, 3));        \u002F\u002F List\u003CInteger> ok\nsum(List.of(1.5, 2.5));       \u002F\u002F List\u003CDouble> ok\n```\n\nEvery element is guaranteed to be **at least a `T`**, so reading as `T` is\nsafe. This is the **producer** side — the structure produces `T`s for you to\nconsume.\n",{"id":36,"difficulty":14,"q":37,"a":38},"why-cant-add-extends","Why can't you add to a List\u003C? extends Number>?","Because the compiler knows the list is `List\u003CSomeSubtypeOfNumber>` but **not\nwhich** subtype. It could be `List\u003CInteger>`, `List\u003CDouble>`, or anything else —\nso adding *any* concrete value might violate the real element type.\n\n```java\nList\u003C? extends Number> nums = new ArrayList\u003CInteger>();\nnums.add(1);        \u002F\u002F compile error — what if it's really List\u003CDouble>?\nnums.add(1.5);      \u002F\u002F compile error — what if it's really List\u003CInteger>?\nnums.add(null);     \u002F\u002F the only legal add — null fits any type\nNumber n = nums.get(0); \u002F\u002F reading is fine — guaranteed to be a Number\n```\n\nThe list becomes effectively **read-only** for element types. The rule:\n`extends` wildcards are for **getting**, not putting.\n",{"id":40,"difficulty":24,"q":41,"a":42},"lower-bounded-wildcard","What is a lower-bounded wildcard \u003C? super T>?","`\u003C? super T>` means \"some **unknown supertype** of `T`\" — it sets a **lower\nbound**. It's used when you want to **write** `T` values *into* a structure.\n\n```java\nstatic void addNumbers(List\u003C? super Integer> list) { \u002F\u002F Integer or any supertype\n  list.add(1);          \u002F\u002F safe — an Integer fits a List of Integer-or-wider\n  list.add(2);\n}\naddNumbers(new ArrayList\u003CInteger>()); \u002F\u002F ok\naddNumbers(new ArrayList\u003CNumber>());  \u002F\u002F ok — Integer fits a Number list\naddNumbers(new ArrayList\u003CObject>());  \u002F\u002F ok — Integer fits an Object list\n```\n\nWhatever the real type is, it's `Integer` or wider, so an `Integer` is always a\nvalid element. This is the **consumer** side — the structure consumes the `T`s\nyou supply.\n",{"id":44,"difficulty":14,"q":45,"a":46},"read-from-super-wildcard","What can you read back from a List\u003C? super T>?","Only **`Object`**. The compiler knows the list holds *some supertype* of `T`,\nbut the widest guaranteed common type of any supertype is `Object`, so that's\nall a `get` can be typed as.\n\n```java\nList\u003C? super Integer> list = new ArrayList\u003CNumber>();\nlist.add(42);              \u002F\u002F writing Integers is fine\nObject o = list.get(0);    \u002F\u002F ok — only Object is guaranteed\nInteger i = list.get(0);   \u002F\u002F compile error — could be a Number\u002FObject list\n```\n\nSo `super` wildcards are primarily for **putting in**; reading gives you back\nuntyped `Object`. This asymmetry with `extends` is exactly what PECS captures.\n",{"id":48,"difficulty":14,"q":49,"a":50},"pecs-principle","What is the PECS principle?","**PECS** = **Producer Extends, Consumer Super**. When a parameter **produces**\n`T`s for you (you read from it), use `\u003C? extends T>`. When it **consumes** `T`s\nyou give it (you write to it), use `\u003C? super T>`. The canonical example is a\n`copy` method:\n\n```java\n\u002F\u002F src PRODUCES elements -> extends; dest CONSUMES elements -> super\nstatic \u003CT> void copy(List\u003C? extends T> src, List\u003C? super T> dest) {\n  for (T t : src) dest.add(t);   \u002F\u002F read from src, write to dest\n}\nList\u003CInteger> ints = List.of(1, 2, 3);\nList\u003CNumber> dst = new ArrayList\u003C>();\ncopy(ints, dst);                 \u002F\u002F Integer producer -> Number consumer\n```\n\nThis is how `Collections.copy` is actually declared. PECS maximizes API\nflexibility: callers can pass a wider range of list types on each side.\n",{"id":52,"difficulty":14,"q":53,"a":54},"bounded-type-param-vs-wildcard","When should you use a bounded type parameter \u003CT extends Number> vs a wildcard?","Use a **bounded type parameter** when you need to **name the type** — to refer\nto it more than once, relate two arguments, or use it in the return type. Use a\n**wildcard** when the type is used only **once** and you never need to name it.\n\n```java\n\u002F\u002F type parameter: the SAME T links input and return\nstatic \u003CT extends Number> T firstOf(List\u003CT> list) { return list.get(0); }\n\n\u002F\u002F wildcard: type used once, never named\nstatic double sumOf(List\u003C? extends Number> list) { \u002F* ... *\u002F return 0; }\n```\n\nA good rule: if a wildcard would force you to invent a helper just to name the\ntype, use a type parameter instead. Otherwise prefer wildcards in API\nparameters — they read more cleanly to callers.\n",{"id":56,"difficulty":14,"q":57,"a":58},"multiple-bounds","How do multiple bounds \u003CT extends A & B> work?","A type parameter can require **several bounds** joined by `&`, meaning `T` must\nsatisfy **all** of them. At most **one can be a class**, and if present it must\ncome **first**; the rest must be interfaces.\n\n```java\n\u002F\u002F T must be both Comparable AND Serializable\nstatic \u003CT extends Comparable\u003CT> & Serializable> T maxOf(T a, T b) {\n  return a.compareTo(b) >= 0 ? a : b; \u002F\u002F can call Comparable methods on T\n}\n\n\u002F\u002F class first, then interfaces:\nstatic \u003CT extends Number & Comparable\u003CT>> T pick(T x) { return x; }\n```\n\nWithin the method `T` exposes the members of **all** bounds. Wildcards, by\ncontrast, allow only a **single** bound (`\u003C? extends A>`), so multiple bounds\nrequire a named type parameter.\n",{"id":60,"difficulty":14,"q":61,"a":62},"recursive-bound","Why does \u003CT extends Comparable\u003CT>> appear so often?","This is a **recursive (self-referential) type bound** — `T` must be comparable\n**to itself**. It captures the idea \"this type knows how to order its own\ninstances,\" which is exactly what sorting and min\u002Fmax need.\n\n```java\nstatic \u003CT extends Comparable\u003CT>> T max(List\u003CT> list) {\n  T best = list.get(0);\n  for (T t : list)\n    if (t.compareTo(best) > 0) best = t; \u002F\u002F t.compareTo(T) is type-safe\n  return best;\n}\nmax(List.of(3, 1, 2));        \u002F\u002F T = Integer, Integer implements Comparable\u003CInteger>\n```\n\nWithout the recursion you couldn't safely call `compareTo` with a `T` argument.\nThe real `Collections.max` uses `\u003CT extends Comparable\u003C? super T>>` — slightly\nlooser so a subtype can reuse an ancestor's comparison.\n",{"id":64,"difficulty":14,"q":65,"a":66},"wildcard-capture","What is wildcard capture and the capture-helper pattern?","**Wildcard capture** is the compiler giving the unknown type of a `\u003C?>` a\ntemporary name (shown in errors as `CAP#1`). Sometimes you need to *name* that\ntype to operate on it — the fix is a private **capture helper** generic method\nthat captures the wildcard into a real type variable.\n\n```java\n\u002F\u002F fails: compiler won't prove list.get(i) matches list.set(j, ...)\nstatic void swap(List\u003C?> list, int i, int j) {\n  swapHelper(list, i, j);                 \u002F\u002F delegate to capture the wildcard\n}\nprivate static \u003CT> void swapHelper(List\u003CT> list, int i, int j) {\n  T tmp = list.get(i);                    \u002F\u002F now there is a concrete T\n  list.set(i, list.get(j));\n  list.set(j, tmp);\n}\n```\n\nThe public method keeps the clean `\u003C?>` signature; the helper captures the\nwildcard as `T` so the body type-checks.\n",{"id":68,"difficulty":14,"q":69,"a":70},"array-covariance-generic-invariance","Why are arrays covariant but generics invariant?","Arrays are **covariant**: `String[]` *is a* `Object[]`. Generics are\n**invariant**: `List\u003CString>` is **not** a `List\u003CObject>`. Generics chose\ninvariance for **compile-time safety** — array covariance defers the check to\nruntime and can blow up.\n\n```java\nObject[] arr = new String[3];\narr[0] = 42;          \u002F\u002F compiles, throws ArrayStoreException at RUNTIME\n\nList\u003CObject> list = new ArrayList\u003CString>(); \u002F\u002F compile error — caught early\n```\n\nBecause generics are erased at runtime there's no `ArrayStore` check to fall\nback on, so the language forbids the unsafe assignment up front. **Wildcards**\nthen restore the lost flexibility safely (`List\u003C? extends Object>` accepts a\n`List\u003CString>` but won't let you put the wrong thing in).\n",{"id":72,"difficulty":24,"q":73,"a":74},"wildcards-restore-flexibility","How do wildcards restore the flexibility lost to invariance?","Invariance means `List\u003CInteger>` isn't a `List\u003CNumber>`, so a method taking\n`List\u003CNumber>` would reject an `Integer` list. A **wildcard** widens the\nparameter to accept a family of types while staying safe.\n\n```java\nstatic double total(List\u003CNumber> list) { \u002F* ... *\u002F return 0; }\ntotal(new ArrayList\u003CInteger>());      \u002F\u002F compile error — invariance\n\nstatic double total2(List\u003C? extends Number> list) { \u002F* ... *\u002F return 0; }\ntotal2(new ArrayList\u003CInteger>());     \u002F\u002F ok — wildcard accepts subtypes\ntotal2(new ArrayList\u003CDouble>());      \u002F\u002F ok\n```\n\nSo wildcards are the bridge between strict invariance and the polymorphism you\nactually want — you opt into covariance (`extends`) or contravariance (`super`)\nexactly where it's safe.\n",{"id":76,"difficulty":14,"q":77,"a":78},"collections-max-signature","Why is Collections.max declared with both extends and super wildcards?","Its signature is `static \u003CT extends Object & Comparable\u003C? super T>> T\nmax(Collection\u003C? extends T> coll)`. The two wildcards do different jobs:\n`Collection\u003C? extends T>` lets it accept any subtype collection (the collection\n**produces** `T`s), and `Comparable\u003C? super T>` lets a type be ordered by a\ncomparator **inherited from an ancestor**.\n\n```java\nclass Animal implements Comparable\u003CAnimal> { \u002F* ... *\u002F }\nclass Dog extends Animal { }\n\nList\u003CDog> dogs = List.of(new Dog(), new Dog());\nDog biggest = Collections.max(dogs); \u002F\u002F Dog uses Animal's Comparable\u003CAnimal>\n```\n\nThe `super` on `Comparable` is the key flexibility: `Dog` doesn't need its own\n`compareTo` — inheriting `Comparable\u003CAnimal>` suffices. This is PECS applied to\nthe comparison itself.\n",{"id":80,"difficulty":24,"q":81,"a":82},"addall-signature","How does Collection.addAll use wildcards?","`boolean addAll(Collection\u003C? extends E> c)` uses an **upper-bounded** wildcard\nbecause the source collection is a **producer** — `addAll` only **reads** from\n`c` and writes into `this`. That lets you add a collection of any subtype of\n`E`.\n\n```java\nList\u003CNumber> nums = new ArrayList\u003C>();\nList\u003CInteger> ints = List.of(1, 2, 3);\nnums.addAll(ints);     \u002F\u002F ok — Integer extends Number (producer)\n```\n\nWithout `? extends E` you could only pass an exact `Collection\u003CE>`, forcing\ncallers to convert. This is the \"Producer Extends\" half of PECS in the standard\nlibrary.\n",{"id":84,"difficulty":24,"q":85,"a":86},"cant-instantiate-wildcard","Can you use a wildcard when creating an object with new?","**No.** You can't write `new` with a wildcard type — the compiler needs a\nconcrete type argument to know what to construct. Wildcards are for **variable,\nparameter, and field types**, not instantiation.\n\n```java\nList\u003C?> ok = new ArrayList\u003CString>();   \u002F\u002F wildcard on the VARIABLE — fine\nList\u003C?> bad = new ArrayList\u003C?>();        \u002F\u002F compile error — can't instantiate \u003C?>\nvar list = new ArrayList\u003C>();            \u002F\u002F diamond infers \u003CObject>, not a wildcard\n```\n\nThe diamond `\u003C>` is **not** a wildcard — it tells the compiler to *infer* a\nconcrete type from context. A genuine `\u003C?>` has no concrete type to allocate, so\nconstruction is forbidden.\n",{"id":88,"difficulty":24,"q":89,"a":90},"wildcards-in-return-types","Why are wildcards discouraged in return types?","A wildcard in a **return type** leaks into the caller's code: they're forced to\ndeal with `\u003C?>` (read-only, capture errors) even though it gave them no\nflexibility. The advice (Effective Java) is to use wildcards on **parameters**,\nnot returns.\n\n```java\n\u002F\u002F bad: caller now holds a List\u003C?> they can barely use\nstatic List\u003C?> bad() { return new ArrayList\u003CString>(); }\n\n\u002F\u002F good: return a concrete or named type\nstatic \u003CT> List\u003CT> good(T seed) { return new ArrayList\u003C>(); }\n```\n\nIf a method's return type would need a wildcard, that's usually a sign it should\ntake a **type parameter** instead, so the caller gets a usable concrete type.\n",{"id":92,"difficulty":14,"q":93,"a":94},"nested-wildcards","How do nested wildcards like List\u003CList\u003C?>> behave?","Wildcards apply at **each level independently**. `List\u003CList\u003C?>>` is a list whose\nelements are each \"a list of some unknown type\" — and crucially that **outer\nlist is invariant**: it is *not* the same as `List\u003CList\u003CString>>`.\n\n```java\nList\u003CList\u003C?>> outer = new ArrayList\u003C>();\nouter.add(List.of(1, 2));        \u002F\u002F ok — inner is List\u003C? = Integer>\nouter.add(List.of(\"a\"));         \u002F\u002F ok — inner is List\u003C? = String>\n\nList\u003CList\u003CString>> strs = new ArrayList\u003C>();\nList\u003CList\u003C?>> alias = strs;      \u002F\u002F compile error — outer level is invariant\n```\n\nTo accept \"a list of lists of anything\" you need `List\u003C? extends List\u003C?>>` on\nthe outer level too. Mixing levels (`List\u003C? extends List\u003C? extends Number>>`) is\nlegal but a readability red flag.\n",{"id":96,"difficulty":14,"q":97,"a":98},"bounded-wildcard-vs-bounded-param-return","Why does a bounded type parameter, not a wildcard, let you return the element type?","A **wildcard has no name**, so you can't mention it in a return type — the best\nyou could return is `Object` or another wildcard. A **type parameter is named**,\nso it can appear in the return position and flow that exact type back to the\ncaller.\n\n```java\n\u002F\u002F wildcard: can't name the element type to return it\nstatic Number first(List\u003C? extends Number> l) { return l.get(0); } \u002F\u002F only Number\n\n\u002F\u002F type parameter: returns the caller's exact T\nstatic \u003CT extends Number> T firstTyped(List\u003CT> l) { return l.get(0); }\nInteger i = firstTyped(List.of(1, 2)); \u002F\u002F gets Integer back, not just Number\n```\n\nSo when the *output* type must match the *input* element type, a named bounded\ntype parameter is required.\n",{"id":100,"difficulty":14,"q":101,"a":102},"comparator-super-wildcard","Why do sort and Comparator parameters use \u003C? super T>?","A `Comparator\u003C? super T>` lets you sort a `List\u003CT>` with a comparator defined\nfor `T` **or any of its supertypes** — the comparator is a **consumer** of `T`s,\nso PECS says `super`. You shouldn't be forced to write a `T`-specific comparator\nwhen an ancestor's already works.\n\n```java\n\u002F\u002F List.sort signature: void sort(Comparator\u003C? super E> c)\nList\u003CDog> dogs = new ArrayList\u003C>(\u002F* ... *\u002F);\nComparator\u003CAnimal> byAge = Comparator.comparingInt(Animal::age);\ndogs.sort(byAge);     \u002F\u002F ok — a Comparator\u003CAnimal> can compare Dogs (super)\n```\n\nWithout `super` you'd have to duplicate `byAge` as a `Comparator\u003CDog>`. This\n\"Consumer Super\" usage is one of the most common real-world wildcard payoffs.\n",{"id":104,"difficulty":24,"q":105,"a":106},"get-put-principle","What is the get-and-put principle and how does it relate to PECS?","The **get-and-put principle** is the same rule as PECS stated mechanically:\nuse `extends` when you only **get** values out, use `super` when you only\n**put** values in, and use an **exact type** (no wildcard) when you need to do\n**both**.\n\n```java\nList\u003C? extends Number> producer = List.of(1, 2);\nNumber n = producer.get(0);   \u002F\u002F get: ok    | put: forbidden\n\nList\u003C? super Integer> consumer = new ArrayList\u003CNumber>();\nconsumer.add(7);              \u002F\u002F put: ok     | get returns only Object\n\nList\u003CInteger> both = new ArrayList\u003C>();\nboth.add(7); int x = both.get(0); \u002F\u002F exact type: get AND put both work\n```\n\nSo if a method must read *and* write the same element type, drop the wildcard\nand use a concrete type or a named type parameter.\n",21,null,{"description":11},"Java generics wildcards interview questions — unbounded, upper- and lower-bounded wildcards, the PECS principle, bounded type parameters, multiple bounds, and wildcard capture.","java\u002Fgenerics\u002Fwildcards-bounds","Wildcards & Bounded Types","Generics","generics","2026-06-20","Q4MMlXMr2OlzLlAypo6k565_DfRC63kkkhC4vyNUgmM",[118,122,123],{"subtopic":119,"path":120,"order":121},"Generics Basics","\u002Fjava\u002Fgenerics\u002Fgenerics-basics",1,{"subtopic":112,"path":20,"order":12},{"subtopic":124,"path":125,"order":126},"Type Erasure","\u002Fjava\u002Fgenerics\u002Ftype-erasure",3,{"path":128,"title":129},"\u002Fblog\u002Fjava-generics-wildcards-pecs","Java Generics — Wildcards, Bounded Types & the PECS Principle",1782244116066]