Java Overloading: Number,Number ; int,Double - java

In two days i have an exam in java, and i can not figure out the answer to this question:
class ClassA {
public String foo(Integer x , int y) {
return "Integer, int";
}
public String foo(int x, Double y) {
return "int, Double";
}
public String foo(Number x, Number y) {
return "Number, Number";
}
public String foo(Object x, Object y) {
return "Object, Object";
}
public static void main(String... args) {
ClassA a = new ClassA();
System.out.print(a.foo(5, 1.2f) + " ");
System.out.println(a.foo(null, null));
}
}
What's the output?
The Answer is:
Number, Number Number, Number
I know that java always chooses the most specified Method, that is why a.foo(null,null); will envoke the Number,Number Method and not the Object,Object Method.
But why does a.foo(5,1.2f); also envoke the Number,Number Method and not the int,Double Method??
But one more thing which might be helpful:
If i remove the f after 1.2, so that the call is:
a.foo(5,1.2);
I get a compiler error, that it can not choose between the Number,Number and int,Double Method...
Would be really helpful, if you guys could explain that to me :)

1.2f is not wrapped by a Double, it's wrapped by a Float. SinceFloat is not a subclass of Double (they are distinct subclasses of Number), the most specific method signature that can be used is foo(Number,Number).
Once you remove the f, 1.2 will be treated a double (the primitive, not the wrapper class) by default, which can be autoboxed to a Double. However the 5 can also be autoboxed to an Integer, thus causing the ambiguity.

There are two important factors here.
First, 1.2f is not a Double. It's a Float. The (int, Double) function doesn't match at all. (Number, Number) is the best fit.
Second, even when you change it to 1.2 it is still not a Double. It is a double. That is, it's a primitive, not an object. Now, Java will still happily pass a double into a function that wants a Double without much complaint, but in this case you've confused it by giving it two valid conversions it could make:
Convert 5 to an Integer and convert 1.2 to a Double
Leave 5 as a primitive int but convert 1.2 to a Double.
There isn't a rule for which of those is preferable. Java produces a compiler error that it has an ambiguous function call, and forces you to choose which one you'd prefer (by manually wrapping one or both of them in objects).
As an aside, if you had a method that took (int, double) there would be no ambiguity at all: that method actually matches the existing types of 5 and 1.2, so it would be called. It's the fact that some of the arguments here are wrapper objects that causes the mayhem.

Generic Answer:
public class OverloadingNumeric {
public void print(int x){
System.out.println("int");
}
public void print(long x){
System.out.println("long");
}
public void print(float x){
System.out.println("float");
}
public void print(double x){
System.out.println("double");
}
public void print(Integer x){
System.out.println("Integer");
}
public void print(Long x){
System.out.println("Long");
}
public void print(Float x){
System.out.println("Float");
}
public void print(Double x){
System.out.println("Double");
}
public void print(Number x){
System.out.println("Double");
}
public void print(Object x){
System.out.println("Object");
}
public static void main(String[] args) {
OverloadingNumeric obj = new OverloadingNumeric();
/*
* Primitives will take more precedence
* of calling instead of wrapper class arguments,
*/
obj.print(10);
obj.print(10l);
obj.print(10f);
obj.print(10d);
obj.print(10.1);
//obj.print(999999999999999); Error: this letral type int is out of range
obj.print(999999999999999l);
/*
* OUTPUT
* int
* long
* float
* double
* double
* long
*/
/*
* Assume all primitive argument methods
* are commented. then calling the same again
*/
obj.print(10);
obj.print(10l);
obj.print(10f);
obj.print(10d);
obj.print(10.1);
//obj.print((Double)10); //Cannot cast int to Double
obj.print((double)10); //Success
//obj.print((Float)10); //Cannot cast int to Float
obj.print((float)10); //Success
//obj.print(null); ERROR AMBIGUOUS
/*
* OUTPUT
* Integer
* Long
* Float
* Double
* Double
* Double
* Float
*
*/
}
}
interface SuperIfc {}
class SuperClass implements SuperIfc{}
class SubClass extends SuperClass {}
public class OverloadingTest {
public void print(SuperIfc x){
System.out.println("SuperIfc");
}
public void print(SuperClass x){
System.out.println("SuperClass");
}
public void print(SubClass x){
System.out.println("SubClass");
}
public void print(Object x){
System.out.println("Object");
}
public static void main(String[] args) {
OverloadingTest obj = new OverloadingTest();
SuperClass superObj = new SuperClass();
SubClass subObj = new SubClass();
obj.print(superObj);
obj.print(subObj);
obj.print(null);
obj.print((SuperIfc)superObj);
obj.print((SuperIfc)subObj);
obj.print((SuperIfc)null);
/*
* OUTPUT
* SuperClass
* SubClass
* SubClass
* SuperIfc
* SuperIfc
* SuperIfc
*/
}
}

