I got an arraylist and a method to add an object to the arraylist. Currently im using overloaded methods to differentiate between different kinds of object. Is there a way to use an undefined object as a parameter for the method and differentiate inside of the method what kind of an object it is?
By "undefined object as a parameter", I assume you mean that you're looking to write a function that doesn't specify the type of the object in the function declaration, allowing you to only have one function.
This can be done with generics.
Instead of:
static void func(String str)
{
System.out.println("The string is: "+str);
}
static void func(Integer integer)
{
System.out.println("The integer is: "+integer);
}
you can have:
static <T> void func(T value)
{
if (value instanceof Integer)
System.out.println("The integer is: "+value);
else if (value instanceof String)
System.out.println("The string is: "+value);
else
System.out.println("Type not supported!! - "+value.getClass());
}
Test:
func("abc"); // The string is: abc
func(3); // The integer is: 3
func(3.0); // Type not supported!! - class java.lang.Double
See Java generics for more information.
One way you can do it is pass two parameters. First parameter is the Object you need to pass and second parameter is the indicator of which type of Object you are passing.
public void TestFunc(Object obj1, String type){}
Of course, there can be better ways than using a String, we can use Enums and some other mechanism. You can also use InstanceOf to differentiate if you don't want to pass additional parameter.
By "undefined object" I assume you mean null. You can cast null to a specific type of object and the compiler will know which overloaded method to bind to the call:
public void method(String s) { . . . }
public void method(Integer s) { . . . }
public void caller() {
method((String) null);
method((Integer) null);
}
If you have an object of undefined type, you can use instanceof operator to test what type it is, or getClass() to obtain the class object itself. If you have a null value of unknown type, there's not much you can do other than redefining your method signature to accept an additional argument of type Class.
However, if the comment by Dukeling is accurate and by "undefined object" you mean "an object of unknown type", you should look into using Java generics. Generics let you write a single method that works with a range of object types.
public <T> void method(T arg) { . . . }
public void caller() {
method("String"); // String arg
method(0); // Integer arg
}
Start with the Java generics tutorial for more information.
Related
I have added three methods with parameters:
public static void doSomething(Object obj) {
System.out.println("Object called");
}
public static void doSomething(char[] obj) {
System.out.println("Array called");
}
public static void doSomething(Integer obj) {
System.out.println("Integer called");
}
When I am calling doSomething(null) , then compiler throws error as ambiguous methods. So is the issue because Integer and char[] methods or Integer and Object methods?
Java will always try to use the most specific applicable version of a method that's available (see JLS §15.12.2).
Object, char[] and Integer can all take null as a valid value. Therefore all 3 version are applicable, so Java will have to find the most specific one.
Since Object is the super-type of char[], the array version is more specific than the Object-version. So if only those two methods exist, the char[] version will be chosen.
When both the char[] and Integer versions are available, then both of them are more specific than Object but none is more specific than the other, so Java can't decide which one to call. In this case you'll have to explicitly mention which one you want to call by casting the argument to the appropriate type.
Note that in practice this problem occurs far more seldom than one might think. The reason for this is that it only happens when you're explicitly calling a method with null or with a variable of a rather un-specific type (such as Object).
On the contrary, the following invocation would be perfectly unambiguous:
char[] x = null;
doSomething(x);
Although you're still passing the value null, Java knows exactly which method to call, since it will take the type of the variable into account.
Each pair of these three methods is ambiguous by itself when called with a null argument. Because each parameter type is a reference type.
The following are the three ways to call one specific method of yours with null.
doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);
May I suggest to remove this ambiguity if you actually plan to call these methods with null arguments. Such a design invites errors in the future.
null is a valid value for any of the three types; so the compiler cannot decide which function to use. Use something like doSomething((Object)null) or doSomething((Integer)null) instead.
Every class in Java extends Object class.Even Integer class also extends Object. Hence both Object and Integer are considered as Object instance. So when you pass null as a parameter than compiler gets confused that which object method to call i.e. With parameter Object or parameter Integer since they both are object and their reference can be null. But the primitives in java does not extends Object.
I Have tried this and when there is exactly one pair of overloaded method and one of them has a parameter type Object then the compiler will always select the method with more specific type. But when there is more than one specific type, then the compiler throws an ambiguous method error.
Since this is a compile time event, this can only happen when one intentionally passes null to this method. If this is done intentionally then it is better to overload this method again with no parameter or create another method altogether.
class Sample{
public static void main (String[] args) {
Sample s = new Sample();
s.printVal(null);
}
public static void printVal(Object i){
System.out.println("obj called "+i);
}
public static void printVal(Integer i){
System.out.println("Int called "+i);
}
}
The output is Int called null and so ambiguity is with char[] and Integer
there is an ambiguity because of doSomething(char[] obj) and doSomething(Integer obj).
char[] and Integer both are the same superior for null that's why they are ambiguous.
I have added three methods with parameters:
public static void doSomething(Object obj) {
System.out.println("Object called");
}
public static void doSomething(char[] obj) {
System.out.println("Array called");
}
public static void doSomething(Integer obj) {
System.out.println("Integer called");
}
When I am calling doSomething(null) , then compiler throws error as ambiguous methods. So is the issue because Integer and char[] methods or Integer and Object methods?
Java will always try to use the most specific applicable version of a method that's available (see JLS §15.12.2).
Object, char[] and Integer can all take null as a valid value. Therefore all 3 version are applicable, so Java will have to find the most specific one.
Since Object is the super-type of char[], the array version is more specific than the Object-version. So if only those two methods exist, the char[] version will be chosen.
When both the char[] and Integer versions are available, then both of them are more specific than Object but none is more specific than the other, so Java can't decide which one to call. In this case you'll have to explicitly mention which one you want to call by casting the argument to the appropriate type.
Note that in practice this problem occurs far more seldom than one might think. The reason for this is that it only happens when you're explicitly calling a method with null or with a variable of a rather un-specific type (such as Object).
On the contrary, the following invocation would be perfectly unambiguous:
char[] x = null;
doSomething(x);
Although you're still passing the value null, Java knows exactly which method to call, since it will take the type of the variable into account.
Each pair of these three methods is ambiguous by itself when called with a null argument. Because each parameter type is a reference type.
The following are the three ways to call one specific method of yours with null.
doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);
May I suggest to remove this ambiguity if you actually plan to call these methods with null arguments. Such a design invites errors in the future.
null is a valid value for any of the three types; so the compiler cannot decide which function to use. Use something like doSomething((Object)null) or doSomething((Integer)null) instead.
Every class in Java extends Object class.Even Integer class also extends Object. Hence both Object and Integer are considered as Object instance. So when you pass null as a parameter than compiler gets confused that which object method to call i.e. With parameter Object or parameter Integer since they both are object and their reference can be null. But the primitives in java does not extends Object.
I Have tried this and when there is exactly one pair of overloaded method and one of them has a parameter type Object then the compiler will always select the method with more specific type. But when there is more than one specific type, then the compiler throws an ambiguous method error.
Since this is a compile time event, this can only happen when one intentionally passes null to this method. If this is done intentionally then it is better to overload this method again with no parameter or create another method altogether.
class Sample{
public static void main (String[] args) {
Sample s = new Sample();
s.printVal(null);
}
public static void printVal(Object i){
System.out.println("obj called "+i);
}
public static void printVal(Integer i){
System.out.println("Int called "+i);
}
}
The output is Int called null and so ambiguity is with char[] and Integer
there is an ambiguity because of doSomething(char[] obj) and doSomething(Integer obj).
char[] and Integer both are the same superior for null that's why they are ambiguous.
I have added three methods with parameters:
public static void doSomething(Object obj) {
System.out.println("Object called");
}
public static void doSomething(char[] obj) {
System.out.println("Array called");
}
public static void doSomething(Integer obj) {
System.out.println("Integer called");
}
When I am calling doSomething(null) , then compiler throws error as ambiguous methods. So is the issue because Integer and char[] methods or Integer and Object methods?
Java will always try to use the most specific applicable version of a method that's available (see JLS §15.12.2).
Object, char[] and Integer can all take null as a valid value. Therefore all 3 version are applicable, so Java will have to find the most specific one.
Since Object is the super-type of char[], the array version is more specific than the Object-version. So if only those two methods exist, the char[] version will be chosen.
When both the char[] and Integer versions are available, then both of them are more specific than Object but none is more specific than the other, so Java can't decide which one to call. In this case you'll have to explicitly mention which one you want to call by casting the argument to the appropriate type.
Note that in practice this problem occurs far more seldom than one might think. The reason for this is that it only happens when you're explicitly calling a method with null or with a variable of a rather un-specific type (such as Object).
On the contrary, the following invocation would be perfectly unambiguous:
char[] x = null;
doSomething(x);
Although you're still passing the value null, Java knows exactly which method to call, since it will take the type of the variable into account.
Each pair of these three methods is ambiguous by itself when called with a null argument. Because each parameter type is a reference type.
The following are the three ways to call one specific method of yours with null.
doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);
May I suggest to remove this ambiguity if you actually plan to call these methods with null arguments. Such a design invites errors in the future.
null is a valid value for any of the three types; so the compiler cannot decide which function to use. Use something like doSomething((Object)null) or doSomething((Integer)null) instead.
Every class in Java extends Object class.Even Integer class also extends Object. Hence both Object and Integer are considered as Object instance. So when you pass null as a parameter than compiler gets confused that which object method to call i.e. With parameter Object or parameter Integer since they both are object and their reference can be null. But the primitives in java does not extends Object.
I Have tried this and when there is exactly one pair of overloaded method and one of them has a parameter type Object then the compiler will always select the method with more specific type. But when there is more than one specific type, then the compiler throws an ambiguous method error.
Since this is a compile time event, this can only happen when one intentionally passes null to this method. If this is done intentionally then it is better to overload this method again with no parameter or create another method altogether.
class Sample{
public static void main (String[] args) {
Sample s = new Sample();
s.printVal(null);
}
public static void printVal(Object i){
System.out.println("obj called "+i);
}
public static void printVal(Integer i){
System.out.println("Int called "+i);
}
}
The output is Int called null and so ambiguity is with char[] and Integer
there is an ambiguity because of doSomething(char[] obj) and doSomething(Integer obj).
char[] and Integer both are the same superior for null that's why they are ambiguous.
The default return of an object in Java is to return the toString method, is there a way to change this behavior to for example return a number or some other type or is this just a core unchangeable component of the language?
Test test = new Test();
blankMethod(test);
I am not sure why people are saying my assumption is wrong... if I Override the toString method of object it will output that new toString method...
#Override
public String toString() {
System.out.println("This method is run when the object is used as a parameter");
return "test";
}
The default return of an object in Java is to return the toString method
That's how PrintStream.println works. Any object in java extends java.lang.Object and therefore inherits Object behavior. In particular, any method which takes Object as an argument, also can take any object of another type. However, you can override any public or protected method defined in Object. In your case you should override toString() method in Test class, otherwise if you pass Test object to PrintWriter.println(), it'll use toString from superclass (Object in your case). So, if i understood your question correctly, the answer is no.
Update: your terminology is wrong. There is no default return of an object in java. Returning Object.toString is the default behavior only for PrintStream.println(Object).
Update2: more widely, Java doesn't support implicit type conversion except upcasting. In your case, Test extends Object, but it doesn't extend String (actually, String is final and therefore you can't extend it). So, if you try to pass Test object to method which only takes String, you'll get compilation error because String and Test belong to different branches of class hierarchy.
You are actually calling
PrintStream.println(Object x)
instead of
public void println(String x)
The PrintStream.println(Object x) implementation is below:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
The method calls String.valueOf(x) whose implementation is below:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Note that the Object.toString() method is being called.
Notes on implicit conversion
An Object is only implicitly converted to a String using the toString method when the string concatenation operator (+) is invoked. More exactly the conversion works as follows:
A value x of primitive type T is first converted to a reference value...
This reference value is then converted to type String by string conversion.
Now only reference values need to be considered.
If the reference is null, it is converted to the string "null" (four
ASCII characters n, u, l, l). Otherwise, the conversion is performed
as if by an invocation of the toString method of the referenced object
with no arguments; but if the result of invoking the toString method
is null, then the string "null" is used instead.
The toString method is defined by the primordial class Object"
Java Language Specification 15.18.1
One language (of many) that expand on the idea of implicit conversions is Scala which allows one to bring a conversion (e.g., A -> B) into scope which is then invoked whenever some type (A) is passed as an argument when a different type (B) is required.
This answers "why people are saying my assumption is wrong".
Here is a simple program:
public class Test {
public String toString(){
return "I am a Test object.";
}
public int add(int a, int b){
return a+b;
}
public static void main(String[] args) {
Test object = new Test();
System.out.println(object);
System.out.println(object.add(2,2));
System.out.println(adder(object));
}
public static int adder(Test test){
return test.add(3,5);
}
}
Output:
I am a Test object.
4
8
The System.out.println method has to turn its argument into a String, one way or another. If it is passed an object reference, it uses its toString() method. If it is passed a primitive, such as an int expression, it converts it in an appropriate way.
It is nothing to do with what is being returned.
It also has nothing to do with any automatic conversion on passing a reference as an argument. See the third line of output, which depends on using the Test reference I passed to adder as a Test, not a String.
If you want to change what println prints, do what I did above, and pass it something different.
So here it is this example
public static void main(String[] args) {
new Stuff(null);
new Stuff("a");
new Stuff(1);
}
and class Stuff is defined as follow
public class Stuff {
Stuff(Object o){
System.out.println("object");
}
Stuff(String s){
System.out.println("string");
}
}
The output is
string
string
object
How does Java tell the null is a String? If I change Stuff to
public class Stuff {
Stuff(String s){
System.out.println("string");
}
Stuff(Integer o){
System.out.println("Integer");
}
}
I get compilation error for Stuff(null):
The constructore Stuff(String) is ambigous.
Again, why does Java "decide" null is a String?
The compiler first lists all applicable methods. In your case, both are applicable.
It then tries to find a method which is more specific than the other(s).
In your first example, String is a subclass of Object and is therefore more specific.
In your second example, both methods are applicable (String and Integer) but neither is more specific than the other (String is not a subclass of Integer which is not a subclass of String). So there is an ambiguity, hence the compiler error.
The full algorithm to determine which method should be chosen is defined in the JLS.
Because String is more specific then Object. Java always tries to use more specific match when figuring out which constructor or method to use.