I've got some classes which include toString functions which work very well as:
snipped of declaration:
public String toString() {
return "Port info: "+myPort.variable;
}
snipped of main():
Port myPort;
myPort.fillInfo();
system.out.println(myPort);
output:
"Port info: 123"
I'm trying to replace all my system.out.println(myPort) calls with myWindow.println(myPort) calls where myWindow contains:
public void println(String toPrint)
{
textArea.append(toPrint+"\n"); //or insert
}
However, I'm getting:
The method println(String) in the type window is not applicable for the arguments (Port)
In other words, my declaration is expecting the String type, and I'm trying to pass it the Port type.
Somehow, system.out.println() will take any class that's got a toString() declared.
How does system.out.println take any class and print it out, and run its toString() method if it exists? And, more to the point, how can I replicate this functionality for my own println() function?
Change your Window to
public void println(Object obj)
{
textArea.append(obj +"\n");
}
PrintStream.println has an overload that takes an Object argument. You can make your println do the same.
First, please don't use \n as a line separator (it isn't portable). In addition to overloading println(Object), you could make your method generic. Something like
public <T> void println(T obj)
{
textArea.append(String.format("%s%n", obj));
}
or
public void println(Object obj)
{
textArea.append(String.format("%s%n", obj));
}
or
public void println(Object obj)
{
textArea.append((obj == null ? "null" : obj.toString())
+ System.lineSeparator());
}
The problem is that System.out has a method to print to console an object as it contains for all primitive data types. The thing about this is that as all methods have the same name and just change the data type of the parameter you want to print, you think you can pass an object by a string and is not. The method .println() automatically takes which passes an object. Within this method .println() he takes the object that you indicated by parameters and calls his method .toString() to obtain the string representation of the object and printed on the console.
If you want to print any type of object you must declare your parameter as object type and invoke the method .toString() from the object and print that 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.
We know that when we pass any object like list, map or any object to System.out.println(), it will get the list.toString(), map.toString(), object.toString()as parameter automatically.
I want to create user defined function like this.
static void print(String s)
{
//someprocessing
}
But for this method when I pass any object to it should be converted explicitly to string.
for example,
print(list.toString());
But I want to define a method that will implicitly convert object to its toString. Can anyone tell me how to do that in java ?
I did something Like this to solve this !
static void print(Object o)
{
System.out.println(o.toString());
// String rep = o.toString();
}
So I can use it on any Object type except for primitives.
I have the following classes defined:
class BaseClass {
public String toString()
{
return "I am a: " + getClass().getName();
}
}
class DerivedClass {
public String toString()
{
return super.toString();
}
}
In my main() function I have the following code:
BaseClass b = new BaseClass();
DerivedClass d = new DerivedClass();
System.out.println(b);
System.out.println(d); // not sure why/how this works!
As expected, I do get the correct run-time class types when this code runs:
I am a: BaseClass
I am a: DerivedClass
My question is, how exactly does the call to toString() in my DerivedClass work? In my DerivedClass override of toString(), I'm making a call to super.toString() which seems like it should actually return "I am a: BaseClass" because we're calling toString() on the parent class.
I suspect it may have something to do with the fact that my base class toString() utilizes getClass().getName(), so that when I call it through a subclass object, Java must be detecting my actual object type - but I don't know how it knows to do that...
Sorry if this sounds like a noob question, but I'm still wrapping my head around the concept of polymorphism. If anyone could explain why this works the way it does, I'd appreciate any insight.
getClass() is a polymorphic method. It returns the actual concrete class of the object on which it is called. Since d id of type DerivedClass, its getClass() method returns DerivedClass.class.
You would get the result you expect if the method implementation was
return "I am a: " + BaseClass.class.getName();
Imagine your classes looked like this:
class BaseClass {
#Override
public String toString() {
return "I am a: " + getClass().getName();
}
public Class<?> getClass() {
return BaseClass.class;
}
}
class DerivedClass extends BaseClass {
#Override
public Class<?> getClass() {
return DerivedClass.class;
}
}
Because of the way overriding works, getClass() will always return DerivedClass.class when invoked on an instance of DerivedClass, even when called from the superclass BaseClass. Calling super.toString() doesn't change that, and is in fact entirely unnecessary, since the superclass implementation is inherited by default.
Note that this is just a demonstration of what you can expect when calling getClass(). In real life, getClass() is actually a final native method. Overriding it is not possible or necessary.
Your first question is:
System.out.println(d); // not sure why/how this works!
And it is a good question! After all, you are passing the println method a reference, d, to an instance of DerivedClass. Why would that result in actually calling a method that is named toString()?
The answer to this question lies in the Javadoc for the appropriate println method. The compiler (javac) correctly compiles your code to say that you are interested in calling the println method that takes in an Object. Note that println is an overloaded method and compiler must resolve the right method based on passed argument(s). In this case, the method resolves to println(Object x) which states:
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
Then you visit the String.valueOf() method and see:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Bingo! That closes the first loop, either the BaseClass's toString() is called, or DerivedClass's.
The actual reason why the d's getClass() is called has to do with the value of the this reference. As you perhaps know, every instance method in Java (like the toString() one) receives an invisible parameter called the this reference in addition to the arguments that are declared. In this particular case, since the this reference points to d, all the methods are invoked on that reference. The class of d is clearly DerivedClass.
public class Curiosity {
public void toString()//error because of this specific method name
{
System.out.println("method is successfully implemented");
}
}
How can i use a method of the same name "toString()" if i want to ?
Do I have to give its return type as String if not what should i do to change its return type like suppose if i want to use a void return type for toString does java allow that ?
toString() method must return a String. That's the only way to override Object's toString().
public String toString()
{
return "method is successfully implemented";
}
If you wish to use the same name but not override Object's toString, you can overload the name toString by adding arguments, thus changing the signature of your method.
Example :
public void toString (String something)
{
System.out.println("method is successfully implemented " + something);
}
You are trying to overload toString() method in a wrong manner
Overloaded methods are differentiated by the number and the type of the arguments passed into the method. In the code sample, draw(String s) and draw(int i) are distinct and unique methods because they require different argument types.
You cannot declare more than one method with the same name and the same number and type of arguments, because the compiler cannot tell them apart.
The compiler does not consider return type when differentiating methods, so you cannot declare two methods with the same signature even if they have a different return type.
The only way to use toString() in your class is by keeping the return type as String
public String toString()
{
//your code here
}
That is how it is defined in Objectclass and if you wish to override it you will have to use the exact signature
or if you still wish to use the method name as toString what you can do is change the method's signature.
A method's signature includes method's name and the parameters.
Remember that return type is not a part of a method's signature
You can look at the source code of the java.lang.Object.
The toString method have a return value in String type. You can't have another method which's name is toString but return type is not String.
Actually, it's forbidden in Java in any inheritance relationship. When you call the method, the compiler only cares the name and the parameters. So how can it distinguishes the methods of the same name but with the different return type?
If I am printing an object of the class then it is printing the toString() method implementation even I am not writing the toString() method so what are the implementation,how it is calling toString() internally?
You're not explicitly calling toString(), but implicitly you are:
See:
System.out.println(foo); // foo is a non primitive variable
System is a class, with a static field out, of type PrintStream. So you're calling the println(Object) method of a PrintStream.
It is implemented like this:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
As we see, it's calling the String.valueOf(Object) method.
This is implemented as follows:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
And here you see, that toString() is called.
Every object in Java IS-A(n) Object as well. Hence, if a toString() implementation has not been provided by a class the default Object.toString() gets invoked automatically.
Object.toString()'s default implementation simply prints the object's class name followed by the object's hash code which isn't very helpful. So, one should usually override toString() to provide a more meaningful String representation of an object's runtime state.
even I am not writing the toString() method so what are the implementation,how it is calling toString() internally?
toString() is one of the few methods (like equals(), hashCode() etc.) that gets called implicitly under certain programmatic situations like (just naming a few)
printing an object using println()
printing a Collection of objects (toString() is invoked on all the elements)
concatenation with a String (like strObj = "My obj as string is " + myObj;)
Everything inherits from Object, so the toString on Object will be called if you have not defined one.
toString() method is present in Object class, so when u put obj in System.out.println(obj);, impliciyly it will call toString() present in Object class since every user created class will implicitly inherits Object class so as ur newly created class, that means that toString() is available in ur class so it will print something like for example: "PkgNamePackage.Classname#12cf4"
However if u explicitely override toString method and give ur own implementation then it will written the string what ever u give in Overriden tostring method();
ex:
public class DogArray {
#Override
public String toString() {
return "Im the newly created Object";
}
public static void main(String args[]) {
DogArray d1 = new DogArray();
System.out.println(d1);
}
}
output: Im the newly created Object
In java object class is super class to the each and every class.whenever your passing parameter to the system.out.println internally object class to string method will be excuted.it returns class name#reference value given but as per our application requirement object class to string method will override in collection and string class.it returns their content.