After compilation on a platform that discards type arguments, what does a stored container value still record about its argument?
answer
- checked, then thrown away
- the phase matters, not the value
- compile time spends the argument
- value carries the erased shape only
- declarations may describe, values cannot
basics
~20 sNothing you can ask the value for. The argument is spent during compilation, and what runs is an ordinary container over the erased element shape. Only a declaration, never the object it points at, may keep a written description of it.
solid answer
~50 sNothing the value itself can be asked about. The compiler verifies every insertion and every read against the argument written at the declaration site, and then drops it: what the build emits is a container over the **erased element shape** — the placeholder's limit, or the platform's root reference type when nothing restricted it. Two containers built over different arguments therefore have the same run-time shape, and an examiner holding one of them in isolation cannot say which argument produced it. What can survive is a *description* attached to a declaration — the written argument of a field, of a method signature, of a supertype clause — but that description belongs to the declaration, not to the object. On a platform that keeps arguments in full the opposite holds, and the value itself carries them.
code
pseudocode · 13 lines// source, as written
declare container OrderBatch<T>
function first() returns T
batchA = new OrderBatch<PriorityOrder>()
batchB = new OrderBatch<RefundRequest>()
// what an examiner finds after the build
declare container OrderBatch
function first() returns RootType
batchA = new OrderBatch() // same shape
batchB = new OrderBatch() // same shapego deeper
Remember the one-line answer: the argument is checked while the code is compiled and then dropped, so the running value is just a container of the erased shape.
Explain the mechanics: what the erased shape actually is, why two containers over different arguments are indistinguishable, and why a description can sit on a declaration while the object it refers to carries none.
Show the consequence you have lived with: designs that assume a value can be asked what it was built over break on an erasing platform, and the breakage usually appears far from the assumption.
The angle to own is portability: if a house rule allows designs that depend on interrogating a value's argument, that rule quietly binds you to one class of platform, and the cost lands at migration time.
## Two jobs, only one of which reaches run time A parameterized declaration does two separate jobs. The first is **verification**: while the program is compiled, every value put into the container and every value read out of it is checked against the argument written at the declaration site. The second is **representation**: what the emitted artifact actually contains once that verification is finished. On a platform that **discards type arguments**, the first job is complete before the second begins, and the argument has no remaining work to do. It is dropped. So the honest answer to *what does a stored container value still record about its argument* is: **nothing you can ask the value for**. What reaches run time is a container over the **erased element shape** — the placeholder's limit where the declaration restricted it, and the platform's root reference type where it did not. ## What an examiner finds after the build Open the compiled artifact of an order pipeline and look at a handler that was declared over a placeholder: - The **placeholder is gone** from the executable shape; one compiled body serves every argument the source used. - Two pipelines built over different arguments — one over priority orders, one over refund requests — yield values of the **same run-time shape**. Comparing two such values tells you nothing about which argument produced each. - The compiler has inserted **conversions on the caller's side**, at the points where a value coming back through an erased signature is used at its more specific type. - A **description of the original signature may still be attached to the declaration**: the written argument of a field, a method's parameter and return signature, a supertype clause. That description is data recorded about the declaration, not a property of any object. ## Declarations remember; values do not This is the distinction most candidates miss, and it is the one worth saying out loud. A field declared as *list of orders* can keep the words "of orders" in the artifact. The list object that field refers to at run time cannot — it is shaped like every other list. Interrogate the declaration and you may get an answer; interrogate the value and you get the erased shape. An **empty container** is the sharpest illustration. It holds no elements at all, so even an indirect guess from contents is unavailable. And a guess from contents is exactly that — a guess: if a container happens to hold only refund requests, that reports what was *inserted*, not what the declaration *allowed*. A container declared over a wider limit is perfectly entitled to be empty of the narrower kind, or to hold a mix. ## The spread across platforms Platforms do not agree here, and naming which behaviour you are describing is part of a good answer: | What the platform does with the argument | What a value carries at run time | What a declaration carries | |---|---|---| | Discards it | Only the erased shape | Possibly a written description of the signature | | Keeps it in full | The argument itself, per value | The declared signature | | Keeps only a description | Only the erased shape | The description, recorded beside the erased shape | The middle row inverts the whole answer: where arguments are kept in full, two containers built over different arguments genuinely are different values at run time, and "what does this value record" has a real answer. ## Saying it well in an interview 1. Name the **phase** first — the argument is used *during* compilation and dropped *before* the program runs. 2. State what is left: the erased shape, which is the limit or the root reference type. 3. Draw the line between **declaration** and **value**, and offer the empty-container example. 4. Close by saying that platforms differ, and say which behaviour you have been describing. ## The common wrong turn The wrong turn is treating erasure as if the *check* were lost rather than the *record*. Erasure does not weaken the compile-time guarantee: inside code the compiler saw end to end, the contents are exactly what the declaration promised. What is lost is the ability to interrogate that promise later, from inside the running program. Those are different losses, and conflating them produces two bad beliefs — that an erased container is somehow unsafe, and that a wrong element can be quietly slipped in from code the compiler fully checked.
- Two batches are built over different arguments on an erasing platform — can an examiner tell them apart at run time?Not from the values. Both are containers over the same erased element shape, so nothing about either object names its argument. The difference lives at the declaration sites that produced them, and in any description the artifact recorded there. On a platform that keeps arguments in full the answer flips: the two values genuinely differ.
- Does an empty container reveal less about its argument than a populated one?Both reveal nothing, but the empty one makes it obvious. A populated container invites a guess from its contents, and that guess reports what was inserted rather than what the declaration allowed — a batch declared over a wider limit may legitimately hold only one narrow kind, or nothing at all.
- If the argument is gone, what was it for?It was for the compiler. The declared argument is what every insertion and every read is checked against while the program is built, and what lets the caller's code be written without hand-written narrowing. Its job finishes at the end of compilation; only its effects — the accepted program and the inserted conversions — continue into the run.
A parcel is weighed and stamped at the depot before it ships, but the receipt stays in the depot's paperwork, not inside the box. Open the box later and you find contents, never the checking that let them in.
saying these in an interview costs you the question
- Says the container re-checks each element's type as it is read
- Claims the argument can be recovered from the elements present
- Thinks erasure makes checked code unsafe rather than merely uninspectable
- Says containers over different arguments have different run-time shapes
- Confuses a description recorded on a declaration with a property of the value
- Assumes every platform behaves this way after compilation