null value considered as Object or Array - java

public class Test
{
public Test(Object o) {
System.out.println("object");
}
public Test(int[] o) {
System.out.println("array");
}
public static void main(String[] args) {
new Test(null);
}
}
Output :
array
Can somebody please explain me the reason behind this?

The rule is: the more specific method will be called. In this case, it's the method receiving a int[] which is more specific than the one receiving a java.lang.Object parameter.
Here's a link to Java's official documentation referencing to this case. Take a look at section 15.2.2. Quoting an interesting part (section 15.2.2.5):
If more than one member method is both accessible and applicable to a
method invocation, it is necessary to choose one to provide the
descriptor for the run-time method dispatch. The Java programming
language uses the rule that the most specific method is chosen.
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 type error.
An another one:
It is possible that no method is the most specific, because there are
two or more methods that are maximally specific. In this case:
If all the maximally specific methods have override-equivalent
(§8.4.2) signatures, then: If exactly one of the maximally specific
methods is not declared abstract, it is the most specific method.
Otherwise, if all the maximally specific methods are declared
abstract, and the signatures of all of the maximally specific methods
have the same erasure (§4.6), then the most specific method is chosen
arbitrarily among the subset of the maximally specific methods that
have the most specific return type. However, the most specific method
is considered to throw a checked exception if and only if that
exception or its erasure is declared in the throws clauses of each of
the maximally specific methods. Otherwise, we say that the method
invocation is ambiguous, and a compile-time error occurs.

It's always subclass would be preferred over the parent class. If you want to call Object one you could do the following:
new goFuncTest((Object) null);

