Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / April 2008

Tip: Looking for answers? Try searching our database.

enumerate the consumers of foo.toString() within an application

Thread view: 
Rex Mottram - 19 Apr 2008 20:32 GMT
Say I have a class with an explicit toString() method, for which I want
to change the output format (have it return a different String). I first
want to see if anywhere else in the program is using it and might be
broken (this is not a published API but a standalone application -
otherwise I wouldn't change toString at all).

This turns out to be harder than it I thought. For one thing, toString
is special in that it can be called implicitly, i.e. out.println(foo) is
the same as out.println(foo.toString()). So I can't depend on searching
for literal occurrences of foo.toString. With another method I could
remove or rename it temporarily and see who else breaks. But of course
toString will just revert to the superclass.

The meta-problem is that I often provide a toString as a debugging aid
only - for instance Eclipse will show the toString result for any
highlighted instance which can be very handy. Other times it's doing
something critical. I guess one lesson of this is that toString is best
left as a convenience/debugging aid and more descriptive method names be
used for mission-critical stringifying. But in the meantime, any bright
ideas on how to enumerate the users of foo.toString() within a
self-contained application?

RM
Stefan Ram - 19 Apr 2008 20:47 GMT
>Say I have a class with an explicit toString() method, for which I want
>to change the output format (have it return a different String).

 You can write toString() as you like it.

>This turns out to be harder than it I thought. For one thing, toString
>is special in that it can be called implicitly, i.e. out.println(foo) is
>the same as out.println(foo.toString()).

 It is not strictly the same - it just might have the same effect.

 »toString()« is not special compared to any other method.

>ideas on how to enumerate the users of foo.toString() within a
>self-contained application?

 You need to inspect all libraries you use for uses, too,
 because of run-time polymorphism in Java. Let me elaborate ...

 What is object-oriented programming?

   Object-oriented programming uses objects (storage entities)
   annotated with run-time types: Every object carries
   information about its type, which implies information about
   the layout and encoding of its storage.

 What is an object-oriented programming language?

   An object-oriented programming language supports
   object-oriented programming, but it usually hides the type
   information of objects and automatically assigns operations
   specified for a type to each object.  Thus, in an object
   oriented programming language, the programmer does not read
   the type information himself nor does he use it to select an
   appropriate action. Instead he just states the action by a
   "verb" with a type and the programing language will then
   make sure, that the correct implementation is called for any
   given object at run-time. This is called »run-time
   polymorphism« or »late binding«. Individual object-oriented
   programming languages might include additional support for
   object-oriented programing, but this binding is the core
   feature of every object-oriented programming language.

 What is the main advantage of an object-oriented programming
 language?

   The main advantage is that verbs can be extended without the
   need to modify existing code. For example, in Java, a new
   type can extend the verb »toString«. This extension can then
   be used immediatly by the existing »println« verb, without
   the need that the author of the code for »println« was aware
   of the new type, so it is not necessary to modify the given
   Java SE library, which contains other definitions of the
   verb »toString«. One only needs to /add/ new code. Thus, the
   »open/closed principle« is fulfilled.

 Can you give a small example programm that shows something
 that can be done in an object-oriented programming language,
 but is not possible in a purely procedural programming
 language?

   Yes, a Java program illustrating the answer to the previous
   question is:

class Position
{ int x; int y; public java.lang.String toString()
 { return java.lang.String.valueOf( x ) +
   ", " + java.lang.String.valufOf( y ); }}

public class Main
{ public static void main( final java.lang.String[] args )
 { java.lang.System.out.println( new Position() ); }}

   The output of this program is as follows.

0, 0

 What is the reason for run-time information?

   It is needed whenever data, whose encoding, layout or
   language might change or is not yet known, is to be
   transfered between two parties to indicate this encoding,
   layout or language.
Roedy Green - 19 Apr 2008 21:40 GMT
>  »toString()« is not special compared to any other method.

Except that Sun code will call toString under a number of
circumstances.  In that sense it is magic.
Signature


Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Stefan Ram - 19 Apr 2008 21:44 GMT
>>»toString()« is not special compared to any other method.
>Except that Sun code

 or code form other parties

>                     will call toString under a number of
>circumstances.  In that sense it is magic.

 Yes, as magic as »hashCode()« and other methods of
 »java.lang.Object« or other superclasses or interfaces (like
 java.lang.Runnable#run()).
Eric Sosman - 19 Apr 2008 22:04 GMT
>>  »toString()« is not special compared to any other method.
>
> Except that Sun code will call toString under a number of
> circumstances.  In that sense it is magic.

    Could you elaborate?  Off-hand, I can't think of any
circumstances where the compiler fabricates a toString()
call out of thin air.  Something to do with Enum, maybe?

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Bill Butler - 19 Apr 2008 22:43 GMT
>>>  »toString()« is not special compared to any other method.
>>
[quoted text clipped - 4 lines]
> circumstances where the compiler fabricates a toString()
> call out of thin air.  Something to do with Enum, maybe?

System.out.println(foo);  // this calls foo.toString() to get a String
from an object

Granted...this is not really fabricating anything, but it appears
magical at first glance

   Bill
Eric Sosman - 20 Apr 2008 01:54 GMT
>>>>  »toString()« is not special compared to any other method.
>>> Except that Sun code will call toString under a number of
[quoted text clipped - 5 lines]
> System.out.println(foo);  // this calls foo.toString() to get a String
> from an object

    But the toString() call is not magically generated by the
compiler at all.  The compiler generates a call to the
PrintStream.println(Object) method, which in turn makes a
perfectly normal call to String.valueOf(Object), which in
its turn calls toString() on foo's class.  No magic, just
explicit calls to perfectly ordinary methods.

    However, I've thought of one sense in which toString() may
be thought of as magical: String concatenation.  In

    String s = myDog + " is bigger than " + yourDog;

the compiler "magically" calls toString() on the StringBuilder
object that actually performs the concatenation.  Note that it
does not call myDog.toString() nor yourDog.toString(); rather,
it calls StringBuilder.append(xxxDog), which eventually gets
around to calling xxxDog.toString().

    Still, it might be considered magical that the compiler
knows StringBuilder.toString() is useful.

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Peter Duniho - 20 Apr 2008 02:34 GMT
>>>>>  »toString()« is not special compared to any other method.
>>>> Except that Sun code will call toString under a number of
[quoted text clipped - 7 lines]
>      But the toString() call is not magically generated by the
> compiler at all.

Note, however, that the original statement said nothing about the  
compiler.  Simply that toString() will be called.  (It said by "Sun code",  
but it's not limited to that, especially since not all Java  
implementations were written by Sun :) ).

The real question is whether there are situations in which toString() is  
called implicitly and thus could be considered "special".  And there are.  
I think in that respect, it is "special".  Though, it's only "special" to  
the extent that any method in the base Object class is "special" and thus  
relied upon by a variety of code using those methods.

Pete
Bill Butler - 20 Apr 2008 14:25 GMT
<snip>
>>      But the toString() call is not magically generated by the
>> compiler at all.
[quoted text clipped - 10 lines]
> is "special" and thus  relied upon by a variety of code using those
> methods.

Well said Peter,
There are no "rules" being broken, by the compiler, on behalf of the
toString method.
There are places, however, where the code takes advantage of the fact
that every Object must have a "toString" method.
This can result in code that can appear magical at first glance.

   Bill
Lew - 20 Apr 2008 14:48 GMT
> There are places, however, where the code takes advantage of the fact
> that every Object must have a "toString" method.
> This can result in code that can appear magical at first glance.

So can polymorphism generally.  The code relies on the fact that all concrete
types inherit from Object.  That's pretty much fact number one about Java,
isn't it?  Expressing behavior polymorphically is arguably the core idiom of
object-oriented programming.

Done right, it is magic.

Signature

Lew

Rex Mottram - 20 Apr 2008 19:59 GMT
>> There are places, however, where the code takes advantage of the fact
>> that every Object must have a "toString" method.
[quoted text clipped - 6 lines]
>
> Done right, it is magic.

But not all _methods_ inherit from Object methods. Those that do get an
extra helping of magic.

BTW, not that I mind the interesting debate at all but for the record
please note that I (the OP) did not use the word "magic". Nor "unique",
nor "uniquely magical". I said "special", and it is. Apparently because
the compiler know that it inherits all the way from Object.

RM
Lew - 20 Apr 2008 20:29 GMT
>>> There are places, however, where the code takes advantage of the fact
>>> that every Object must have a "toString" method.
[quoted text clipped - 9 lines]
> But not all _methods_ inherit from Object methods. Those that do get an
> extra helping of magic.

Yes, that magic is called "polymorphism", and it is used every time a class
inherits an instance method.

Every method that inherits from a superclass gets that "helping of magic";
there's nothing "extra" about it.

> BTW, not that I mind the interesting debate at all but for the record
> please note that I (the OP) did not use the word "magic". Nor "unique",
> nor "uniquely magical". I said "special", and it is. Apparently because
> the compiler know that it inherits all the way from Object.

It isn't special, it's normal polymorphism.

Signature

Lew

Mark Space - 21 Apr 2008 04:25 GMT
> BTW, not that I mind the interesting debate at all but for the record
> please note that I (the OP) did not use the word "magic". Nor "unique",
> nor "uniquely magical". I said "special", and it is. Apparently because
> the compiler know that it inherits all the way from Object.

The only magic is in the way string objects can be created without "new"
or by concatenation with an overloaded "+".

All the Sun code does is:

class Test
{
    public void someMethod( Object o )
    {
        o.toString();
        //...
     }
}

That's it. There's no magic or preferential treatment by the compiler
that I can see.  It's not special.  It's plain old bog standard object
inheritance.  You can do the exact same thing yourself.
Mark Space - 19 Apr 2008 21:34 GMT
> highlighted instance which can be very handy. Other times it's doing
> something critical. I guess one lesson of this is that toString is best
> left as a convenience/debugging aid and more descriptive method names be
> used for mission-critical stringifying. But in the meantime, any bright

Yes, and good design would have spotted that fairly early.  So the other
meta issue is why did this requirement not get captured properly?
Something to look at for future reference and learning and best
practices and such.

My advice, although it may be painful:  Since you have to search,
manually, for all occurrences of this overloaded (I mean design-wise,
not overloaded in the programming/Java sense of the word) use of
toString(), you should just refactor the design.  Add the new method now
to the class(es) and replace the use of toString() with the new method
where you find it is needed.
Logan Shaw - 19 Apr 2008 21:49 GMT
> Say I have a class with an explicit toString() method, for which I want
> to change the output format (have it return a different String). I first
> want to see if anywhere else in the program is using it and might be
> broken (this is not a published API but a standalone application -
> otherwise I wouldn't change toString at all).

Some issues have already come up in this thread.  One is how far your
toString() might be visible (i.e. are you writing library code).  You
implied you don't care about that, nor do you care about complications
with subclasses and so on.

Anyway, a couple of thoughts:

(1) You can't remove toString() or modify its signature, but you could
    temporarily modify toString() to make it throw an unchecked exception.
    Now, if you can only get all the code in the project to run, you
    could detect who's calling toString().  That may be difficult for
    all the reasons that code coverage (and covering all the relevant
    inputs) can be, but then again maybe not.

(2) Won't these toString() calls have to be explicit in the bytecode?
    Could you analyze the .class files instead of the source code?

(3) In the idealized unit test world, unit tests would notice all the
    breakages you caused by changing toString(), and they would provide
    a helpful safety net.

It strikes me that even though #2 could get you a lot closer, it can't
do easily do anything about "Object o = getSomeObject; o.toString();".
Maybe some static flow analysis (on the .class files, yay) could, but
then again probably not completely, and the type erasure of generics
unfortunately may make that worse.  So leveraging the compiler's
habit of making toString() explicit in the .class files is good for
one reason, but it's bad since the compiler throws out other
information you need.  Bleah.  :-)

  - Logan
Eric Sosman - 19 Apr 2008 22:13 GMT
> [... finding implicit and explicit toString() calls ...]
> (2) Won't these toString() calls have to be explicit in the bytecode?
>     Could you analyze the .class files instead of the source code?

    I don't think that will work.  In a situation like

    Thing someThing = new Thing();
    ...
    System.out.println(someThing);

... there will be no toString() call in the class file, just
an ordinary call on System.out.println(Object) -- which will
eventually get back to Thing.toString() via an invokevirtual.

    String meAlong = someThing + ":" + zipCode;

... the bytecode will have one call on StringBuilder.toString(),
but no calls to Thing.toString().  There will be ordinary calls
to StringBuilder's overloaded append() methods, and one of
those will eventually get back to Thing.toString(), but you
won't find that toString() call in the snippet's bytecode.

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Roedy Green - 19 Apr 2008 23:30 GMT
>first
>want to see if anywhere else in the program is using it and might be
>broken (this is not a published API but a standalone application -
>otherwise I wouldn't change toString at all).

An IDE like Intellij will find uses for you, but since the method
could also be called via Object.toString the number of all possible
uses would be overwhelming.
Signature


Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.