Related

Java: Function parameter that takes any type

Im writing a Java function to output things to the console with a certain format, but I need one of the parameters to accept any type as an argument. How do i do this?
Using Generics, it would work as follows:
public static <T> void printAnything(T anything){
System.out.println(anything);
}
public static void main(String[] args){
printAnything(new SyncPart());
}
The generics shown in SMA's answer are unnecessary: just take Object as your parameter type:
public static void printAnything(Object anything){
System.out.println(anything);
}
Any type is not possible. Primitives will stop you from what you're doing.
But you can use void myFunction(Object anyObject) {} for example, and give it any Class-type = reference-type Object.
If you still wanna include primitives, you have to split up to multiple methods:
package stackoverflow;
public class ClassOverload {
// central method
static public void myMethod(final Object pObject) {
final String type = pObject == null ? null : pObject.getClass().getSimpleName();
System.out.println("ClassOverload.myMethod(" + pObject + ") of type " + type);
}
// primitive overloading methods
static public void myMethod(final boolean pValue) { // absolutely needed
myMethod(Boolean.valueOf(pValue));
}
static public void myMethod(final char pValue) { // absolutely needed
myMethod(Character.valueOf(pValue));
}
static public void myMethod(final byte pValue) {
myMethod(Byte.valueOf(pValue));
}
static public void myMethod(final short pValue) {
myMethod(Short.valueOf(pValue));
}
static public void myMethod(final int pValue) {
myMethod(Integer.valueOf(pValue));
}
static public void myMethod(final long pValue) { // absolutely needed
myMethod(Long.valueOf(pValue));
}
static public void myMethod(final float pValue) {
myMethod(Float.valueOf(pValue));
}
static public void myMethod(final double pValue) { // absolutely needed
myMethod(Double.valueOf(pValue));
}
}
This will convert your primitives to their reference type and keep the type as close to the original as possible.
If you wanna reduce the methods, you could just keep the boolean, long and double methods. All other primitives can be cast into one of those three:
boolean will use the boolean method.
char will use the char method.
byte, short, int and long (all "whole number" integer values, as opposed to floating-point values) will use the long method.
float and double (floating-point) will use the double method.

Java Overridden method visibility scope

How is the following program correct?
abstract class Calculate
{
abstract int multiply(int a, int b);
}
public class Main
{
public static void main(String[] args)
{
int result = new Calculate()
{
#Override
int multiply(int a, int b)
{
return a*b;
}
}.multiply(12,32);
System.out.println("result = "+result);
}
}
We are changing the scope of the overridden method here.It is not public anymore and it should of default scope.Is the scope change of overridden method allowed?
You are creating an anonymous subclass in your current code, but you are very close to having a functional interface. Let's change it to that, like
#FunctionalInterface
interface Calculate {
int multiply(int a, int b);
}
Now you have a single abstract method and can use fancy lambdas. Like,
public static void main(String[] args) {
Calculate calc = (a, b) -> a * b;
int result = calc.multiply(12, 32);
System.out.println("result = " + result);
}
Note this is exactly like your original example, just syntactic sugar added with Java 8.
From your code, it multiply is not public to begin with. If you change your mulyiply method your Calculate class to
public abstract int multiply(int a, int b);
then it will not work.
According to your code, the calculate method is not in public scope, so you are not changing the scope.
abstract class Calculate {
public abstract int multiply(int a, int b);
}
public class MyClass {
public static void main(String[] args) {
int result = new Calculate() {
#Override
public int multiply(int a, int b) {
return a * b;
}
}.multiply(11,11);
System.out.println("result = " + result);
}
}
The access level cannot be more restrictive than the overridden method's access level. For example: If the super class method is declared public then the overriding method in the subclass cannot be either private or protected.
Now there is a separate scope as default scope introduced in java , so you can call it as package private scope.
For rules of overriding in java you can follow the Link

