Varargs and argument less method - java

I am just catching up with java 1.5, (yes i know its too early;) ) . while trying out few exercises on varargs , i just found something strange as below. the code compiles well and the varargs method is invoked only when i supply atleast one parameter. shouldn't this have been compiler error, a method and overloaded method with varargs. Or is there any specific usecase you may think, this scenario will
be useful
public class VarargsExample {
public static void main(String args[]) {
test1();
}
public static void test1(int... x) {
System.out.println("AssertionExample.test1(ARRAY METHOD)");
}
public static void test1() {
System.out.println("AssertionExample.test1(PARAM LESS)");
}
}
PS: tried to search this in SO, could not find similar one. pardon me if there is one already:)
Summary, thanks all for your quick responses. seems to be the normal methods are the one preferred. Same is the case when a single param method is present as below
public class VarargsExample{
public static void main( String args[] ){
test1();
test1(2);
}
public static void test1(int... x){
System.out.println("AssertionExample.test1(ARRAY METHOD)");
}
public static void test1(int x){
System.out.println("AssertionExample.test1(single param METHOD)");
}
public static void test1(){
System.out.println("AssertionExample.test1(PARAM LESS)");
}
}

First of call, the parameter-less overloading gets called because its signature is more specific than that of the overlauding with varargs. It is in general a very bad idea to have two overloaded methods which perform a completely different operation. So let's assume that the parameter-less method does the same thing as the varargs method when called without arguments, that is, the parameter-less method is a specialization of the varargs method.
Then a use-case is the following. Calling a varargs method always requires creating an array. Although, certainly at first, I wouldn't think about such minor optimizations too much, but it is an overhead which might, in some cases (for example in tight loop), be considerable enough. The parameter-less version of the method does not require creating an array, and additionally also may contain other optimizations for the specific case.
Sometimes, one sees more than one specializations, one with no arguments, one with one, one with two, and a general method. For example:
void doSomething() { ... }
void doSomething(String a1) { ... }
void doSomething(String a1, String a2) { ... }
void doSomething(String... as) { ... }
But I suggest to only do this in a late stage of development, if at all.

Related

Weird behavior when overloading using variable arguments with primitive types in java

Clearly I've not enough knowledge of how overloading, autoboxing and variable arguments work.
So here's the program causing trouble whenever there's an involvement of primitive types.
public static void z(int a, Object...objects){
}
public static void z(Object...objects){
}
public static void main(String[] args) {
z(); // no error
z(4); // Compile time Error : Ambiguous
z2(); // No error
z2(true, "sadas"); // Error
// No problem with reference types
z3(); // No error. String one called
z3(5); // No error. Object one called
z4(); // Error
z4(4); // Error
z4("asdas"); // Working properly
}
public static void z2(boolean b, Object...objects){
}
public static void z2(Object...objects){
}
public static void z3(String...objects){
System.out.println("String one called");
}
public static void z3(Object...objects){
System.out.println("Object one called");
}
public static void z4(int...objects){
System.out.println("int z4 called");
}
public static void z4(Object...objects){
System.out.println("Object z4 called");
}
Can anybody explain why any of this is happening? I can happily use Integer, Boolean instead of int, boolean but would very much like to know internal working behind it.
A method call will not compile if the compiler cannot determine which of the overloaded method variants it should use.
Let's use z4 as an example:
The method call z4() fits the signature of both variants.
The method call z4(4) also fits the signature of both variants because the variable can be auto-boxed.
The method call z4("asdas") is not ambiguous, as String cannot be cast to int.
Update: the rules for resolving overloaded method calls are as follows:
The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.
...
The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.
...
The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.
If more than one variant is selected in the same phase, then the most specific one is chosen,* but in short z3(String...) is more specific than z3(Object...), while z4(int...) and z4(Object...) are equally specific.
*The rules for determining this most specific variant are somewhat complicated (see here)
Thats a fab question
Now consider
public static void z2(boolean b, Object... objects) {
}
public static void z2(Object... objects) {
}
Both methods have a vararg argument, which means they will both be considered on the third and final phase of overloading resolution.
Remember Object class is the mother of all objects in java
Well this explains one thing
The compiler can treat both as object which will result in object array again.
Now finally
void z2(boolean b, Object... objects)
public static void z2(Object... objects)
is treated as same function.
To check you can comment
z2(true);
z2(true, "sadas");
removing either of
public static void z2(boolean b, Object... objects) {
}
Or
public static void z2(Object... objects) {
}
This will work.
But
You have taken object inside parameter
If you are specific for example
public static void z2(boolean b, String... objects) {
}
public static void z2(String... objects) {
}
z2(); // No error
z2(true, "sadas"); // No error
This way it can be resolved