As pablo's answer suggests, the most specific / least generic method will be called. Actually, the classlevel in the class hierarchy is checked to decide which method to call. The method with lower class level is called.
If 2 classes are at the same level, then you will get a compile time error stating - ambiguous method call just like in the below case.
public class Sample {
void someMethod(Object o) {
System.out.println("object");
}
void someMethod(String s) {
System.out.println("String");
}
void someMethod(int[] o) {
System.out.println("int[]");
}
public static void main(String[] args) {
new Sample().someMethod(null); // error ambiguous call both array and String are direct children of Object
}
Case -2 : To prove that the method with lower class level will be called.
public class Sample {
void someMethod(Object o) {
System.out.println("object");
}
void someMethod(OutputStream os) {
System.out.println("OutputStream");
}
void someMethod(FileOutputStream fos) {
System.out.println("FileOutputStream");
}
public static void main(String[] args) {
new Sample().someMethod(null);
}
}
O/P :FileOutputStream
Since FileOutputStream is child of OutputStream which is again a child of Object class (FileOutputStream is also a child of both OutputStream and Object classes). So the compiler goes like this Object --> OutputStream --> FileOutputStream while resolving the method call.

Thumb rule is child first in method call. As Object is parent of all and as null can be assigned to any type of object instance variable, it will first match any java type(which of course is child of object) and then super parent i.e. Object.

up gradation of Null to Array is preferred over casting it to Object. Object is top in the hierarchy while Array is closest to Null.
This is like up gradation of byte to int.

Related

Method overloading or overriding?

We have a Parent and child class, which has method with the same name but argument are as primitive and wrapper. Could someone please explain the reason whether this would be referred as Method Overriding and Method overloading. Running this program would invoke Parent method - which would be overriding and not overloading, looking for explanations.
class Parent {
public void takeValue(int a) {
System.out.println("take value method from parent is invoked");
}
}
class Child extends Parent {
public void takeValue(Integer a) {
System.out.println("take value method from child is invoked");
}
public static void main(String[] args) {
Parent p = new Child();
p.takeValue(new Integer(51));
}
}
The method is overloaded.
Running this program would invoke Parent method - which would be overriding and not overloading
Yes. You're calling takeValue on a Parent variable, which means that the compiler will look for a signature match on the Parent class. The overload is not even visible here (signatures are matched based on static types, i.e., java finds the method based on the declared data type of the variable on which the method is called, not with the data type of the object assigned to the variable, which would be a runtime thing).
And because public void takeValue(Integer a) is not considered by the compiler when checking the method invocation, p.takeValue(new Integer(51)); is linked to Parent.takeValue(int) by virtue of autoboxing (it would have matched the other method if both of them were visible - or declared in the Parent class in this example).
This is overloading. You have same name but type of input parameters are different.
To confirm that, you will get an error when you try to attach the #Override annotation.
Integer and int are different types.

Is it overloading or overriding?

I have a code and I am not able to get why the output will be "Radial Tire with long".Can somebody help me to understand this code?
class Tyre {
public void front() throws RuntimeException {
System.out.println("Tire");
}
public void front(long a) {
System.out.println("Radial Tire with long");
}
}
class TestSolution extends Tyre {
public void front() {
System.out.println("Radial Tire");
}
public void front(int a) throws RuntimeException {
System.out.println("Radial Tire with int");
}
public static void main(String... args) {
Tyre t = new TestSolution();
int a = 10;
t.front(a);
}
}
front is not overridden in TestSolution, it is overloaded.
You can regard an overloaded function as a completely different function, like one with a different name.
So t.front(a) will call the one in Tyre, with an a implicitly converted to long.
So if we go with definitions
Overloading means methods with same name but with different number or order of parameters.
Overriding means method with same name with same number of parameters along with rules mentioned here
So in your case front method is overloaded in both the classes Tyre and TestSolution
method front() from Tyre class is overridden in class TestSolution.
no overriding in case of method front(long a) and front(int a).
There's no overriding taking place in your main.
t's static (compile-time) type is Tyre, so, since method overload resolution is determined by the compile-time type of the instance, the only front methods available for the compiler to choose from are those declared in the base class Tyre :
public void front()
public void front(long a)
Only the latter (public void front(long a)) matches the arguments of the call t.front(a), and that method is not overridden by the sub-class. Therefore Radial Tire with long is displayed.
Calling ((TestSolution)t).front(a); would invoke the sub-class's method - public void front(int a).
General rule: if I have a variable of one class I can access only methods and components defined in that class.
The only particular case is:
you have a component or method both in the super class and in the subclass (overriding)
you have a variable of the super class and an object of the subclass (your case)
In these cases you can follow the following rule:
for the components the type of the variable decides which to use
for the methods the type of the object does (late binding)
In your case as stated before the method is not overridden so you can't apply the last rule.
Lets understand the difference between overloading and overriding
Overloading:
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists
Overriding:
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.
Tyre declared front() method with long as parameter.
TyreSolution declared front() method with int as parameter.
Since the method signature is different, TyreSolution overloads Tyre's front() method
If you change signature of front() in TyreSolution to accept long value as input parameter instead of int, then TyreSolution overrides Tyre's front() method.
e.g. TestSolution class definition of front() method
public void front(long a) throws RuntimeException {
System.out.println("Radial Tire with long in TestSolution");
}
output:
Radial Tire with long in TestSolution

What is "override-equivalence" and how is it related to #Override?

Reading the Javadoc for the #Override annotation, I came across the following rule:
If a method is annotated with this
annotation type compilers are required to generate an error message
unless at least one of the following conditions hold:
The method does override or implement a method declared in a supertype.
The method has a signature that is override-equivalent to that of any public method
declared in Object.
I'm clear on the first point, but I'm unsure about the second one.
What does it mean by "override-equivalent"? How are public methods of Object special in this respect? And why is this not covered under the first criterion?
Moreover, this is only true of the Java 7+ documentation. The Java 6 doc doesn't say anything about override-equivalence. Why the change?
Update:
After further consulting the JLS (Section 8.4.2), I found the following explanation of override-equivalence:
The signature of a method m1 is a subsignature of the signature of a method m2 if
either:
m2 has the same signature as m1, or
the signature of m1 is the same as the erasure (§4.6) of the signature of m2.
Two method signatures m1 and m2 are override-equivalent iff either m1 is a
subsignature of m2 or m2 is a subsignature of m1.
As far as I can tell, this answers the first question ("What does it mean?") and the third question ("Why doesn't the first condition cover this?").
If I understand correctly (please inform me if I don't!), there is only one case where two methods are override-equivalent and which doesn't fall under the first condition of the original question. This is the case when the erasure of the signature of the subclass method is the same as the signature of the superclass method, but not the other way around.
The second condition of the original question, then, would only come into play when we attempt to add type parameters when attempting to "override" a public method of the Object class. I tried the following simple example to test this, with an unused type parameter:
public class Foo {
#Override
public <T> boolean equals(Object obj) {
return true;
}
}
Of course, this class doesn't compile, because the method doesn't actually override the equals method and thus clashes with it. But I also still receive a compiler error for using the #Override annotation. Am I wrong in assuming that this example meets the second condition for #Override usage? Or is the compiler generating this error despite not being required to?
The reason for this is to allow you to use the #Override annotation in interfaces, which do not inherit from Object but implicitly declare all public methods from Object (see JLS section 9.2 interface members). You are thus allowed to declare an interface like:
interface Bar { #Override int hashCode(); }
However, you would not be allowed to declare the following interface:
interface Quux { #Override Object clone(); }
since the clone() method is not implicitly declared in an interface (it is not public).
This is described in JLS section 9.6.3.4 #Override (the Javadoc for #Override still refers to an old section number)
Your question is basically a design question and JLS explains its:
"The notion of subsignature is designed to express a relationship
between two methods whose signatures are not identical, but in which
one may override the other. Specifically, it allows a method whose
signature does not use generic types to override any generified
version of that method. This is important so that library designers
may freely generify methods independently of clients that define
subclasses or subinterfaces of the library."
Your code is not a valid example of this , see the below code it works:
public class SubSignatureTest extends SignatureTest {
#Override
public List test(Collection p) {
return null;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
class SignatureTest {
public <T> List<T> test(Collection<T> t) {
return null;
}
}
Whole point is that signature of superclass and subclass should be same after erasure.
EDIT:
When we talk of override equivalence then parent class should have generic method and child class should have non generic method. Here is an example to explain this .Below code will not work because child class have generic method. For a moment lets assume that java allowed that then the call in main method will always fail :
class A{
public int compareTo(Object o){
return 0;
}
}
class B extends A implements Comparable<B>{
public int compareTo(B b){
return 0;
}
public static void main(String[] argv){
System.out.println(new B().compareTo(new Object()));
}
}
In class B method will be like this after compilation:
public int compareTo(Object x){
return compareTo((B)x);
}
Which means this is always error: new B().compareTo(new Object()) .
Therefore java will not allow child class to have generic method if parent class has non generic method. So you can't define override equivalence methods for object class.
Hope that clarifies.
I used the post http://lists.seas.upenn.edu/pipermail/types-list/2006/001091.html for reference, it has lot more details.

Java abstract method signature

I am quite confused about abstract method signitures that Java classes implement.
For example, consider:
interface Programmer {
Object program();
}
class Linus implements Programmer {
public String program() {
return "goto end;";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(new Linus().program());
}
}
This is apparently acceptable, since anything expecting an Object to come from Linus.program() will get one (specifically, a String).
But now consider this:
interface OS {
void run(String code);
}
class Linux implements OS {
public void run(Object code) {
System.out.println("Hello world");
}
}
public class Main {
public static void main(String[] args) {
new Linux().run("print 'Hello world'");
}
}
This fails to compile, and yields the error:
The type Linux must implement the inherited abstract method OS.run(String)
Now, anything could expected to be able to pass a String into any instance of the OS interface, and you could certainly do that with Linux.
I see no reason why the second one fails to compile. Of the consequences of having Java compile the second program, am I missing something that makes this prohibitive?
What you are doing for the second case is method over-loading.
Signature of a method is "method-name" and "number and types of arguments"
In the second case you are changing the type of argument which compiler things is another method, and ask you to implement the abstracted (unimplemented) methods. And if you implement the methods present in the interface public void run(String code) then this method public void run(Object code) will be treated as an overloaded method.
NOTE: Method over-riding is never based on the return type of the method. As return type is not considered as method's signature
You cannot pass an instance of base class Object in place of an instance of class String but the reverse is valid. In your interface OS, the parameter to the run method is of type String and in the implementation class you are generalising the parameter to be of type Object which is not allowed. Hence, the compiler complains.
You say "Now, anything could expected to be able to pass a String into any instance of the OS interface, and you could certainly do that with Linux." => Problem is that you could, but are not required to.
Consider this: as Linux version of the method takes an Object as a parameter, you could try and pass a Collection, for example. Thus you would not respect the interface, which explicitely restricts the parameter to being a String. That is why Linux version of the method is not considered to be the "child" of OS version.
And as each method in the interface needs to have its "child", the compiler complains you did not implement a "child" for OS.run(String)

trying to understand implicit superinterfaces

Sorry to bring back the dead. But I still don't clearly understand what this section of specification states.
If an interface has no direct superinterfaces, then the interface
implicitly declares a public abstract member method m with signature
s, return type r, and throws clause t corresponding to each public
instance method m with signature s, return type r, and throws clause t
declared in Object, unless a method with the same signature, same
return type, and a compatible throws clause is explicitly declared by
the interface. It is a compile-time error if the interface explicitly
declares such a method m in the case where m is declared to be final
in Object.
Given
interface Testing
{
void test();
}
public class Test{
public static void main(String[] args) {
Testing t = new Testing(){
#Override
public void test(){
}
};
t.test();
t.toString();
}
}
Now as the spec states that the above will change to
interface Testing
{
void test();
String toString();
//other non-final methods of Object
}
public class Test{
public static void main(String[] args) {
Testing t = new Testing(){
#Override
public void test(){
}
};
t.test();
t.toString();
}
}
Also. please confirm if there is an hierarchy of interfaces then all of them get these abstract methods.
What it means is that every class extends Object (at some point in its class heirarchy). However, interfaces do not extend Object. This is to avoid the problems that arise from multiple inheirtance.
Since interfaces do not extend Object that would mean we were unable to use methods like toString if the type (not class) of the object we had access to was an interface. But we know those methods must be available since all classes at some point extend from Object. Therefore, to get around this problem all of Object's not final methods are implicitly declared in all interfaces that have no superinterfaces. These contracts of these methods are always satisfied since all classes must at some point extend from Object.
TL;DR -- it's a trick to make sure we can access the methods made available by Object when we have an instance of some class stored in variable that's type is an interface (eg. Serializable)
edit: To answer your question, You're slightly off. All non-final methods of Object are added to an interface (whether they are used or not) if that interface has no parent interface AND for each method to added: that there is no matching method is explicitly declared by the interface.
As long as there is no super interface to an interface it gets the implicit declaration of the Object class methods. As long as these methods are included in the interface. Every interface that either extends or implements this interface doesn't see much difference between the methods that are explicitly declared by this interface or it got implicitly. That point forward that interface is as good as declared them explicitly.

Categories