Java how to make a method argument accept subclass type and superclass

I have a superclass and one subclass with some variables like below:
public class A{
private int first;
private int second;
public A(int _first, int _second){
first = _first;
second = _second;
}
public int getFirst(){
return first;
}
}
public class B extends A{
private int third;
public B(int _first, int _second, int _third){
super(_first, _second);
third = _third;
}
public int getThird(){
return third;
}
}
I want to build a method in the main class that accepts a generic argument that can be of type A or type B like below:
public class Main{
public int val = 2;
public static void main(String []args){
A a = new A(1, 2);
B b = new B(1, 2, 3);
printObject(a);
printObject(b);
}
public void printObject(A a){
int f = a.getFirst() * val;
int s = a.getSecond() * val;
if(a instanceOf B){
int t = a.getThird() * val; // compiler does not find the getThird() method this way
}
}
}
How can this be achieved?. is generics an option? I have thought about making printObject() method inside A then override it inside B however I have some other variable like val above that I am creating in main.
update
I tried to use instanceOf like the above method. But this way the compiler does not find the subclass's specific method.
Firstly, by definition, if you declare A as a parameter to any method and B is it's sub-class, then any A or B can be passed to that method.
You could then achieve what you want using the instanceof operator (to check if the parameter passed in is of type B). However, inheritance / method override should typically be used rather than instanceof.
You could pass 'val' into the printObject() methods on A/B. If several variables like 'val' are involved you could pass in another object or perhaps you need to split your code across multiple methods on class A (overridden in B), passing in different values as appropriate? (You wouldn't normally do calculations in a method whose purpose is to print an object but perhaps that was just an example?)
Everything is much simplier) You could get rid of this method in the main class, cause it's producing some redundant coupling. And all this instanceof really smells in 2019. You could make it more independent.
Class A:
public class A{
private int first;
private int second;
public A(int _first, int _second){
first = _first;
second = _second;
}
public int getFirst(){
return this.first;
}
public int getSecond(){
return this.second;
}
public void print(int multiplier) {
System.out.println(this.first * multiplier);
System.out.println(this.second * multiplier);
}
}
Class B:
public class B{
private int third;
public B(int _first, int _second, int _third){
super(_first, _second);
third = _third;
}
public int getThird(){
return this.third;
}
#Override
public void print(int multiplier) {
super.print(multiplier);
System.out.println(this.third * multiplier);
}
}
Class Main:
public class Main{
public int val = 2;
public static void main(String []args){
A a = new A(1, 2);
B b = new B(1, 2, 3);
a.print(val);
b.print(val);
}
}
Writing object oriented code is more than extending a class , your API's and other functionality should be designed as part of the solution.
In your case, the most appropriate way to do this is to add the print method to the object itself, you can either override the entire function or to call the super class inside the overriding class.
public class A{
/// ... your code
public void print(){
System.out.println("first :"+first+", second : "+second);
}
}
public class B extends A{
/// ... your code
public void print(){
//Option A - use parent class getters/setters to implement print for object B
System.out.println("first :"+super.getFirst()+", second : "+super.getsecond() +" third" + third);
}
//Option B (More usable to methods returning a value or performing an update) - Perform operation on parent variables, then perform on class specific variables
super.print()
System.out.println("third : "+third);
}
}
and then
A a = new A();
A b = new B();
a.print();
b.print();
Will each call the correct runtime function based on their actual implementation

Testing a Calculator in JUnit 4 in Eclipse