Java overloading: reference to call ambiguous

Consider the following example code:
public class TestClass {
public void doSth(String str, String l, Object... objects) {
System.out.println("A");
}
public void doSth(String str, Object... objects) {
System.out.println("B");
}
}
When I now call new TestClass().doSth("foo", "bar") I get the expected result A. But if I change the method signature of the first method by chaging the parameter l to a primitive type:
public class TestClass {
public void doSth(String str, long l, Object... objects) {
System.out.println("A");
}
public void doSth(String str, Object... objects) {
System.out.println("B");
}
}
calling new TestClass().doSth("foo", 2L) will yield a reference to call ambiguous compile time error.
I thought about that one for some time now and also consulted this stackoverflow question, but I was unable to understand why this happens. In my opinion the doSth("foo", 2L) is more specific to the doSth(String string, long l, Object... obj) signature and should allow the compiler to also come to this conclusion.
In this case, auto-boxing is causing you grief. Ironically, before that you're correct - the "long" version would have easily been picked.
Basically the compiler knows that it can create a Long from your value which, of course, is an Object. So it is still confused as either the long or the Long version could be used. Is one "better" than the other? Maybe but it is a pretty fine line.
At this state, I can only report my observation, not the exact argumentation as to WHY Java behaves, like it does.
First, changing the methods to
void doSth(long l) {...}
void doSth(Object o) {...}
gets rid of the problem, i.e. doSth(2L); will yield the expected result.
Going one step further, changing the method parameter to varargs
void doSth(long... ls) {...}
void doSth(Object... os) {...}
together with the call doSth(2l); yields the same compilation error as reported by OP.
My suggestion at this stage is that encapusalting the parameter into an array, together with Autoboxing causes the havoc. My knowledge about the JLS is not firm enough to explain this properly.

Init block VS init() private method called in constructor

I know there are several ways to initialize stuff at instance creation in Java, but I'm interested in the difference between the following 2 possibilities.
Case 1:
{
// common init code for all constructors
}
public MyType() {
super();
// specific init code
}
public MyType(Object arg) {
super(arg);
// specific init code
}
Case 2:
public MyType() {
super();
init();
// specific init code
}
public MyType(Object arg) {
super(arg);
init();
// specific init code
}
private void init() {
// common init code for all constructors
}
I believe these 2 cases are equivalent in terms of code. I think the first is faster because there is 1 less method call, but on the other hand it might be confusing for someone who is not very knowledgeable about initialization.
Is there another difference that I have missed that could lead us to choose one over the other? Which option should I use preferably?
Note: the init() method is private, and I know a different visibility could lead to initialization bugs (when subclassing), this is not the point.
Maybe the first is faster because there is 1 less method call, but I think it is less readable.
I wouldn't even consider efficiency here as it would make just a minor difference of method call. But why do you think it is less readable? It's a well known feature of Java language.
Which option should I use preferably?
The benefit of first approach is, you've to write less code. And there is slight chance of human error in second approach. Generally you would use instance initializer block when you want the initialization to be done in every constructor. That saves you from explicitly writing same code in all constructor. With the other approach, you have to remember to invoke init() method from all the constructors.
But if you want some initialization to be part of some constructor, then the second approach might be useful. But that is very rare IMO.
In short, init code in first case will be called before constructor, in second - after.
Check out this question.
General rule is to avoid constructions like theese and use static-factory-methods instead.
Order might matter then calling this() instead of super():
Consider code:
public class InitOrderTest {
static class Super {
Super() {
System.out.println("Super constructor");
}
}
static class Puper extends Super {
{
System.out.println("Code block");
}
Puper() {
this("Self constructor");
init();
}
public Puper(String inner) {
System.out.println(inner);
}
private void init() {
System.out.println("Init call");
}
}
public static void main(String[] args) {
new Puper();
}
}
It prints:
Super constructor
Code block
Self constructor
Init call

Verify that overriden superclass method is called when invoking this method on subclass

