Can anybody explain to me the concept of the toString() method, defined in the Object class? How is it used, and what is its purpose?
From the Object.toString docs:
Returns a string representation of the
object. In general, the toString
method returns a string that
"textually represents" this object.
The result should be a concise but
informative representation that is
easy for a person to read. It is
recommended that all subclasses
override this method.
The toString method for class Object
returns a string consisting of the
name of the class of which the object
is an instance, the at-sign character
`#', and the unsigned hexadecimal
representation of the hash code of the
object. In other words, this method
returns a string equal to the value
of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
Example:
String[] mystr ={"a","b","c"};
System.out.println("mystr.toString: " + mystr.toString());
output:- mystr.toString: [Ljava.lang.String;#13aaa14a
Use of the String.toString:
Whenever you require to explore the constructor called value in the String form, you can simply use String.toString...
for an example...
package pack1;
import java.util.*;
class Bank {
String n;
String add;
int an;
int bal;
int dep;
public Bank(String n, String add, int an, int bal) {
this.add = add;
this.bal = bal;
this.an = an;
this.n = n;
}
public String toString() {
return "Name of the customer.:" + this.n + ",, "
+ "Address of the customer.:" + this.add + ",, " + "A/c no..:"
+ this.an + ",, " + "Balance in A/c..:" + this.bal;
}
}
public class Demo2 {
public static void main(String[] args) {
List<Bank> l = new LinkedList<Bank>();
Bank b1 = new Bank("naseem1", "Darbhanga,bihar", 123, 1000);
Bank b2 = new Bank("naseem2", "patna,bihar", 124, 1500);
Bank b3 = new Bank("naseem3", "madhubani,bihar", 125, 1600);
Bank b4 = new Bank("naseem4", "samastipur,bihar", 126, 1700);
Bank b5 = new Bank("naseem5", "muzafferpur,bihar", 127, 1800);
l.add(b1);
l.add(b2);
l.add(b3);
l.add(b4);
l.add(b5);
Iterator<Bank> i = l.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
}
}
... copy this program into your Eclipse, and run it... you will get the ideas about String.toString...
The toString() method returns a textual representation of an object. A basic implementation is already included in java.lang.Object and so because all objects inherit from java.lang.Object it is guaranteed that every object in Java has this method.
Overriding the method is always a good idea, especially when it comes to debugging, because debuggers often show objects by the result of the toString() method. So use a meaningful implementation but use it for technical purposes. The application logic should use getters:
public class Contact {
private String firstName;
private String lastName;
public Contact (String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {return firstName;}
public String getLastName() {return lastName;}
public String getContact() {
return firstName + " " + lastName;
}
#Override
public String toString() {
return "["+getContact()+"]";
}
}
It may optionally have uses within the context of an application but far more often it is used for debugging purposes. For example, when you hit a breakpoint in an IDE, it's far easier to read a meaningful toString() of objects than it is to inspect their members.
There is no set requirement for what a toString() method should do. By convention, most often it will tell you the name of the class and the value of pertinent data members. More often than not, toString() methods are auto-generated in IDEs.
Relying on particular output from a toString() method or parsing it within a program is a bad idea. Whatever you do, don't go down that route.
toString() returns a string/textual representation of the object.
Commonly used for diagnostic purposes like debugging, logging etc., the toString() method is used to read meaningful details about the object.
It is automatically invoked when the object is passed to println, print, printf, String.format(), assert or the string concatenation operator.
The default implementation of toString() in class Object returns a string consisting of the class name of this object followed by # sign and the unsigned hexadecimal representation of the hash code of this object using the following logic,
getClass().getName() + "#" + Integer.toHexString(hashCode())
For example, the following
public final class Coordinates {
private final double x;
private final double y;
public Coordinates(double x, double y) {
this.x = x;
this.y = y;
}
public static void main(String[] args) {
Coordinates coordinates = new Coordinates(1, 2);
System.out.println("Bourne's current location - " + coordinates);
}
}
prints
Bourne's current location - Coordinates#addbf1 //concise, but not really useful to the reader
Now, overriding toString() in the Coordinates class as below,
#Override
public String toString() {
return "(" + x + ", " + y + ")";
}
results in
Bourne's current location - (1.0, 2.0) //concise and informative
The usefulness of overriding toString() becomes even more when the method is invoked on collections containing references to these objects. For example, the following
public static void main(String[] args) {
Coordinates bourneLocation = new Coordinates(90, 0);
Coordinates bondLocation = new Coordinates(45, 90);
Map<String, Coordinates> locations = new HashMap<String, Coordinates>();
locations.put("Jason Bourne", bourneLocation);
locations.put("James Bond", bondLocation);
System.out.println(locations);
}
prints
{James Bond=(45.0, 90.0), Jason Bourne=(90.0, 0.0)}
instead of this,
{James Bond=Coordinates#addbf1, Jason Bourne=Coordinates#42e816}
Few implementation pointers,
You should almost always override the toString() method. One of the cases where the override wouldn't be required is utility classes that group static utility methods, in the manner of java.util.Math. The case of override being not required is pretty intuitive; almost always you would know.
The string returned should be concise and informative, ideally self-explanatory.
At least, the fields used to establish equivalence between two different objects i.e. the fields used in the equals() method implementation should be spit out by the toString() method.
Provide accessors/getters for all of the instance fields that are contained in the string returned. For example, in the Coordinates class,
public double getX() {
return x;
}
public double getY() {
return y;
}
A comprehensive coverage of the toString() method is in Item 10 of the book, Effective Java™, Second Edition, By Josh Bloch.
Whenever you access an Object (not being a String) in a String context then the toString() is called under the covers by the compiler.
This is why
Map map = new HashMap();
System.out.println("map=" + map);
works, and by overriding the standard toString() from Object in your own classes, you can make your objects useful in String contexts too.
(and consider it a black box! Never, ever use the contents for anything else than presenting to a human)
Correctly overridden toString method can help in logging and debugging of Java.
Coding:
public class Test {
public static void main(String args[]) {
ArrayList<Student> a = new ArrayList<Student>();
a.add(new Student("Steve", 12, "Daniel"));
a.add(new Student("Sachin", 10, "Tendulkar"));
System.out.println(a);
display(a);
}
static void display(ArrayList<Student> stu) {
stu.add(new Student("Yuvi", 12, "Bhajji"));
System.out.println(stu);
}
}
Student.java:
public class Student {
public String name;
public int id;
public String email;
Student() {
}
Student(String name, int id, String email) {
this.name = name;
this.id = id;
this.email = email;
}
public String toString(){ //using these toString to avoid the output like this [com.steve.test.Student#6e1408, com.steve.test.Student#e53108]
return name+" "+id+" "+email;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public int getId(){
return id;
}
public void setId(int id){
this.id=id;
}
public String getEmail(){
return email;
}
public void setEmail(String email){
this.email=email;
}
}
Output:
[Steve 12 Daniel, Sachin 10 Tendulkar]
[Steve 12 Daniel, Sachin 10 Tendulkar, Yuvi 12 Bhajji]
If you are not used toString() in Pojo(Student.java) class,you will get an output like [com.steve.test.Student#6e1408, com.steve.test.Student#e53108].To avoid these kind of issue we are using toString() method.
Apart from what cletus answered with regards to debugging, it is used whenever you output an object, like when you use
System.out.println(myObject);
or
System.out.println("text " + myObject);
The main purpose of toString is to generate a String representation of an object, means the return value is always a String. In most cases this simply is the object's class and package name, but on some cases like StringBuilder you will got actually a String-text.
/**
* This toString-Method works for every Class, where you want to display all the fields and its values
*/
public String toString() {
StringBuffer sb = new StringBuffer();
Field[] fields = getClass().getDeclaredFields(); //Get all fields incl. private ones
for (Field field : fields){
try {
field.setAccessible(true);
String key=field.getName();
String value;
try{
value = (String) field.get(this);
} catch (ClassCastException e){
value="";
}
sb.append(key).append(": ").append(value).append("\n");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return sb.toString();
}
If you learn Python first and then Java. I think it plays the same role as __str__() method in Python, it is a magic method like __dict__() and __init__() but to refer to a string representing the the object.
the toString() converts the specified object to a string value.
I noticed a scenario today. When we pass a parameter on private methods, the entity will return the revised values but not primitives.
Here is my sample code,
/**
* #author gowthami
*
*/
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
String s = "gowth";
System.out.println("before " + s);
concateMe(s, "ami");
System.out.println("after " + s);
BeanTest bt = new BeanTest();
bt.setId("1");
System.out.println("before");
System.out.println(bt.getId());
System.out.println(bt.getName());
setBeanTestName(bt, "gowthami");
System.out.println("after");
System.out.println(bt.getId());
System.out.println(bt.getName());
String st = new String("gowth");
System.out.println("before " + st);
concateMe(st, "ami");
System.out.println("after " + st);
}
private static void setBeanTestName(BeanTest bt, String string) {
bt.setName(string);
}
private static void concateMe(String s, String string) {
s = s+string;
System.out.println("inside method " + s);
}
}
BeanTest.java
public class BeanTest {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
So the bean is getting updated even though we are not returning it from private method but a string is not. Can someone explain me whats happening on JVM level?
This is because Java follows Call by value, not Call by reference.
When you are passing s you are actually passing value of s, not the actual s. So though you are changing s in concateMe(), it will not change in your main method.
When you are passing bt, then the change is affecting as you are changing the field variable of that reference. But if you change the reference, then there will be no effect. You can add this in main method:
System.out.println("before......");
System.out.println(bt.getId());
System.out.println(bt.getName());
changeBeanTest(bt);
System.out.println("after");
System.out.println(bt.getId());
System.out.println(bt.getName());
Suppose your changeBeanTest is like this:
private static void changeBeanTest(BeanTest tempBeanTest) {
BeanTest bt = new BeanTest();
bt.setId("2");
bt.setName("Trump");
tempBeanTest = bt;
}
run this. There will be no change to bt sent from main().
The Bean is a full object in java passed by reference to the private method so it is the same instance in the main method and the private method.
You are modifying the values of that instance so the changes show up in both places.
The string is more or less a primitive and passed as a copy of the value instead of the exact instance from main. It is a new instance in the private method and so you are modifying a new variable. The changes don't show up in the main method as it is a different entity.
String s = "gowth"; in this line s is pointing to "gowth" from String Pool.When you are calling
private static void concateMe(String s, String string) here String s is different from caller method String s.Here String s scope is local to method ContactMe,But contactMe local String s pointing same "gowth" which is pointed by Caller class String s.After s = s + string;since String is immutable the method local reference String s pointing a different String "gowthami",but caller method String s is still pointing to "gowth".So you are getting this output.
But in case of Bean both the object pointing same String reference,Once we made any change in reference it would be reflected for both object.
So, I need to do this for part of my homework :
Create a method in the Customer class called hasMoreMoneyThan(Customer c)
which returns true if the customer calling the method has more money than the
customer c, otherwise it should return false.
I am looking to be pointed in the right direction for the line that says "the customer calling the method"
This is very confusing to me and doesn't make sense, this my Customer is a class.
Here is the necessary code :
public class Customer
{
private String name;
private int age;
private float money;
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public Customer(String n, int a, float m)
{
name = n;
age = a;
money = m;
}
I started writing the method:
public boolean hasMoreMoneyThan(Customer c)
{
}
But am not sure how to call that with my Customer object (which I think the question is asking.
Other relevant code :
public class StoreTestProgram {
public static void main(String args[]) {
Customer[] result;
Store walmart;
walmart = new Store("Walmart off Innes");
walmart.addCustomer(new Customer("Amie", 14, 100));
}
}
When a method is called on an object, the objects variables are in the current scope. In this case, the 'customer calling the method' is the object that the method is being called on (object being an instance of the class).
So, if boolean hasMoreMoneyThan(Customer c) is being called on Customer a, then you should think of it as asking Customer a has more money than Customer c?.
You can use the this keyword to refer to the current object (to help the reader differentiate from Customer c).
So, in your hasMoreMoneyThan method, you can compare this.money with c.money.
And to call this method, you need a reference to the current customer and the customer you want to compare with. You could do something like:
Customer currentCustomer = new Customer(...
Customer customerToCompareWith = new Customer(...
if (currentCustomer.hasMoreMoneyThan(customerToCompareWith)) {
// do something
}
Edit Let's try a different example. Let's say you want a method to know whether a customer is older than another customer. That code might look like:
public boolean isOlderThan(Customer c) {
return this.age > c.age;
}
And to call the method:
if (currentCustomer.isOlderThan(customerToCompareWith)) {
// the current customer is older
} else {
// the current customer is not older
}
this is how you reference an object from methods that are members of an object. this.money ><=? c.money
if in your constructor you you used public Customer(String name, int age, float money) you would use this.name= name instead of name= n to clear up ambiguity.
It may be a common question but I couldn't find nice explanation for it. I am trying to understand the encapsulation of reference variables in Java.In the below code:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName();
}
}
Output: bobfred
At first I thought making our field private and providing a getter method, it's a good encapsulation technique. But when I took closer look on it, I saw that when I invoke getName(), I do in fact return a copy, just like Java always does. But, I am not returning a copy of the StringBuilder object. I am returning a copy of the reference variable that point to the one and only StringBuilder object. So, at the point that getName() returns, I have one StringBuilder object and two reference variables pointing to it ( s and s2).
What are the techniques to make it well encapsulated?? A good explanation with code example expected :) . Thanks in advance.
There are two basic approaches I can think of.
The first is to only return immutable values. The caller can then do what he wants without risking the integrity of your object. In your case, the immutable type would be String:
class Special {
private String s = "bob";
String getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
String s2 = sp.getName();
s2 += "fred";
// Alternatively: StringBuilder s2 = new StringBuilder(sp.getName()).append("fred");
sp.printName(); // prints "bob"
}
}
Note: If s needs to be a StringBuilder, you can return s.toString().
The other option is to return a mutable value, but create a defensive copy in your getter. In other words, return a separate reference with duplicate data:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return new StringBuilder(s); } // return a copy of s
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName(); // prints "bob"
}
}
There can be multiple ways to apply encapsulation to mutable object.
By providing copy constructor (in above example new StringBuilder(oldBuilder.toString())
public class Student{
private String name;
public Student(Student s){
this.name = s.name;
}
}
Using prototype pattern with clone method. But copy Constructor is recommend over clone method.
public Student implements Cloneable{
private int rollNo;
private String name;
public Student clone(){
Student s = (Student)super.clone();
s.name = this.name;
s.rollNo = this.rollNo;
return s;
}
}
public class Clazz{
private Map students= new HashMap();
public student getStudent(int rollNo){
Student s = students.get(rollNo);
return s.clone();
}
}
Using immutable form of mutable object. e.g. Collections.unmodifiablecollection().
Whenever we return collection or array, always return read-only form. So modifications to collection will not impact the state of the object.
As per the JAVA documentation, the super.clone() when called returns a shallow copy of the object. In the code below I have two objects name and id; and one primitive variable num.
When the super.clone() method is called on the first object, it seems to be creating a deep copy of the objects(name and id) in addition to an expected copy of only num. After cloning the object obj, I have changed its name and id fields. These changes should be reflected in the cloned object if a shallow copy was being made. Am I right?
public class Cloning implements Cloneable {
String name;
int num;
Integer id;
Cloning(String name,int num,Integer id)
{
this.name = name;
this.num = num;
this.id = id;
}
public Object clone()
{
try
{
return super.clone();
}
catch(CloneNotSupportedException E)
{
System.out.println(E.getMessage());
return null;
}
}
public void print()
{
System.out.println(name);
System.out.println(num);
System.out.println(id);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Cloning obj = new Cloning("Annu",203,new Integer(3));
Cloning obj1 = (Cloning)obj.clone();
obj.name = "Annu_modified";
obj.num = 204;
obj.id = new Integer(4);
obj.print();
obj1.print();
}
}
I get the following output on running the code:
Annu_modified
204
4
Annu
203
3
The name and id fields are references to objects of type String and Integer. When you make a shallow copy the new copy points to the same objects for name and id.
Then when you do
obj.name = "Annu_modified";
You change obj.name to refer to a new object of type String while obj1.name continues to refer to the old object. If you could have changed the object obj.name referred to it would have changed for both. However with a String you can't cause it is a so called immutable object.
Let's look at a section from your example: obj.id = new Integer(4);. Here you're not changing the internal representation of id - you're assigning new instance to the id reference. Both Integer and String are immutable so it's hard to feel the difference of shallow vs deep copy with them. Try to add e.g. an ArrayList attribute and in order to modify it you can e.g. add a new element obj.myList.add(13);
try this test
Cloning obj = new Cloning("Annu",203, 1000);
Cloning obj1 = (Cloning)obj.clone();
System.out.println(obj.id == obj1.id);
it prints true, it means id of cloned object points to the same instance of Integer, if it were deep clone it would print false
class Subject {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Subject(String s) {
name = s;
}
}
class Student implements Cloneable {
//Contained object
private Subject subj;
private String name;
public Subject getSubj() {
return subj;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Student(String s, String sub) {
name = s;
subj = new Subject(sub);
}
public Object clone() {
//shallow copy
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
public class CopyTest {
public static void main(String[] args) {
//Original Object
Student stud = new Student("John", "Algebra");
System.out.println("Original Object: " + stud.getName() + " - "
+ stud.getSubj().getName());
//Clone Object
Student clonedStud = (Student) stud.clone();
System.out.println("Cloned Object: " + clonedStud.getName() + " - "
+ clonedStud.getSubj().getName());
stud.setName("Dan");
stud.getSubj().setName("Physics");
System.out.println("Original Object after it is updated: "
+ stud.getName() + " - " + stud.getSubj().getName());
System.out.println("Cloned Object after updating original object: "
+ clonedStud.getName() + " - " + clonedStud.getSubj().getName());
}
}
Output is:
Original Object: John - Algebra
Cloned Object: John - Algebra
Original Object after it is updated: Dan - Physics
Cloned Object after updating original object: John - Physics
In this example, all I did is, implement the class that you want to copy with Clonable interface and override clone() method of Object class and call super.clone() in it. If you observe, the changes made to "name" field of original object (Student class) is not reflected in cloned object but the changes made to "name" field of contained object (Subject class) is reflected in cloned object. This is because the cloned object carries the memory address of the Subject object but not the actual values. Hence any updates on the Subject object in Original object will reflect in Cloned object.