When I compile something like this:
public class MyClass
{
void myMethod(String name, String options, String query, String comment)
{
...
}
}
and compile this to a class file, it seems that argument names are lost. That is, when some other Java code references MyClass
and wants to call or overwrite myMethod
, my IDE (currently Eclipse) seems to get this method signature from the class-file:
void myMethod(String arg0, String arg1, String arg2, String arg3);
I know that Eclipse (and possibly other IDEs too) allows me to provide a link to the source or the javadoc (as Bishiboosh pointed out) of MyClass
and can take advantage of this. But I'm curious if there is some way to tell javac
to include the names into the class-file, so that users of that class can see the argument names even if they only have the class file.
When I compile a class with java -g:vars
, the names of parameters are included in the class file. -g:vars
seems to be equivalent to Eclipse -> project properties -> Java compiler -> Add variable attributes to generated class files.
This solution was suggested by several authors, but the answer from Nick finally made me believe.
On my machine, Eclipse sometimes used this info, sometimes it didn't, which was probably my fault or a bug in Eclipse, but not a problem with the class files or the compile. Anyway, now I know that the information is definitely present.
While this works (kind of) fine for classes, it's not working for interfaces.
For me, the logical reason seems to be, that -g:vars only provides the names of local variables, which is what the documentation for javac also states. In the body of a method, it's parameters are very similar to local variables, thus they are covered by -g:vars. interface methods don't have bodies, so they can't have local varibles.
My initial question only asked for classes, because I was not aware that there might be any difference.
As gid pointed out, the class file format does not support storrage of parameter names. I found a section in the class file spec that descibes a data struture which should holf the parameter names of methods, but this is definitely not used when compiling interfaces.
When compiling a class, I can't tell if the mentioned data structure is used, or if Eclipse infers the parameter names from the usage of parameters inside the method body. An expert could clarify this, but it's not that relevant I think.
The reason the parameter names, as you call them, don't match is only one is a parameter. When you call a function you pass it a number of arguments that must match the type and number of parameters a function takes.
By default Java . class files do not store parameter names. To store parameter names in a particular . class file, and thus enable the Reflection API to retrieve parameter names, we need to compile the source file with the -parameters option of the javac compiler.
The parameter types include BOOLEAN, STRING, and INTEGER.
To preserve names in the class file for debugging purposes try project properties, Java compiler, then "Add variable attributes to generated class files" (See Eclipse Help).
Compiling the following source:
public class StackOverflowTest {
public void test(String foo, String bar) {
// blah
}
}
Is decompiled into:
// Compiled from StackOverflowTest.java (version 1.5 : 49.0, super bit)
public class StackOverflowTest {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public StackOverflowTest();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 1]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: StackOverflowTest
// Method descriptor #15 (Ljava/lang/String;Ljava/lang/String;)V
// Stack: 0, Locals: 3
public void test(java.lang.String foo, java.lang.String bar);
0 return
Line numbers:
[pc: 0, line: 4]
Local variable table:
[pc: 0, pc: 1] local: this index: 0 type: StackOverflowTest
[pc: 0, pc: 1] local: foo index: 1 type: java.lang.String
[pc: 0, pc: 1] local: bar index: 2 type: java.lang.String
}
See the parameter names are preserved in the class files.
I would suggest you look into how your source is being compiled, which version it is compiled for etc.
EDIT:
Ah, I see this is different for interfaces - they don't seem to have this information available for the debugger which I guess makes sense. I don't think there'll be a way round this, if you just want to see the parameter names when you're editing source you'll need to go the javadoc route as Nagrom_17 suggests (attach the source).
You don't specially need the source to make arg names appear in Eclipse...If you specify the Javadoc, Eclipse will display the args.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With