I'll show my problem using this example:
I have a class with a method foo. That class has a subclass which overrides this method.
Subclass' method calls superclass' method. Can I verify that?
I don't want to test what foo in superclass does. I just need to verify that it was called.
I know that refactoring could help (favour composition over inheritance, etc) but I am unable to do that.
Is there any way to achieve what I need?
Below is simple example of what I've tried
package tmp;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.times;
public class Example {
#Test
public void test() {
// given
ChildClass childClass = new ChildClass();
ChildClass spyChildClass = Mockito.spy(childClass);
// when
spyChildClass.foo(100);
// then
Mockito.verify((BaseClass) spyChildClass, times(1)).foo(101);
}
}
abstract class BaseClass {
public void foo(int n) {
System.out.printf("BaseClass.foo(%d)%n", n);
}
}
class ChildClass extends BaseClass {
#Override
public void foo(int n) {
System.out.printf("ChildClass.foo(%d)%n", n);
super.foo(n + 1);
}
}
And this is the result:
ChildClass.foo(100)
BaseClass.foo(101)
Argument(s) are different! Wanted:
childClass.foo(101);
-> at tmp.Example.test(Example.java:19)
Actual invocation has different arguments:
childClass.foo(100);
-> at tmp.Example.test(Example.java:16)
Expected :childClass.foo(101);
Actual :childClass.foo(100);
<Click to see difference>
Obviously it's not what I wanted to see.
I can't modify BaseClass. I don't want to test BaseClass (I am not responsible for it). I don't even neet to know what exactly it does. I just need to verify that its method was called. Wnything else is not my problem. Its the problem of people who maintain BaseClass.
Test the behaviour of the class, not it's implementation.
Write the test such that the method is called and is expected to do something. Next check the object now represents what you now expect it to represent.
If BaseClass.foo is expected to increment some counter by 100, yet Subclass.foo increments some counter by 50 then calls the superclass, verify that the counter is now 150 and not just 50.
Don't peek the how - they may change over time. Do test the behaviour. The method foo may do other things besides increase counters - check the state of the object not what it did.
Possible solution: Make foo final, and decree that subclasses need to override some other method, the implementation of foo, instead of the actual foo.
abstract class BaseClass {
private boolean myFooCalled;
public final void foo(int n) {
myFooCalled = false;
fooImpl(int n);
if (!myFooCalled) { ... }
}
public void fooImpl(int n) {
myFooCalled = true;
System.out.printf("BaseClass.foo(%d)%n", n);
}
}
Notes: This is off the top of my head, so (1) I haven't tested it, (2) I'm not sure if this is what you really want, (3) I'm not sure whether your design ought to be improved. This is a general answer about "how you could make sure an overriding method calls the superclass method", not an answer tailored to your purposes.
I hesitate to give this answer because everyone here (including the OP) knows you can do this... but to answer the OP's question you can do this:
Instead of having
#Override
public void reset() throws IOException{
// ...
super.reset();
}
do this:
#Override
public void reset() throws IOException{
// ...
callSuperReset();
}
void callSuperReset() throws IOException {
super.reset();
}
... and verify that callSuperReset was indeed called...
I am a mocking newb (no doubt it shows), and I thought for a long time the command was simply "Thou shalt not create methods just to suit your tests".
But in a previous question of mine, davidxxx in his answer says
In fact I would say rather : "thou shalt not create methods to suit
your tests and that open the API of the application in an undesirable
way"
Given that this method callSuperReset is package-private, is there any problem in principle with it? (other than its total inelegance)
Yes, such a test can be written. And there is nothing wrong with wanting to do it, provided what you are testing is the contract of an API, not its implementation.
Here is a test for the contrived example in the question, using the JMockit mocking API:
#Test
public void subclassShouldObeyContractOfBaseClass(
#Mocked final BaseClass anyBaseInstance)
{
new ChildClass().foo(123);
new Verifications() {{ anyBaseInstance.foo(anyInt); }};
}
If necessary (as dictated by the contract of BaseClass#foo(int)), the test could also verify the argument value passed to the base method as being n + 1 (or whatever).

Find out which method called me

I'm tring to find out a way to get the complete method signature that is calling me.
For example:
public class Called {
public void whoCallMe() {
System.out.println("Caller Method: " + new Throwable().getStackTrace()[1].getMethodName());
}
}
public class Caller {
public static void run(int i) {
new Called().whoCallMe();
}
public static void run(String str) {
new Called().whoCallMe();
}
public static void run(boolean b) {
new Called().whoCallMe();
}
/** MAIN **/
public static void main(String[] args) {
run("hi");
}
The way I've implemented whoCallMe() method I can see that run method called it, but since I 3 overloads I can't say which one was the caller cause whoCallme return only "run" as the method name.
Do you guys know other way where I could get the complete method signature like run(java.lang.String) ?
You can use AspectJ to create an aspect which will apply to every method invocation and add the details about the method being invoked to a per-thread stack, and then remove it after method completes. It's going to be insanely expensive, of course. Most likely you don't want to do that. Also you don't want to throw anything to find out who called you.
Basically the answer to your question is: do not do it.
Explain why you think you want to do it and somebody will give you a good alternative.
Also, come to think of it, you can argue that method overloading (not overriding!) is considered harmful. Do you really need multiple different methods with different arguments and the same name?

Categories