Check how many arguments a method has on Java - java

I have multiple classes that extends an abstract class A.
The abstract class has the following two methods:
public abstract int methodOne (int n);
public abstract int methodTwo (int n);
One of the classes, class B, that extends the class A overloads one of the methods for instance:
public int methodOne (int n) {
return n * 2;
}
public int methodOne (int n, int k) {
return n * k;
}
Now we are working with an instance of the class B, is there a way to check if the method methodOne has been overloaded and if so make a condition.
A ourTest = new B();
If methodOne has two arguments then use the method with two arguments, otherwise use the methodOne with one argument.

You can use reflection to inspect what methods B declares. Note there are 2 flavors:
B.getClass().getMethods()
Will give you an array of Method objects representing all of the public methods of the class, including those declared by the class or interface and those inherited from superclasses and superinterfaces.
You can also call
B.getClass().getDeclaredMethods()
Will give you an array containing Method objects reflecting all the declared methods of the class, including public, protected, default (package) access, and private methods, but excluding inherited methods.
Not that in your case, class A doesn't have a 2 argument form of methodOne so it technically cannot be inherited or overridden in B.
So, you could call getDeclaredMethods() and loop over the array of Method objects to see if B has a 2 argument form of methodOne.
This works even if you declared an object of type A but instantiate it with new B().
The following sample code shows it in action:
public abstract class A {
public abstract int methodOne (int n);
public abstract int methodTwo (int n);
}
public class B extends A {
#Override
public int methodOne(int n) {
return n;
}
public int methodOne(int n, int k) {
return n + k;
}
#Override
public int methodTwo(int n) {
return n * 2;
}
}
// test it out (note that this can throw several different exceptions
// so you'll have to handle them..I left that out to keep the code
// concise.
A a = new B();
Method[] methods = a.getClass().getDeclaredMethods();
for(Method m : methods) {
System.out.println(m.toGenericString());
if(m.getName().equals("methodOne") && m.getParameterCount() == 2) {
int result = (int)m.invoke(a, 3, 2);
System.out.println("Result = " + result);
}
}
This will print the following:
public int B.methodTwo(int)
public int B.methodOne(int,int)
Result = 5
public int B.methodOne(int)

You have no same method with one or two arguments. Both methods are different although have the same name (methodOne). If you want to find how many arguments a method has, or if it has been overloaded, there is Java Reflection API available. But you are trying to do seems to make no sense.

If methodOne has two arguments then use the method with two arguments, otherwise use the methodOne with one argument.
No, you cannot do that, because Java is statically typed.
Since A defines only the one-argument version of methodOne, that is all you'll ever have for code that uses variables of type A.
Any method added to subclasses are not visible in plain Java code for variables of type A. You can only call such "extra" methods by either casting to the subclass in question, or by using reflection.

Related

Do inherited methods use the visibility, methods and attributes of the superclass or subclass?

What I assume is that an inherited method will, by standard, use the methods and attributes of the class whose object is used to execute that method.
Here's an example for my question, it's from a task from an older exam:
public class Test {
public static void main(String[] args) {
A a = new A(3);
A b = new B(1, 4);
b.methodOne(6); // <----- This. I think that this uses "b.m" and "b.increase"
}
}
public class A {
private int m;
private int n;
public A(int n) {
m = n;
}
public void methodOne(int i) {
m -= i;
increase(i);
}
public void increase(int i) {
m += 2 * i;
}
public void visilibityTest() {
n++; // <----- I think that b.visibilityTest() would work
// Because it uses the visibility "rights" of A.
}
}
public class B extends A {
private int m;
public B(int m, int n) {
super(n);
this.m = m + 1;
}
public void increase(int i) {
m += i;
}
}
As I said in the comments, I think that by executing b.methodOne, the attribute "b.m" and the method "b.increase" are used, even though methodOne is inherited from class A. (I mean this.m of b, not super.m)
1. Is this true? Do inherited methods normally use the methods and attributes of the subclass?
2. What role do the static/dynamic type play in this task? ("A b = new B")
And what about visibility? In another task I found out that if you use inherited methods to access private attributes of the superclass (that should not be visible to a subclass), you can access those attributes, as if you were accessing superclass's visibility rights. I added an example method called visibilityTest() to show that example on this task. Would that work?
3. Do inherited methods use the visibility of the superclass?
I apologize for any unclear wording. I'm both still trying to understand most of this, and also have to find out what many terms are called like in English, for the purpose of translation.
Any pointing out of unclear wording will be appreciated.
Yes, this is correct. When a method is inherited from a superclass, the subclass can override it to change the behavior, but if not overridden, it will use the implementation in the superclass. In this case, calling b.methodOne(6) will use the m and increase from the B class, since b is an object of type B.
The static type refers to the type of a reference variable (in this case A b) whereas the dynamic type refers to the actual type of the object referred to by the reference variable (in this case B). When you call b.methodOne(6), the static type is A but the dynamic type is B. This means that the method methodOne is resolved based on the type of the object b refers to (dynamic type B) rather than the type of the reference variable b (static type A).
Inherited methods use the visibility of the superclass unless they are overridden in the subclass. In this case, b.visibilityTest() would work, because it is a method in the superclass A and visibility is not changed by inheritance.

