Recreate a method signature from the descriptor javap prints for it
javap prints every method's descriptor — the class-file encoding of its parameter and return types, where (I)V means void f(int). For the class below, running javap -s -p Descriptors must print exactly the descriptor (Ljava/lang/String;[IJ)Ljava/util/List; for the method pick.
Constraints:
pickispublic staticand lives in the class below- keep the parameter order the descriptor encodes
- the declared return type is
List<String>— generics are erased, so they never appear in a descriptor
import java.util.List;
public final class Descriptors {
// javap -s -p -> descriptor: (Ljava/lang/String;[IJ)Ljava/util/List;
// your code here
}
Write the implementation.
A descriptor lists the parameters in order inside the parentheses and the return type after them, encoding I as int, J as long, a leading [ as an array and Lcom/foo/Bar; as a reference type. So this one is public static List<String> pick(String s, int[] a, long n) — the generic argument is erased. javap -s prints descriptors and -p adds private members.
- ✗Reading the return type before the parentheses instead of after them
- ✗Expecting generic type arguments to show up in a descriptor — they are erased
- ✗Forgetting that
javaphides private members unless-pis passed
- →What does
javap -cshow about a method thatjavap -sdoes not? - →Where does the generic type
List<String>survive inside the class file, if not in the descriptor?
Solution
import java.util.List;
public final class Descriptors {
public static List<String> pick(String s, int[] a, long n) {
return List.of(s);
}
}
javap -s -p Descriptors prints:
public static java.util.List<java.lang.String> pick(java.lang.String, int[], long);
descriptor: (Ljava/lang/String;[IJ)Ljava/util/List;
How to read a descriptor. Inside the parentheses come the parameters in order; after them comes the return type. The single-letter codes are Z boolean, B byte, C char, S short, I int, J long, F float, D double, V void (return only). A reference type is L<internal/name>; and an array is a leading [ before its element type. So Ljava/lang/String; → String, [I → int[], J → long, and the return Ljava/util/List; → List.
Generics do not live in the descriptor — it stores erased types only. The generic List<String> survives in a separate Signature attribute, which is exactly what javap reads to print java.util.List<java.lang.String> on the signature line above the descriptor.
Useful flags: -s prints descriptors, -p includes private members, -c disassembles the bytecode, -v adds the constant pool and stack map tables.