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.)
Related
Preface
I have been experimenting with ByteBuddy and ASM, but I am still a beginner in ASM and between beginner and advanced in ByteBuddy. This question is about ByteBuddy and about JVM bytecode limitations in general.
Situation
I had the idea of creating global mocks for testing by instrumenting constructors in such a way that instructions like these are inserted at the beginning of each constructor:
if (GlobalMockRegistry.isMock(getClass()))
return;
FYI, the GlobalMockRegistry basically wraps a Set<Class<?>> and if that set contains a certain class, then isMock(Class<?>> clazz) would return true. The advantage of that concept is that I can (de)activate global mocking for each class during runtime because if multiple tests run in the same JVM process, one test might need a certain global mock, the next one might not.
What the if(...) return; instructions above want to achieve is that if mocking is active, the constructor should not do anything:
no this() or super() calls, → update: impossible
no field initialisations, → update: possible
no other side effects. → update: might be possible, see my update below
The result would be an object with uninitialised fields that did not create any (possibly expensive) side effects such as resource allocation (database connection, file creation, you name it). Why would I want that? Could I not just create an instance with Objenesis and be happy? Not if I want a global mock, i.e. mock objects I cannot inject because they are created somewhere inside methods or field initialisers I do not have control over. Please do not worry about what method calls on such an object would do if its instance fields are not properly initialised. Just assume I have instrumented the methods to return stub results, too. I know how to do that already, the problem are only constructors in the context of this question.
Questions / problems
Now if I try to simulate the desired result in Java source code, I meet the following limitations:
I cannot insert any code before this() or super(). I could mitigate that by also instrumenting the super class hierarchy with the same if(...) return;, but would like to know if I could in theory use ASM to insert my code before this() or super() using a method visitor. Or would the byte code of the instrumented class somehow be verified during loading or retransformation and then rejected because the byte code is "illegal"? I would like to know before I start learning ASM because I want to avoid wasting time for an idea which is not feasible.
If the class contains final instance fields, I also cannot enter a return before all of those fields have been initialised in the constructor. That might happen at the very end of a complex constructor which performs lots of side effects before actually initialising the last field. So the question is similar to the previous one: Can I use ASM to insert my if(...) return; before any fields (including final ones) are initialised and produce a valid class which I could not produce using javac and will not be rejected when loaded or retransformed?
BTW, if it is relevant, we are talking about Java 8+, i.e. at the time of writing this that would be Java versions 8 to 14.
If anything about this question is unclear, please do not hesitate to ask follow-up questions, so I can improve it.
Update after discussing Antimony's answer
I think this approach could work and avoid side effects, calling the constructor chain but avoiding any side effects and resulting in a newly initialised instance with all fields empty (null, 0, false):
In order to avoid calling this.getClass(), I need to hard-code the mock target's class name directly into all constructors up the parent chain. I.e. if two "global mock" target classes have the same parent class(es), multiple of the following if blocks would be woven into each corresponding parent class, one for each hard-coded child class name.
In order to avoid any side effects from objects being created or methods being called, I need to call a super constructor myself, using null/zero/false values for each argument. That would not matter because the next parent class up the chain would have a similar code block so that the arguments given do not matter anyway.
// Avoid accessing 'this.getClass()'
if (GlobalMockRegistry.isMock(Sub.class)) {
// Identify and call any parent class constructor, ideally a default constructor.
// If none exists, call another one using default values like null, 0, false.
// In the class derived from Object, just call 'Object.<init>'.
super(null, 0, false);
return;
}
// Here follows the original byte code, i.e. the normal super/this call and
// everything else the original constructor does.
Note to myself: Antimony's answer explains "uninitialised this" very nicely. Another related answer can be found here.
Next update after evaluating my new idea
I managed to validate my new idea with a proof of concept. As my JVM byte code knowledge is too limited and I am not used to the way of thinking it requires (stack frames, local variable tables, "reverse" logic of first pushing/popping variables, then applying an operation on them, not being able to easily debug), I just implemented it in Javassist instead of ASM, which in comparison was a breeze after failing miserably with ASM after hours of trial & error.
I can take it from here and I want to thank user Antimony for his very instructive answer + comments. I do know that theoretically the same solution could be implemented using ASM, but it would be exceedingly difficult in comparison because its API is too low level for the task at hand. ByteBuddy's API is too high level, Javassist was just right for me in order to get quick results (and easily maintainable Java code) in this case.
Yes and no. Java bytecode is much less restrictive than Java (source) in this regard. You can put any bytecode you want before the constructor call, as long as you don't actually access the uninitialized object. (The only operations allowed on an uninitialized this value are calling a constructor, setting private fields declared in the same class, and comparing it against null).
Bytecode is also more flexible in where and how you make the constructor call. For example, you can call one of two different constructors in an if statement, or you can wrap the super constructor call in a "try block", both things that are impossible at the Java language level.
Apart from not accessing the uninitialized this value, the only restriction* is that the object has to be definitely initialized along any path that returns from the constructor call. This means the only way to avoid initializing the object is to throw an exception. While being much laxer than Java itself, the rules for Java bytecode were still very deliberately constructed so it is impossible to observe uninitialized objects. In general, Java bytecode is still required to be memory safe and type safe, just with a much looser type system than Java itself. Historically, Java applets were designed to run untrusted code in the JVM, so any method of bypassing these restrictions was a security vulnerability.
* The above is talking about traditional bytecode verification, as that is what I am most familiar with. I believe stackmap verification behaves similarly though, barring implementation bugs in some versions of Java.
P.S. Technically, Java can have code execute before the constructor call. If you pass arguments to the constructor, those expressions are evaluated first, and hence the ability to place bytecode before the constructor call is required in order to compile Java code. Likewise, the ability to set private fields declared in the same class is used to set synthetic variables that arise from the compilation of nested classes.
If the class contains final instance fields, I also cannot enter a return before all of those fields have been initialised in the constructor.
This, however, is eminently possible. The only restriction is that you call some constructor or superconstructor on the uninitialized this value. (Since all constructors recursively have this restriction, this will ultimately result in java.lang.Object's constructor being called). However, the JVM doesn't care what happens after that. In particular, it only cares that the fields have some well typed value, even if it is the default value (null for objects, 0 for ints, etc.) So there is no need to execute the field initializers to give them a meaningful value.
Is there any other way to get the type to be instantiated other than this.getClass() from a super class constructor?
Not as far as I am aware. There's no special opcode for magically getting the Class associated with a given value. Foo.class is just syntactic sugar which is handled by the Java compiler.
I've read today about the Java 8 release. But I don't understand fully the concept of reference methods in Java 8. Does this mean that Java now has the support of functions as first class objects? I have seen, how to construct a reference to function. But it seems to me, that the Converter object they provide has quite limited functionality. Is it now possible in Java:
to pass the function as the argument to another function?
to return the function as the return value from another function?
and what about closures? Are they implemented fully like in functional languages, or they do have some limitations? It seems to me that there are some limitations (you cannot change the value of the variable you reference in a closure, it must be marked as final and etc).
The most important aspects of first-class functions have been blended into the existing Java type system. No true function type has been introduced; any single-method interface is its own "function type". So, as for your first two questions, you can freely pass around instances of such functional interfaces.
There are many subtle changes to the semantics, which allow one to use lambda syntax/method references to implement any such interface. You can even use higher-order functions such as compose, which returns a generic Function type, and pass it to a method which expects a compatible functional interface type.
you cannot change the value of the variable you reference in a closure
This is not a limitation specific to Java. In fact, most FP languages don't support mutable variables of any kind. Note that there is no requirement to use the final keyword on the variable; the concept of effectively final takes care of that.
It is possible. How do you do it?
First construct a "Functional Interface" (or use one of the provided ones). A functional interface is an interface with a single method. java.lang.Runnable is an example.
Second, write a method that takes a functional interface as a parameter.
public void doAThing(Runnable r) {
r.run();
}
Third, write a method with the correct signature.
public class MyClass {
public void runAThing() {
System.out.println("I executed!");
}
}
Fourth, call the function passing in a method reference.
MyClass mc = new MyClass();
doAThing(mc::runAThing);
You'll note that none of the classes you've wrote ever explicitly implements Runnable. This is handled for you by the compiler.
You can do something similar using a lamdba expression:
doAThing(() -> System.out.println("I executed as a lamdba expression!"));
To return the function as a value from another function, just return an instance of Runnable.
Methods are not first class objecs in Java, apart from the already existing usage in reflection, to answer your questions:
Yes, you can pass it on, but it needs to satisfy the signature.
For a void method() you use a Runnable, like this:
Runnable method = this::method if it is in the same class, and then run the actual method with method.run().
However for a double method() you need to use a DoubleSupplier, like this:
DoubleSupplier method = this::method, and then use it as double d = method.get().
And many more signatures, and you can even define your own with Functional Interfaces.
Yes it is possible, but only specific signatures as shown in Point 1.
Lambdas behave exactly as anonymous inner classes, which are closures by itself, Java has had support for closures since they introduced anonymous inner classes. The only thing that is added now is that the syntax is much prettier.
No, not first class functions. Lambda expression are wrapped in a interface, and some syntatic sugar applied for brevity.
But you can;t create a function on its own and pass it around different methods, whether thats a key point or not is a different question.
Since a static function call is translated into a static invocation bytecode regardless of how the definition exists... is there some way to force a caller of a static function to compile successfully even when the target function and class don't exist yet?
I want to be able to compile calls to functions that don't exist yet. I need to tell the compiler to trust me that at runtime, I'll have them properly defined and in the classpath so go ahead and compile it for now.
Is there a way to do this?
Reflectively yes, but not via a regular call.
The call requires an entry in the string pool that includes the method name and parameter types so the compiler needs to be able to decide on a signature for the method.
invokestatic <method-spec>
<method-spec> is a method specification. It is a single token made up of three parts: a classname, a methodname and a descriptor. e.g.
java/lang/System/exit(I)V
is the method called "exit" in the class called "java.lang.System", and it has the descriptor "(I)V" (i.e. it takes an integer argument and returns no result).
Consider
AClass.aStaticMethod(42)
Without knowing anything about AClass, it could be a call to any of
AClass.aStaticMethod(int)
AClass.aStaticMethod(int...)
AClass.aStaticMethod(long)
AClass.aStaticMethod(long...)
ditto for float and double
AClass.aStaticMethod(Integer)
AClass.aStaticMethod(Number)
AClass.aStaticMethod(Comparable<? extends Integer>)
AClass.aStaticMethod(Object)
AClass.aStaticMethod(Serializable)
and probably a few others that I've missed.
... is there some way to force a caller of a static function to compile successfully even when the target function and class don't exist yet?
No. When compiling a method call, the compiler needs to check that the name, argument types, result type, exceptions and so on of the called method. Since you are asking about a static method, this information can only defined in one place ... the class that declares the static method. There is no work-around for this if you want static type-safety.
I need to tell the compiler to trust me that at runtime ...
It is not that simple:
You haven't told the compiler what the method signature should be. The compiler needs to be told, because is not possible to accurately infer the signature from the call.
The Java platform is designed to be robust, and "just trust me" could lead to catastrophic runtime failures.
If you are willing to sacrifice compile-time type safety and eschew the convenience / simplicity / readability of statically typed code, then reflection is an option. But I can't think of any other options that would work.
No, but you could declare interfaces that have the methods and code against them, then use the Abstract Factory pattern to provide implementations at runtime.
Dependency Injection use this approach.
Someone told me:
If you are using Eclipse and don't see any blue words (i.e. member variables) in your methods, then those methods should really be static methods, as long as the parameters (if there are any) are primitive types, or (in the case of object references) are immutable and/or thread-safe.
Is there any other criteria that a Java developer should consider when deciding whether an instance method should really be a static method instead?
Put it simply, if it is pure "helper/function" which does not modify internal state of object, it's good candidate for static method.
... unless you plan to subclass and override the method.
as long as the parameters (if there are any) are primitive types, or (in the case of object references) are immutable and/or thread-safe.
I don't see why that is relevant. Any thread-safety considerations are exactly the same whether you make the method static or not. A static method with only immutable parameters (that also does not mess with static fields of the class) is thread-safe. If the parameters are not immutable and the method changes them and this becomes un-thread-safe, then making this an instance method won't help at all.
If you don't need an instance of an object to call the method it should be static. That is: If you only work with the parameters and no members of an object. Usually those are collected in utility or helper classes that are never instantiated (secure by declaring a private default constructor).
ps: concerning "blue words": You should always use the this. to access member variables and not count on your IDE as the code becomes quite unreadable once you use a simple viewer/editor.
Any function which you plan to use in a global way for all your instances can be made static
what difference does it make in a Java Interface to declare the method signature as final and non-final?
int setName(String name);
int setName(final String name);
Section 8.4.1 of the Java Language specification allows the parameters in any method declaration (and that includes the ones in interfaces) to be declared final. However, since this does not influence the method's signature, declaring a parameter of an abstract function as final has no effect. Since all methods in an interface are implicitely abstract, both variants are equivalent.
The most complete answer I could find on google is this one.
It's nice they mention the link with using anonymous inner classes as it's a strong use case for final parameters.
Regards,
Stéphane
A couple of incidental differences
It can be used by the IDE as a hint. e.g. when you get the IDE to auto-generate your implemented methods, it will make the parameters final by default in the same way it will re-use the same parameter names even though these are not part of the signature either.
the modifier final is available via reflection and could be used by a framework for some implied purpose.