How Can I Accept String Array through scanner class and define its size by user size

Is it possible for two methods to be have the same name and same parameters and return the same type?
For example I have these two methods:
class Method
{
public int mm(int a,int b)
{
return a+b;
}
public int mm(int a,int b)
{
return ab;
}
public static void main*String j[])
{
Method m=new Method();
System.out,println(m.add(12,23);
System.out.println(m.add(12.0f,23.0f);
}
}
But this code generate error it means that return type should not same
Overloading methods must differ in one of the following :
Number of parameters.
Data type of parameters.
Sequence of Data type of parameters.
I see there are several syntactical errors in the code snippet you provided. Never mind, I guess the syntax got wrong while you wanted to put up the code in the question.
Coming to your query:
You see you have the exact method signatures for both your mm methods. Both the mm methods take int a and int b and returns an int.
Thus the compiler will not know what method to call because these two methods will be called in exactly the same conditions. In other words, there is no simple scenario when either of these methods will not be called.
However, if you change the arguments of either of the mm methods, your code will compile:
public int mm(int a, int b) {
return a + b;
}
public int mm(float a, float b) {
return 1;
}
public static void main(String j[]) {
Method m = new Method();
System.out.println(m.mm(12, 23));
System.out.println(m.mm(12.0f, 23.0f));
}
In the above case, the compiler will call the second mm method in the second call statement, System.out.println(m.mm(12.0f, 23.0f));
Thus here you see, you can have same return type.
Hope it helps you!
Not, Both methods have the same signature, You can cause the program to become aware of itself and destroy the world. Try something like this:
public int mm(int a ,int b, int op)
{
int result = 0;
switch (op) {
case 1:
result = a + b;
break;
case 2:
result = a * b;
case 3:
result = a - b;
default:
break;
}
return result;
}
public static void main(String [] args)
{
Method m = new Method();
System.out.println( m.mm(5,5,1));
}
For such questions, you should always consult the JLS. So here we go:
§8.4.9. Overloading
If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.
The same holds true for interfaces:
§9.4.2. Overloading
If two methods of an interface (whether both declared in the same interface, or both inherited by an interface, or one declared and one inherited) have the same name but different signatures that are not override-equivalent (§8.4.2), then the method name is said to be overloaded.
The term "override-equivalent" is explained here:
§8.4.2. Method Signature
Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
The terms "signature" and "subsignature" are also explained in this paragraph, of which signature is the more important one:
Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.
Summarizing this all, it means that the return type is not part of a method's signature, which also means that different return types are not enough to make methods different (with respect to overloading).

cast on object of type superclass returns object of type subclass in java

I have implemented the following code in order to understand the difference between static and dynamic binding:
class A {
int met(A a) {
return 0;
}
int met(B b) {
return 1;
}
int met(C c) {
return 2;
}
}
class B extends A {
int met(A a) {
return 3;
}
int met(B b) {
return 4;
}
int met(C c) {
return 5;
}
}
class C extends B {
int f() {
return ((A)this).met((A)this);
}
}
public class Test {
public static void main(String[] args) {
C x = new C();
System.out.println(x.f());
}
}
The result I get is 3, but I don't understand why, since the first cast is made to A.
So, let's look at the call:
((A)this).met((A)this);
That's equivalent to:
A target = this;
A argument = this;
target.met(argument);
So, for the last line, the compiler looks up the signature based on the compile-time types involved - it will look in A (and superclasses) for a method called met which has a parameter that is compatible with A (the compile-time type of the argument). Overload resolution finds that the answer is:
int met(A a)
That's determined the signature at compile-time. However, the implementation of that method is determined at execution time, based on the execution-time target of the method call. That type is C here - because this is a reference to an instance of C. (The f method is called on an instance of C.)
Now C doesn't override int met(A a), but B (its superclass) does - so that's the implementation that's used. It doesn't matter that B also overrides met(B b) and met(C c) because the compiler has already determined that it's the met(A a) method which is being called.
This is two questions for the price of one. (1) Why do we get the implementation from class B, and (2) why do we get the version of the method with the parameter of type A.
For question (1), the thing to remember is that the class of an object doesn't change when you cast it, or assign it to a variable whose type is something different. So in your example, the class of this is always C, because that's what you created. Class C inherits its version of met(A a) from class B because it doesn't have its own version, and because class B has overridden the version in class A. This is what polymorphism is all about - the version of the method depends on the class of the object that you call it on, not on the type of the expression that you use to call it.
For question (2), it's a wee quirk of Java that method signatures are evaluated at compile time. So the compiler sees that you're passing an expression of type A into your method, so it chooses the signature met(A a). Because this decision is made at compile time, the actual class of the argument doesn't make any difference - the compiler has already chosen the method, based on the type of the expression. In other words, Java doesn't give you polymorphism of method parameters.

Why do I get a compilation error when I try to have two methods with the same name and parameter type?

If i change the byte to int I get a compiler error. Could you explain the problem?
public class A {
protected int xy(int x) { return 0; }
}
class B extends A {
protected long xy(int x) { return 0; } //this gives compilor error
//protected long xy(byte x) { return 0; } // this works fine
}
If i change the byte to int I get a compiler error.
If you do that, you have this:
public class A {
protected int xy(int x) { return 0; }
}
class B extends A {
protected long xy(int x) { return 0; }
}
...and the only difference in the xy methods is their return type. Methods cannot be differentiated solely by their return types, that's the way Java is defined. Consider this:
myInstance.xy(1);
Which xy should that call? long xy(int x) or int xy(int x)?
If your goal is to override xy in B, then you need to make its return type int in order to match A#xy.
You can't have two methods with same signature in a Class though the methods are placed separately in different classes in the same inheritance tree. i.e. Base class and sub class
Note : Just return types can't make the compiler understand the difference in methods. return type is NOT included in the method signature as well
You are trying to write two methods with the same name and input parameters, that is not possible.
Look at the following two methods:
float met(){
return 4.5;
}
double met(){
return 5.4;
}
If we would write this line then
int x = (int)met();
what method would be called?
It is not possible to decide, therefore this situation is not permitted.
That's because if You change byte to int You will have method with the same signature in base and sub class (same method name and parameter type) and therefore return type should be the same as well. Because is not (int and long) it will give You error
You can differentiate methods by parameters and names only.
both methods are in same class B
b.xy(byte x) or b.xy(int x) is called for input xy(0) or xy(1)
Overiding method should return a type that can be substituted for the type returned by overriden method
Because when you change the byte into int the Instance which calls the method doesn't know which method is meant. The overwritten one or the old one?
Thats why it's not allowed to have the same signatures (method name, type of parameters and amount of parameters). Just as an information: The return type is not part of the signature.

Why isn't this method chosen based on the runtime-type of its object?

Consider this:
class A {
int x =5;
}
class B extends A{
int x =6;
}
public class CovariantTest {
public A getObject() {
return new A();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
}
}
class SubCovariantTest extends CovariantTest {
public B getObject(){
return new B();
}
}
As far as I know, the JVM chooses a method based on the true type of its object. Here the true type is SubCovariantTest, which has defined an overriding method getObject.
The program prints 5, instead of 6. Why?
The method is indeed chosen by the runtime type of the object. What is not chosen by the runtime type is the integer field x. Two copies of x exist for the B object, one for A.x and one for B.x. You are statically choosing the field from A class, as the compile-time type of the object returned by getObject is A. This fact can be verified by adding a method to A and B:
class A {
public String print() {
return "A";
}
}
class B extends A {
public String print() {
return "B";
}
}
and changing the test expression to:
System.out.println(c1.getObject().print());
Unless I'm mistaken, methods are virtual in java by default, so you're overriding the method properly. Fields however (like 'x') are not virtual and can't be overriden. When you declare "int x" in B, you are actually creating a totally new variable.
Polymorphism doesn't go into effect for fields, so when you try and retrieve x on an object casted to type A, you will get 5, if the object is casted to type B, you will get 6.
When fields in super and subclasses have the same names it is referred to as "hiding". Besides the problems mentioned in the question and answer there are other aspects which may give rise to subtle problems:
From http://java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html
Within a class, a field that has the
same name as a field in the superclass
hides the superclass's field, even if
their types are different. Within the
subclass, the field in the superclass
cannot be referenced by its simple
name. Instead, the field must be
accessed through super, which is
covered in the next section. Generally
speaking, we don't recommend hiding
fields as it makes code difficult to
read.
Some compilers will warn against hiding variables

Categories