Using getClass().getName() in toString() methods - java

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.

Related

Difference between wrapper class reference and user defines class reference in java

Suppose I have a custom class, say Test.
Test test = new Test(); // test is the reference.
Now when I print the value of test, it returns the hashcode .
Now consider,
Integer i = new Integer(10);
When I print the value of i, it returns 10.
Can someone help me to understand what exactly is the difference here? I believe both are object references, but for wrapper class reference, it returns the value of the object it is pointing to.
When you create a new class, it inherits the method toString() from Object. Integer class overrides that method to return the inner value.
When printing, there is an implicit call to toString() method.
By default (in for your Test class) it uses the one inside Object class. For Integer, it convert the Integer to a String in 10-base.
Your Test class is using Object class's toString() method which prints hashCode. But for Integer class, toString method is overrided. You can see Integer.java here
user defined reference is an object,if you print that object means you may get some hash code because every class extends Object class,so your also have the property (method) tostring().
Wrapper class wraps its respective primitive data type
Integer i = new Integer(10);
and
i=10;
both same in value.
When you call System.out.println(Object) (or, more generally, PrintStream.println(Object)):
This method calls at first String.valueOf(x)
String.valueOf(Object) returns:
if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
Neither of your objects are null, so the toString() method of the instances is called.
In the case of Integer:
The value is converted to signed decimal representation and returned as a string
In the case of Test, unless you've explicitly overridden it (or a superclass has overridden it), you will call Object.toString():
[T]his method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
If this isn't the desired behaviour, override toString() in Test:
class Test {
#Override public String toString() {
// ... Your implementation.
}
}
Whenever you print the object Java will invoke the toString() method. The default implementation of toString() available in Object Class. Object is the base class for the all the Object in java.
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
It will print the class Name with full package path # and HashCode of the object.
The test class doesn't override the toString() method. But all the wrapper class in java override the toString().so when You invoke the Integer method it invoke the toString() implemented in Integer class.

Override toString method in Java

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?

How an object will call toString method implicitly?

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.

java - the use of 'this' within the brackets of a method

System.out.println(this);
Why would you use 'this' in the brackets? Is it for printing the references? Or as in the code below for comparing if the object points to the same reference?
public void compareDrzewo(Drzewo tree)
{ if (tree == this)
{ System.out.println("true"); }
else { System.out.println("false"); }
main method code
Drzewo name1 = name2;
name1.compareDrzewo(name2);
The other examples of the use of 'this.' are quite straight forward (inner class etc.) Please comment only on this or similar use.
That instance has a toString() method associated with it, which means it will invoke it to print out meaningful information, or it uses Object's toString() (meaning it'll print out a memory location, which is much less useful).
System.out.println(this)
is the same as
System.out.println(this.toString());
So if the class of which this is an instance overrides the toString method, that line of code would be meaningful.
You use this to refer to the current object.
One example is when your want to refer to the current instance of your class, so if you need to call a method with your class, for example something.equals(this) or something == this.
Another example is explicitly specifiying a class instance of a variable rather than a local instance, for example a setter:
public void setMyVar(String myVar) {
this.myVar = myVar;
}
So myVar is the variable declared in the method, this.myVar is the variable declared in your class.

Instantiating a class, toString terms

I have two classes :
import android.cla;
public class CW {
public static void main(String [] args){
System.out.println(new cla());
}
}
public class Cl {
#Override
public String toString(){
return "LOL";
}
}
In the first class I'm calling the objects toString() method, which has been overriden and printing it to console. It clearly returns "LOL";
I have two questions :
Is it possible to return data while instantiating like this (new cla()) without overriding the objects toString() method; and
What is the proper term for instantiating classes like this (new cla()), that's without declaration like : Object l = new cla()
Thanks. Please correct me on the proper terms.
1 - No it isn't. A 'constructor' is a special method on the class that always returns an object instance of the class. The whole point of the constructor is to return the object. So no, it can't return anything else.
1a - The reason that System.out.println calls the toString method is because you are asking it to print out that object to the screen, and the toString method is the method chosen by the authors of println (and the Java language in general) to give a string representation of the object.
2 - That way of writing isn't really called anything. It's just an expression that you're passing as an 'actual parameter' to the println method. True, it's an expression that instantiates a new object, but it's no different to println("a string"). You could call it an anonymous object if you really wanted to.
2a - (old answer that doesn't actually answer your question but I'll keep it here) That's just called 'using a less derived reference† to a class'. Beware you can only call methods on the type of the reference, so if you added extra methods to your Cl class you couldn't call them from an Object reference. Look into Liskov substitution principle.
† 'less derived' or 'supertype' or 'superclass' or 'more general class' etc...

Categories