I have this calculator .java from an online practice and I need to test it in JUnit in Eclipse;
package calculator;
import java.util.Scanner;
public class Calculator {
private double accumulator;
public Calculator() { }
public Calculator(double initialValue) { accumulator = initialValue; }
public void add(double number) { accumulator += number; }
public void subtract(double number) { accumulator -= number; }
public void multiply(double number) { accumulator *= number; }
public void divide(double number) { accumulator /= number; }
public void sqrt() { accumulator = Math.sqrt(accumulator); }
public void setAccumlator(double accumulator) { this.accumulator = accumulator; }
public double getAccumulator() { return accumulator; }
#Override
public String toString() { return "Result:" + accumulator; }
}
I've been pouring through documentation (I'm rather new to programming in general) and unsure of how to actually do this. I have JUnit set up and a test file set up, like;
#Test
public void testAdd(){
}
#Test
public void testDivideByZero(){
}
etc.
I've tried a few things and the syntax was wrong, stuff like
The method add(double) in the type Calculator is not applicable for the arguments (double, double)
or
Cannot make a static reference to the non static method add(double) from the type Calculator
Any suggestions?
Example of a test
private Calculator mCalculatorInstance;
#Before
public void setupTestEnvironment() {
// This method will be call before every single test.
mCalculatorInstance = new Calculator(2.0);
}
#Test
public void testAdd(){
mCalculatorInstance.add(2.0); // add 2 to the initial value of 2 which I instanitiate above should return 4.
assertEquals("Adding 2 to 2 should give me 4.", 4.0, c.getAccumulator());
}
In order to do testing, you need to know the expected output of the test. Let use the above test as scenario. I declared that I'm initializing a calculator object with accumulator value of 2.
mCalculatorInstance = new Calculator(2.0);
I know that using the add method of the instance will add the parameter to the accumulator. Hence I call the add method.
mCalculatorInstance.add(2.0);
So now I'm adding 2.0 to the accumulator which already have a value of 2.0
2.0 + 2.0 = 4.0
Since the object provide a method to get back the accumulator, I use the method to get back accumulator and check whether the addition is correct, the value of accumulator should be 4.0.
assertEquals("Adding 2 to 2 should give me 4.", 4.0, c.getAccumulator());

Passing a method to another method from a different Class

Basically im coding a differential equation solver class that will take equations from an "Equation" Class and solve it using the rK4 method.
The main problem Im running into, is that I can't find a way to send a method to another class without extending and gaining acess through inheritance, or making a specefic instance of that Equation methods in my ODE class.
for example, how would I make the code below work? (remember I am not allowed to make a specific instance of Equation methods within the ODE class):
public class Equations {
public double pressureDrp( double a, double b) {
return a+b; //this is just a dummy equation for the sake of the question
}
public double waffles( double a, double b) {
return a-b; //this is just a dummy equation for the sake of the question
}
}
public class ODE {
//x being a method being passed in of "Equations" type.
public double rK4( Equation method x ) {
return x(3, 4);
//this would return a value of 7 from the pressureDrp method in class Pressure
//if I had passed in the waffles method instead I would of gotten a value of -1.
}
}
I would use an interface to encapsulate the concept of a binary method and to allow call-backs, something like:
interface BinaryEquation {
double operate(double d1, double d2);
}
This could then be placed in your equations class like so:
class Equations {
public static class PressureDrop implements BinaryEquation {
#Override
public double operate(double d1, double d2) {
return d1 + d2;
}
}
public static class Waffles implements BinaryEquation {
#Override
public double operate(double d1, double d2) {
return d1 - d2;
}
}
}
And used like so:
class ODE {
public double rk4(BinaryEquation eq) {
return eq.operate(3, 4);
}
}
Or better like so:
public class BinaryTest {
public static void main(String[] args) {
System.out.println("PressureDrop(3, 4): " + new Equations.PressureDrop().operate(3, 4));
System.out.println("PressureDrop(3, 4): " + new Equations.Waffles().operate(3, 4));
}
}

Categories

Resources