How does Java decide which constructor to call in below program?
public class Test
{
Test(int a, int b)
{
System.out.println("a = "+a+" b = "+b);
}
Test(int a, float b)
{
System.out.println("a = "+a+" b = "+b);
}
public static void main (String args[])
{
byte a = 10;
byte b = 15;
Test test = new Test(a,b);
}
}
The the first constructor taking second parameter as int is called, but if I remove first constructor, then the other constructor is called. In case both constructors are there, why the first one is called?
In the first case both byte arguments are widened to int, and this is preferable to converting one argument to float.
In the second case there's no constructor taking two ints, so the only possible choice involves the conversion.
The language definition document contains an exhaustive discussion of constructor resolution.
Related
I'm taking those first steps from python to java and here is my first of many Java questions do doubt.
When printing via a shortened print method, I'm running into a problem with the return value from a inherited class. I'm sure it's something simple about Java I don't get yet. I'm also trying to convert any integers the println method receives to a string with .tostring(), but I'm not sure if that is correct.
class Inheritance {
private static void println (Object line){
System.out.println(line.toString());
}
static class A {
public int multiply(int a, int b){
int val = a*b;
return val;
}
}
static class B extends A {
public int multiply(int a, int b) {
int val = a * b * 5;
return val;
}
}
public static void main(String[] args) {
B b_class = new B();
b_class.multiply(3,4);
println(b_class);
println("Hello World");
}
}
The output is as follows:
Inheritance$B#74a14482
Hello World
You can just use the method inside println
public static void main(String[] args) {
B b_class = new B();
println(Integer.ToString(b_class.multiply(3,4)));
println("Hello World");
}
For Java toString method default it will
returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()
so when you println b_class it will print: Inheritance$B#74a14482.
For your println (Object line) it's receiving Reference type(Object) to println, but as multiply method it's return a primitive type(int), it's not an object, you need to convert it to an Object for println method, as #StanteyS's answer, use Integer.toString can convert int to String.
What's the difference between primitive and reference types?
When you are executing println(b_class); implicitly it calls toString method of same class, which is inherited from Object class.
You need to override toString method to display correct output.
static class B extends A {
int val=0;
public int multiply(int a, int b) {
val = a * b * 5;
return val;
}
public String toString(){
return String.valueOf(val);
}
}
Now, println(b_class); will work as per your expectation.
I am trying to understand how Overloading in JAVA works and trying to get grasp of various overloading rules that are applied in case of widening, autoboxing and varargs in JAVA. I am not able to understand what is happening in the following scenario:
package package1;
public class JustAClass {
public static void add(int a, long b) {
System.out.println("all primitives");
}
//public static void add(Integer a, long b) {
// System.out.println("Wraper int, primitive long");
//}
public static void add(int a, Long b) {
System.out.println("Primitive int, Wrapper long");
}
public static void add(Integer a, Long b){
System.out.println("All wrapper");
}
public static void main(String[] args) {
int a = 10;
Integer b = 10;
long c = 9;
Long d = 9l;
add(a,c);
add(a,d);
add(b,c);
add(b,d);
}
}
At this point, I get a compilation error at the third invocation of the add method saying The method is ambiguous for the type Error .
Why is this so? What are the rules for determining which invocation of method will work? What is exactly happening in the following case?
I feel that fourth overloaded add method should work. Please help me understand the concept behind this.
There are 3 stages to method overloading resolution. The first stage doesn't do auto-boxing/unboxing, which means methods that require boxing/unboxing of the passed parameters in order to match one of the overloaded versions of add will only be considered if no match was found that doesn't require boxing/unboxing. That's why 3 of your calls, which have a single exact match, work. Regarding add(b,c);, see below why it's ambiguous.
add(a,c); // exact match to add(int a, long b)
add(a,d); // exact match to add(int a, Long b)
add(b,c); // there is no exact match, so at least one of the passed parameters must
// be boxed or unboxed. However, by unboxing b to int or boxing
// c to Long, each of the three add methods can match, and the
// compiler doesn't know which one to prefer
add(b,d); // exact match to add(Integer a, Long b)
public Fraction (int a1 , int b1) {
a = a1;
b = b1;
}
Fraction fr = new Fraction (new Fraction(1,1), new Fraction(2,2) )
Is there a way to make this work?
Can this [...] be called like this [...]
Of course not. Java is a statically typed language, and this constructor expects int types:
public Fraction (int a1 , int b1)
However, on this line you're providing it with Fraction types:
new Fraction (new Fraction(1,1), new Fraction(2,2))
That won't work for exactly the reason the compiler is telling you. There is no constructor on Fraction which matches the types of the arguments specified.
(The two inner constructor calls on that line will work. The outer one is the one that's failing.)
Is there a way to make this work?
Depends on how you define your constructors You can define two constructors in your class:
public Fraction (int a1 , int b1)
{
// ...
}
public Fraction (Fraction a1 , Fraction b1)
{
// ...
}
Then you can construct an instance of a Fraction object with either constructor, which would make that line valid. What you do inside that second constructor is up to you.
To make it work, create one more overloaded constructor that accepts two Fraction arguments:
public Fraction(Fraction f1, Fraction f2) {
this(f1.a*f2.b, f1.b*f2.a);
}
Its possible only if you write 2 overloaded Constructor :
public Fraction (int a1 , int b1)
and
public Fraction (Fraction f1 , Fraction f2)
I have the following code:
import java.lang.*;
public class Program
{
public static void main(String [] args)
{
B a = new A();
a.p(10);
a.p(10.0);
}
}
class B {
public void p(double i)
{
System.out.println(i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println(i);
}
}
When I execute this code using B a = new A() , I get 20.0 in both cases which makes sense because overloading is handles during compile time where the compiler looks at the declared type and calls a function appropriately. Since our declared type was class B, class B's method was called in both cases. Now if I do A a = new A(); , I should be getting 10 in both answers but I am not. I am getting 10 for a.p(10) and 20.0 for a.p(10.0). Based on the concept of static binding and whole notion of overloading being done by static binding which looks at the declared type as opposed to the actual type, why is the result coming out this way ? I would very much appreciate your help.
An int can be widened to a double, but not the other way around. This means that 10 can call B.p(double) or A.p(int) but 10.0 is a double and will not be implicitly converted to an int i.e. only B.p(double) will be called.
Its because your method p is not an overridden method, it is just inhereted in your sub-class when you use
Super sup = new Sub();
sup.p(int);
sup.p(double);
In this case as your Super class has a method which takes double as a parameter and aa an int can fit into a double your Super-class's method is invoked the one which accepts double.
Sub sup = new Sub();
sup.p(int);
sup.p(double);
In this case however, as your subclass doesn't have a method which takes a double, for sup.p(double) call it uses the inherited method from super class if you pass double as an argument.
In your case, your are doing overloading which will get binded at compile time(static binding.).And static binding happens with type of reference rather than the type of object the reference is pointing.
In your first case you are using a reference variable of B and assigning an object of A to it.Since your reference is B, the method p(double) from B will get binded statically even if you use an int(since int can be widened to double).
In the second case you are using reference as A itself.In this case, you have two p() methods available.One is p(double) from B and other p(int) from A.So p(10) will call p(int) and p(10.0) will call p(double)
Try this:
class B {
public void p(String i)
{
System.out.println("parent:"+i);
}
}
class A extends B{
public void p(int i)
{
System.out.println(i);
}
}
public class Test1 {
public static void main(String args[]) {
A a = new A(); //arg
a.p(10);
a.p("sample");
}
}
If you change the line marked arg to B a = new A(), you will see compiler trying to call parent p in both the cases.
When you write A a = new A() you create a new object of type A, which will have 2 methods. A.p(int) and B.p(double), and when you call A.p(10.0), it will call B.p(double) due to lack of conversion.
This counter-example might help:
import java.lang.*;
public class X
{
public static void main(String [] args)
{
B c = new A();
c.p(10);
c.p(10.0);
c.p("AAA");
((A)c).p(10);
}
}
class B {
public void p(String s)
{
System.out.println("B: my string is " + s);
}
public void p(double i)
{
System.out.println("B: twice my double is: " + i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println("A: my number is " + i);
}
}
Output:
C:\temp>java X
B: twice my double is: 20.0
B: twice my double is: 20.0
B: my string is AAA
A: my number is 10
The issue is:
1) You're declaring the type as "B" (not "A")
2) B.p(10) can accept an int as a floating point argument
3) Consequently, that's what you're getting
It's really an issue of what argument types can be implicitly converted, than what methods are overloaded or overridden.
When the object has declared type B, the double version is invoked because it's compatible with an int argument, since in Java int is a subtype of double.
When the object is declared as a A, it has the method p() overloaded with two versions:
p(int arg);
p(double arg);
So, when you pass an int, the first version is picked because it's more accurate, and when you pass double the second one, because it's the most specific signature.
For reference, see the relevant JLS at ยง15.12.2 and this post by Gilad Bracha. BTW, don't try to figure out how the language should behave based on what you think is the most logical way, because every programming language is an engineering effort, and this means that there's a price you pay for whatever you take. The primary source of information for Java are the JLS, and if you read it carefully, you'll (surprisingly?) discover that there are even cases where the line in the source code is ambiguous and cannot be compiled.
To make the effect of widening of int to double more vivid I have created another example which is worth looking. Here, instead of double I have created a class called Parent and instead of int a Child class is created.
Thus,
double ~ Parent int~Child
Obviously child object can be widened to Parent reference.
package test;
public class OOPs {
public static void main(String[] args) {
Child ch = new Child(); // like int 10
Parent pa = new Parent();// like double 10.0
B a = new A(); // case 2 : A a = new A();
a.p(ch);// 10
a.p(pa);// 10.0
}
}
class B {
public void p(Parent i) {
System.out.println("print like 20");
System.out.println(i.getClass().getName());
}
}
class A extends B {
public void p(Child i) {
System.out.println("print like 10");
System.out.println(i.getClass().getName());
}
}
class Parent {
String name;
Parent() {
name = "Parent";
}
public String getName() {
return name;
}
}
class Child extends Parent {
String name;
Child() {
name = "Child";
}
public String getName() {
return name;
}
}
Case 1 - Output (B a = new A();)
print like 20
test.Child
print like 20
test.Parent
Case 2 - Output (A a = new A();)
print like 10
test.Child
print like 20
test.Parent
How to initialize the values in constructor that the values cannot be passed by object and that we could pass them from main method?
class ex
{
int a,b;
ex()
{
this.a=b;
}
public static void main(String args[])
{
//here we pass the values to that consructor ex
ex obj=new ex();
}
}
make an overloaded constructor which accepts two arguments.
public ex(int a, int b) {
this.a = a;
this.b = b;
}
public static void main(String...args){
ex obj = new ex(1,2)
}
values canntot be passed by object we should pass from main method
If i understand correctly, you want to pass arguments from the main method and nitialize them in your constructor, the only was to do is by passing them to the constuctor while object creation
You can call setter method from constructor if don't want to display initialization values while declaring new object.
Please see code below for reference :
class Testcl {
int a,b;
Testcl(){
setValues(1,2);
}
private void setValues(int a, int b){
this.a=a;
this.b=b;
}
public static void main(String [] args){
Testcl test = new Testcl();
System.out.println("a : " + test.a + " b : " + test.b);
}}
The first thing to say is that this does actually "work" ... in the sense that it compiles and executes without any errors.
int a,b; // default initialized to 'zero'
ex() {
this.a=b; // assigns 'zsro' to a.
}
But of course, it doesn't achieve anything ... because a is already zero at that point.
Now the main method could assign something to the a and/or b fields after the constructor returns. But there is no way (in pure Java1) to get some non-zero value into b before the constructor is called ... if that is what you are asking.
The practical solution is to just to add a and b arguments to the constructor.
1 - a non-pure Java solution might be to "monkey around" with the bytecodes of the constructor so that it does what you "need" to do. But that's pretty horrible, and horrible solutions have a tendency of coming back to bite you.