This question already has answers here:
How is an overloaded method chosen when a parameter is the literal null value?
(8 answers)
Closed 7 years ago.
I have this code:
class SuperClass {
int method(Object o){
return 1;
}
int method(String s){
return 2;
}
}
public class PassingNull extends SuperClass {
int method(Object s) {
return 3;
}
public static void main(String... a){
SuperClass sc = new SuperClass();
PassingNull sb = new PassingNull();
SuperClass st = new PassingNull();
System.out.println(sc.method(null)); //1
System.out.println(sb.method(null)); //2
System.out.println(st.method(null)); //3
}
}
I understand that for 1 and 3, it prints '2' because that most specific parameter type is called. But not able to understand why 2 prints '2'.
Basically, for the same reason as cases 1 and 2.
SuperClass has two methods named method, as you know. One of them takes an Object and the other takes a String, and the latter is more specific -- so passing null refers to the second (more specific) method, since null is applicable to both.
Now, PassingNull also has two methods named method. Like before, one overload takes Object (the one that overrides SuperClass::method(Object)), and the other one takes String (the one that's inherited straight from SuperClass). So it's a similar situation, meaning that the type resolution will work similarly: given that both overloads are applicable, the more specific one -- the one that takes String -- is the one that will get invoked.
Related
Preface
I'd like to saying two things:
I don't know how to phrase this question in a few words. So I can't find what I'm looking for when searching (on stackoverflow). Essentially, I apologize if this is a duplicate.
I've only been programming Java consistently for a month or so. So I apologize if I asked an obvious question.
Question
I would like to have a method with a parameter that holds (path to) an integer.
How is such a method implemented in Java code?
Restrictions
The parameter should be generic.
So, when there are multiple of that integer variables, the correct one can be used as argument to the method, when it is called (at runtime).
My Idea as Pseudo-Code
Here's the idea of what I want (in pseudo-code). The idea basically consist of 3 parts:
the method with parameter
the variables holding integer values
the calls of the method with concrete values
(A) Method
.
Following is the definition of my method named hey with generic parameter named pathToAnyInteger of type genericPathToInt:
class main {
method hey(genericPathToInt pathToAnyInteger) {
System.out.println(pathToAnyInteger);
}
}
(B) Multiple Integer Variables
Following are the multiple integer variables (e.g. A and B; each holding an integer):
class A {
myInt = 2;
}
class B {
myInt = 8;
}
(C) Method-calls at runtime
Following is my main-method that gets executed when the program runs. So at runtime the (1) previously defined method hey is called using (2) each of the variables that are holding the different integer values:
class declare {
main() {
hey("hey " + A.myInt);
hey("hey " + B.myInt);
}
}
Expected output
//output
hey 2
hey 8
Personal Remark
Again, sorry if this is a duplicate, and sorry if this is a stupid question. If you need further clarification, I'd be willing to help. Any help is appreciated. And hey, if you're going to be unkind (mostly insults, but implied tone too) in your answer, don't answer, even if you have the solution. Your help isn't wanted. Thanks! :)
Java (since Java 8) contains elements of functional programing which allows for something similiar to what you are looking for. Your hey method could look like this:
void hey(Supplier<Integer> integerSupplier) {
System.out.printl("Hey" + integerSupplier.get());
}
This method declares a parameter that can be "a method call that will return an Integer".
You can call this method and pass it a so called lambda expression, like this:
hey(() -> myObject.getInt());
Or, in some cases, you can use a so called method referrence like :
Hey(myObject::getInt)
In this case both would mean "call the hey method and when it needs an integer, call getInt to retrieve it". The lambda expression would also allow you to reference a field directly, but having fields exposed is considered a bad practise.
If i understood your question correctly, you need to use inheritance to achive what you are looking for.
let's start with creating a hierarchy:
class SuperInteger {
int val;
//additional attributes that you would need.
public SuperInteger(int val) {
this.val = val;
}
public void printValue() {
System.out.println("The Value is :"+this.value);
}
}
class SubIntA extends SuperInteger {
//this inherits "val" and you can add additional unique attributes/behavior to it
public SubIntA(int val) {
super(val);
}
#override
public void printValue() {
System.out.println("A Value is :"+this.value);
}
}
class SubIntB extends SuperInteger {
//this inherits "val" and you can add additional unique attributes/behavior to it
public SubIntB(int val) {
super(val);
}
#override
public void printValue() {
System.out.println("B Value is :"+this.value);
}
}
Now you method Signature can be accepting and parameter of type SuperInteger and while calling the method, you can be passing SubIntA/SuperInteger/SubIntB because Java Implicitly Upcasts for you.
so:
public void testMethod(SuperInteger abc) {
a.val = 3;
a.printValue();
}
can be called from main using:
public static void main(String args[]){
testMethod(new SubIntA(0));
testMethod(new SubIntB(1));
testMethod(new SuperInteger(2));
}
getting an Output like:
A Value is :3
B Value is :3
The Value is :3
Integers in Java are primitive types, which are passed by value. So you don't really pass the "path" to the integer, you pass the actual value. Objects, on the other hand, are passed by reference.
Your pseudo-code would work in Java with a few modifications. The code assumes all classes are in the same package, otherwise you would need to make everything public (or another access modifier depending on the use case).
// First letter of a class name should be uppercase
class MainClass {
// the method takes one parameter of type integer, who we will call inputInteger
// (method-scoped only)
static void hey(int inputInteger) {
System.out.println("hey " + inputInteger);
}
}
class A {
// instance variable
int myInt = 2;
}
class B {
// instance variable
int myInt = 8;
}
class Declare {
public static void main() {
// Instantiate instances of A and B classes
A aObject = new A();
B bObject = new B();
// call the static method
MainClass.hey(aObject.myInt);
MainClass.hey(bObject.myInt);
}
}
//output
hey 2
hey 8
This code first defines the class MainClass, which contains your method hey. I made the method static in order to be able to just call it as MainClass.hey(). If it was not static, you would need to instantiate a MainClass object in the Declare class and then call the method on that object. For example:
...
MainClass mainClassObject = new MainClass();
mainClassObject.hey(aObject.myInt);
...
This question already has an answer here:
why java supports function overloading for primitive data types? [duplicate]
(1 answer)
Closed 5 years ago.
I have a package myPackage which contains 2 classes. First one has 2 public constructors that take a numeric value. First one takes an int and the second one takes Integer. As far as I know they both are the same, just one of them is a primitive type.
When I make an object reference in the other class and run it, in result it calls a constructor that takes the int value.
My question: How it is determined which constructor is called in this case?
P.S. Sorry if this question is too simple. I'm just starting to learn Java.
package myPackage
public class myPackageClass{
public myPackageClass(int var){
System.out.println("Constructor + int value["+var+"]");
}
public myPackageClass(Integer var){
System.out.println("Constructor + Integer value["+var+"]");
}
}
the test file
package myPackage
public class testClass{
public static void main(String ... arg){
myPackageClass var2= new myPackageClass(1);
}
}
}
and the output :" Constructor + int value[1] "
They are not exactly of the same type. 1 is of type int, but new Integer(1) would be of type Integer. So if you would do new myPackageClass(new Integer(1)) the output would be Constructor + Integer value[1]
Other options of passing an Integer instead of int are: new myPackageClass((Integer)1) and new myPackageClass(Integer.valueOf(1))
First it will lookup after one constructor with the same parameter (myPackageClass(int) in your case).
Then, if no constructor is found, then will lookup for one with Box/Unbox parameter ( myPackageClass(Integer) )
You can see the algorithm here : jls-15.12.2
if you create the integer like this : Int i = new Integer(1); The second method will be invoked. If you create the integer like this Interger i = 1; if it is within range -128 ~127 the first method will be invoked else the sencond will be involed. If you use the constrctor directly like this A(1); the first method will be invoked
This question already has answers here:
How is an overloaded method chosen when a parameter is the literal null value?
(8 answers)
Closed 6 years ago.
Which overloaded method will be called for the below method and why?
I executed this code and it calls the overloaded method with List but why does it happen?
public class AmbigiousOverload {
public static void add(Object o) {
System.out.println("Overloaded method with Object.");
}
public static void add(List l) {
System.out.println("Overloaded method with List.");
}
public static void main(String[] args) {
add(null);
}
}
Output: Overloaded method with List.
The List overload is called because the List overload is the most specific matching overload, as all List implementations are subclasses of Object.
From JLS Sec 15.12.2.5:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.
Since any parameter you can pass to add(List) can also be passed to add(Object), add(List) is more specific. As such, given that null can be passed to both, the more specific method is the one chosen.
Note that it wouldn't compile if you had an add(String) overload, since List and String are "equally" specific. (Or any other class: it doesn't have to be String).
This question already has answers here:
How does Java choose which constructor to use?
(2 answers)
Closed 6 years ago.
I have a Java class where there are two parameterized constructors
public class TestApplication {
TestApplication(Object o)
{
System.out.println("Object");
}
TestApplication(double[] darray)
{
System.out.println("Array");
}
public static void main(String[] args)
{
new TestApplication(null);
}
}
When I run this program I get output as "Array". Why does the Object constructor not run?
Constructor overloading resolution behaves the same as method overloading resolution. When two constructors match the passed parameter, the one with the more specific argument types is chosen.
null can be assigned to both a double[] and an Object, since both are reference types, but an array is a more specific type than Object (since arrays are sub-classes of the Object class), so new TestApplication(null) triggers the TestApplication(double[] darray) constructor.
This question already has answers here:
Method overloading and choosing the most specific type
(9 answers)
Closed 8 years ago.
class Test {
public Test(Object obj) {
System.out.println("Object");
}
public Test(String s) {
System.out.println("String");
}
public static void main(String[] args) {
new Test(null); //prints String. Why not Object?
}
}
If I add another constructor with argument of type Integer ,or, for that matter any other type, calling new Test(null); results in compilation error - The constructor Test(Object) is ambiguous. Why no error is generated for the above example? On executing it, constructor with argument String is called. Why constructor with argument type Object is not called? How this ambiguity is resolved?
//prints String. Why not Object?
Because compiler choose most specific type.
If I add another constructor with argument of type Integer ,or, for
that matter any other type, calling new Test(null); results in
compilation error - The constructor Test(Object) is ambiguous.
Now String and Integer are in the same level in the object hierarchy, So, compiler can't choose one out of those two
Because it is determined by the most specific type of the parameter.
Since String is subclass of Object, and null is subtype of anything, then the second constructor is called, because String is more specific than Object.
Compiler is designed to pick up the overloaded method that very closely matches the Value sent in parameter.