I have a very specific problem about the method java.lang.Enum.values().
I would like to override its javadoc. Very precisely, the current javadoc for this is, after I created my own enum:
public static MyClass.MyEnum[] values()
...
This method may be used to iterate over the constants as follows:
for (MyClass.MyEnum c : MyClass.MyEnum.values())
System.out.println(c);
Returns:
...
But in my company System.out calls are considered bad practice so I would like it not to be shown. My first try was to override values() but it is apparently not possible. Is there another way I can do this? Or is the only possibility to update the generated doc ?
I am also curious about why values() is not overridable. I read on other questions that "it is generated by the compiler". But can someone be more precise? It seems that it's generated from the enum's name, but it does not explain why.
values is a static method and is not subject to overriding. You cannot provide your own method to replace the generated one, and this is by specification.
There is no standard mechanism to replace the Javadoc of a method whose source code you don't control, but you could probably mess around with either the build tool, or, if all else fails, the final Javadoc HTML.
I don't think this is possible, but you could file a JDK issue and maybe provide an OpenJDK fix, if you like.
From the Oracle Java Tutorials:
The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.
So, the method values cannot be overridden, since it's a special method created by the compiler. The Eclipse IDE generates this error when you try to do so:
The enum (your enum) already defines the method values() implicitly
Related
Based on the older Java (7) Language Specifications (13.1.7):
Any constructs introduced by a Java compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors, the class initialization method, and the values and valueOf methods of the Enum class.
On newer ones (Java (17) Language Specifications (13.1.7): ) that wording changes to:
A construct emitted by a Java compiler must be marked as synthetic if it does not correspond to a construct declared explicitly or implicitly in source code, unless the emitted construct is a class initialization method (JVMS §2.9).
I wonder how would this apply to the accesor methods created for the components of java Records (JEP 395)
For example
record ARecord(int a){}
would have a method int a() yet there is no code representing such method, according to the wording of the older JLS such method is added by the compiler so I would expect it to be synthetic but its not, as it can be corroborated by running the following 2 lines on JShell
jshell
| Welcome to JShell -- Version 17.0.1
| For an introduction type: /help intro
jshell> record ARecord(int a){}
| created record ARecord
jshell> ARecord.class.getDeclaredMethod("a").isSynthetic();
$2 ==> false
jshell>
The reason I ask is because I would like to use reflection (or any other programmatic mean at runtime) to determine which elements on the class have a matching code structure, basically those have code representing them, meaning:
For the following code
record ARecord(int a){
pubic void someMethod() {}
}
that entity would have 2 methods (a and someMethod), a has no code representing it and someMethod does, I need a way to differentiate those based on that criteria
I wonder if it is because its considered as implicitly declared being its code implicitly defined as part of the component
This is exactly it. Note how the old spec only says that "synthetic" should be marked on constructs that
do not have a corresponding construct in the source code
with the exception of the implicitly declared Enum.values and Enum.valueOf. Back then, those were the only two implicitly declared (in the sense that the new spec uses the phrase) things, apparently. :D
On the other hand, the new spec says
does not correspond to a construct declared explicitly or implicitly in source code
Note that this wording automatically handles the Enum exceptions, but also handles the plethora of implicitly declared things that got added since. This includes record components.
From the Java 17 spec §8.10.3. Record Members,
Furthermore, for each record component, a record class has a method with the same name as the record component and an empty formal parameter list. This method, which is declared explicitly or implicitly, is known as an accessor method.
...
If a record class has a record component for which an accessor method is not declared explicitly, then an accessor method for that record component is declared implicitly [...]
The method a is implicitly declared in your component, therefore it is not synthetic.
Generally speaking (there might be exceptions to this that I don't know of), synthetic constructs are constructs that are not specified by the language spec, but are required for a particular implementation of a compiler to work. The spec is basically saying that such constructs must be marked as "synthetic" in the binary. See some examples here.
Any members of a type that have the synthetic flag on are ignored entirely by javac. Javac acts exactly as if those things don't exist at all.
As a consequence, obviously, the 'getters' you get for a record aren't synthetic. If they were, it would be impossible to call them from .java code - the only way to call them is to write a hacky javac clone that does compile access to synthetics, or to use bytecode manipulation to remove the synthetic flag, or to emit bytecode directly, or to use reflection.
I'm using the "final"-keyword for method-parameters like the "const"-keyword in C/C++ even if it's meaning in JAVA is not 100% the same as in C/C++. I do that mainly to easily distinguish between input- and output-parameters. Like here:
interface Test
{
public void myMethod(final int input1, final float input2, SomeResults output);
}
When I then create an implemention of the interface (or abstract class) and let eclipse generate the overloaded methods eclipse will ommit all "final"-keywords which is really bad. There is an option within the SaveActions-Part of the Java-Editor settings but there I can just enforce eclipse to use "final" everywhere where it is possible which is definitely not my intention. How can I force eclipse to NOT IGNORE my "final"-keywords in interface methods or abstract methods and put them in generated method stubs of implementions and child classes instead?
How can I force eclipse to NOT IGNORE my final keywords in interface methods or abstract methods and put them in generated method stubs of implementations and child classes instead?
I don't think it is possible ... unless you are willing to modify Eclipse.
I am afraid that what you are doing doesn't have any effect.
As stated I use the final keyword only to clarify that a parameter is a "pure input" variable. Regarding that primitives will always be passed by value is known to me.
That is not what final means.
All parameters are "pure input" ... in the sense that they are passed by value. There is no such thing as an "out" parameter in Java.
Conversely, if a parameter's type is a reference type, then declaring it final does not stop the method body from mutating the actual parameter. In other words, it doesn't stop the method body from using the parameter to simulate an "out" parameter.
In Java, declaring a formal parameter as final in an abstract method declarator doesn't have any meaning. It only has meaning if the method declarator is followed by a method body. (Then it means that the variable cannot be assigned to.) Therefore, it would be suspect if a tool (e.g. an Eclipse stub generator) were to place any meaning on the final in the the former context.
My advice would be not to place this unintended (by the Java designers) meaning on final, in either interfaces or in classes. If you want to express "this is not an "out" parameter, either do it in the javadocs, or invent a custom annotation to express it. (In the latter case, you could potentially implement a static checker to ensure that the method body does not mutate the parameter object.)
I need to add new (actually, override existing inherited) method in compiled java class. I can modify the method in superclass by using Instrumentation (#retransformClasses()) and Javassist (#insertAfter()). Unfortunately, that will change the behavior of all subclasses of that superclass but I want only the one particular class to be changed.
I can see Javaassist has #addMethod() functionality (and it actually works) but how to inject the resulting bytecode into JVM?
Both Java.Instrumentation #retransformClasses() and #redefineClasses() methods clearly say in javadocs:
...The redefinition must not add, remove or rename fields or methods...
When I look for the Integer.class file in Eclipse, i can find the getChars Method: https://imgur.com/CPD68sA
But in the official Java Documentation there is no getChars Method: https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html
Why?
Because it's not public. It is only used internally.
If you view the access modifier of getChars method, it is default. Hence we cannot use this method on an instance of Integer.
To list down all the method of a class, you can run javap command:
javap java.lang.Integer
The point of javadoc is to document the public API of a class (in the first place).
You only create javadoc for methods that other classes should be using. The method you are asking about is package protected. We are talking about the java.lang package. You can't add classes to that package, so for all practical purpose, you can regard this method to be private.
Coming from there: you simply shouldn't care about such methods. Studying their content might be nice for educational purposes, but they really do not matter for practical purposes. As they represent implementation details. They are subject to change, and you shouldn't rely on them to exist, or even to do a certain thing.
As we know, in Java, method name is not sufficient to distinguish different methods.
I think (may be wrong), to distinguish a method, it needs the following info:
(className, methodName, methodParameters)
Further,
how to identify a method more efficiently internally?
I heard of "method id". Does it mean there is a mapping between the above triple and an integer, so JVM use only method id after parsing?
If so, is it resided in symbol table?
Thanks!
It's a CONSTANT_NameAndType_info Structure pointing at a method descriptor.
It pretty much consists of the method name, the parameter types, and (somewhat surprisingly) the return type.
I do not understand very well what you are trying to do but I think there are some possible answers nonetheless:
You may be interested in the JNI Method Descriptors, one of the various string formats used internally by the JVM (and by JNI libraries) for identifying Java elements.
It is difficult to know about what you are talking about. The "method id" can be a reference for a java.lang.reflect.Method object, or can be the method descriptor mentioned below, or any other thing. Where did you read about it?
I doubt there is such table inside the JVM. I mean, I doubt there is a global table, because almost always you retrieve a method from a class, even when dealing with it inside the JVM, so it is reasonable to believe the method is stored in the class. It is likewhen we use reflection to retrieve a method:
Class clazz = String.class;
Method method = clazz.getDeclaredMethod("charAt", Integer.TYPE);
System.out.println(method.getName());
Note that I ask the class String for the method, instead of asking some util class to give me the method charAt, which receives an int and is from the class String.
In other words, your identification tuple is almost correct - it just does not have a class:
(methodName, methodParameters)
and, instead of retrieving the method from the JVM passing the class and then the method name and then the parameter types, you retrieve the method directly from the class, giving the class the method name and the parameter types. A subtle difference, for sure, but I think it is what you are wondering about.
This is evident even in the JNI descriptors I mentioned below. For example, the method
long f(int i, Class c);
is represented by the following descriptor:
"(ILjava/lang/Class;)J"
Note that there is no reference to the class of the method.
The excellent documentation on the class file format (already pointed by #Lawence) may give you some insights. I recommend you to read it fully.
1) How to identify a method more efficiently internally?
Internally to what? There are many places where a method might need to be "identified" "internally". In the bytecode compiler, the JIT compiler, the classloader / linker, the classfile representation, reflection API, a debugger and so on. They each have different efficiency concerns.
2) I heard of "method id". Does it mean there is a mapping between the above triple and an integer, so JVM use only method id after parsing?
A method id is used in the classfile representation, and could be used by anything based on that, including the class loader / linker, the JIT compiler and the debugger.
The JVM doesn't parse Java code.
3) If so, is it resided in symbol table?
It might do. It depends on what you mean by "the symbol table". Bear in mind that there are lots of places where method identification is required, throughout the lifecycle of a class. For instance, the Java reflection APIs require method information to implement methods such as getDeclaredMethod(...) and various methods of Method.
Java always differentiate its language elements by their fully qualified names.
Suppose you have a method myMethod(int a, int b) in class MyClass which lies in the package com.mypackage then java will identify the method with the name com.mypackage.MyClass.myMethod(int a , int b).
Just to give you some more insight, it also takes the Class Loader into consideration when there is a need to resolve two identical elements.
It does consider, which class loader was used to load the particular class containing the method to which you are referring. There are four types of class loaders in java. You can read the documention for java.lang.Thread class for this.