5

I have got a constructor which takes 4 parameters: String, Object, Object, MyEnum.

public MyClass(String name, Object val1, Object val2, MyEnum cat) { 
// find in usage = 202
    this.name = name;
    this.val1 = val1;
    this.val2 = val2;
    this.cat = cat;
}

In 95% usage cases last parameter is null, so I would like to create another constructor which takes only 3 parameters and sets last one as a null.

Some ideas came to my mind but finally I gave a try to the following solution:

  1. Change last parameter from MyEnum to Integer (compilation error - does not matter): public MyClass(String name, Object val1, Object val2, Integer cat) - still 202 find usage

  2. Add new constructor with last parameter of type Object: public MyClass(String name, Object val1, Object val2, Object cat) and now first constructor (with Integer) has 196 usages and second one 6.

This is exactly what I wanted (I have got exactly 6 invocations with non null last element) but what is the reason of this behaviour? Does Intellij make some checks and if input type is MyEnum it cannot be passed as an Integer type, but null can be passed to both, so why in case of first constructor there is 6 less results?

When I changed from Object to String (now I have 2 constructors with String and Integer) both give me 0 when I run find usage.

Thank you for the explanation of this behaviour.

ruhungry
  • 4,506
  • 20
  • 54
  • 98
  • 1
    Are you asking about Java's [rules for overloading](https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.9)? Or are you trying to describe some way that the "Find usages" in IDEA isn't matching what Java actually does? –  Jul 22 '16 at 15:04
  • I only want to understand how IDEA chooses results of Find Usage in the scenario I posted. – ruhungry Jul 22 '16 at 19:01

2 Answers2

1

If you have both myMethod(Integer a) and myMethod(Object a), a call to myMethod(null) will call the Integer version, because it is more specific. Similarly, if you had just myMethod(MyEnum a) and myMethod(Object a), the MyEnum version would be called if passed a null argument. (See this answer about null overloads, which references section 15.12.2.5 of the Java Language Specification.) There's really no difference in how it's behaving based on whether it's Integer or MyEnum; both are more specific than Object, so that's the overload being selected.

When you ask IntelliJ IDEA to find usages of a method, it uses its own index of your code and its knowledge about how Java handles overload resolution to find all cases where that method would get called. While these rules can be somewhat complicated (looking at all that detail in the Java Language Specification makes my eyes hurt too), and it's conceivable that there's some use case where IDEA would get it wrong and see something differently than the way the Java compiler and runtime would, in this case it looks to be getting it right. It's a handy way to play with it and understand and test how overload resolution works.

Community
  • 1
  • 1
0

This isn't really an IntelliJ question but a java constructor chaining question.

If there is a high chance the cat is null you should have the following two constructors:

public MyClass(String name, Object val1, Object val2) { 
    this(name,  val1, val2, null)
}

public MyClass(String name, Object val1, Object val2, MyEnum cat) { 
    this.name = name;
    this.val1 = val1;
    this.val2 = val2;
    this.cat = cat;
}
UserF40
  • 3,533
  • 2
  • 23
  • 34