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 / December 2006

Tip: Looking for answers? Try searching our database.

how to write array elements to console

Thread view: 
Dzikus - 13 Dec 2006 09:46 GMT
Hello,
I have following problem:
Let's assume there is a function
  f(Object obj){
  ...
  }
And if obj is an array (of some primitive types) I want to write
elements to Sysytem.out

For example if I have:
int[] array = {1, 2, 3, 4};
f(array);

The expected result would be
1
2
3
4
Does anybody knows how to do it?

Thanks in advance
   Dominik
Andrew Thompson - 13 Dec 2006 09:54 GMT
> Hello,
> I have following problem:
...
> And if obj is an array (of some primitive types) I want to write
> elements to Sysytem.out
....
> Does anybody knows how to do it?

Yes, of course!  Doesn't your textbook cover loops?
Or is it that you simply have not bothered consulting
your textbook, and would prefer us to do your homework?

Andrew T.
Dzikus - 13 Dec 2006 10:07 GMT
This is not a homework :> I'm C++/C programmer and I'm not very
familiar with reflection and other more Java - specific conveniences.

The type of f's argument is Object, not array.
There is a function isArray (java.lang.Class) byt still i dont know of
what types the array is (in order to downcast for example)...

Andrew Thompson napisal(a):

> Yes, of course!  Doesn't your textbook cover loops?
> Or is it that you simply have not bothered consulting
> your textbook, and would prefer us to do your homework?
>
> Andrew T.
Dzikus - 13 Dec 2006 10:16 GMT
Maybe i'll put whole code for better understanding:
I'm looking for more generic solution for writing all types of arrays,
not only byte array ...

public aspect Debug {
    pointcut Call() : (execution(* *(..)) || call(* *(..))
            || execution(*.new()))
            && !within(Debug);
    synchronized void write(JoinPoint jp)
    {
        System.out.println(jp.getSignature());

        Object[] args = jp.getArgs();
        if (args.length > 0) {
            System.out.println("Arguments: ");
            String[] names = ((CodeSignature) jp.getSignature())
                    .getParameterNames();
            Class[] types = ((CodeSignature) jp.getSignature())
                    .getParameterTypes();
            for (int i = 0; i < args.length; i++) {
                System.out.println("  " + i + ". " + names[i] + " : "
                        + types[i].getName() + " = " + args[i]);
                if(types[i].getName().compareTo("[B") == 0)
                {
                    System.out.print("Byte table:");
                    byte[] data = (byte[])(args[i]);
                    for(int j = 0; j < data.length; ++j){
                        System.out.print(data[j]);
                    }
                    System.out.println("");
                }
            }
        }
        System.out.println("=====================================");
    }
    before() : Call() {
        write(thisJoinPoint);   
    }

}
Alex Hunsley - 13 Dec 2006 10:22 GMT
> Maybe i'll put whole code for better understanding:
> I'm looking for more generic solution for writing all types of arrays,
> not only byte array ...

Now you're asking the smart question! Much better than the limited
question you posted before.
As I suggested, make your f method take an array of Objects.
Then call .toString() on each of those objects in that method and print
out the result. (You'll need each object you've written yourself to have
a toString() method that returns sensible string output. Lookup
Object.toString() for more info.)
lex
Alex Hunsley - 13 Dec 2006 10:20 GMT
> Hello,
> I have following problem:
[quoted text clipped - 15 lines]
> 4
> Does anybody knows how to do it?

Assuming this isn't homework (it doesn't look like it)...
It can't be done this way, because you can't pass int array (int[]) into
a method expecting an Object. They just don't match.
Alternatives:

1) write your f method to expect an Object array (Object[]) and pass in
an array of Integer objects (*not* primitive ints!)
i.e.
  f(Object[] obj){
   ...
  }

  Integer int[] array = {new Integer(1), new Integer(2), ....};
  f(array);

2) write your f method to take specifically an int array

HTH,
lex
Dzikus - 13 Dec 2006 10:37 GMT
> It can't be done this way, because you can't pass int array (int[]) into
> a method expecting an Object. They just don't match.

What do you mean they don't match?
The following example compiles and works...

private void f(Object o){
       System.out.println("Hello");
   }
private void g(){
      int[] ala = {1,2,3};
      f(ala);
 }
Lew - 13 Dec 2006 15:56 GMT
Alex Hunsley wrote:
>> It can't be done this way, because you can't pass int array (int[]) into
>> a method expecting an Object. They just don't match.

> What do you mean they don't match?
> The following example compiles and works...
[quoted text clipped - 6 lines]
>        f(ala);
>   }

They do so match!

Dzikus, you're entirely correct. Array types are subtypes of Object, and can
be upcast without fear. Downcasting works if the Object happens to be an array
at runtime for the downcast.

What you did, testing the claim, exemplifies wise use of Usenet.

There's a lot of reflection and C++ idiom in your posted code, so I didn't
delve into it much. To answer your original question, how to print an array
from a method that takes an Object parameter:

Another poster suggested simply using the parameter's toString() method, which
you can do implicitly or explicitly.

private PrintWriter out;
...
public void foo( Object obj )
{
    out.println( "Object: " );
    out.println( obj );
}

If you don't like the way the arrays' toString() methods work, you can crack
arrays into a loop. This requires a check for each primitive type and Object
if you're avoiding complicated reflection:

public void foo( Object obj )
{
    if ( obj instanceof Object [] )
    {
        Object [] oarr = (Object []) obj;
        for( Object o : oarr )
        {
            out.println( o );
        }
    }
    else if ( obj instanceof int [] )
    {
        int [] iarr = (int []) obj;
        for ( int i : iarr )
        {
            out.println( i );
        }
    }
    // ... byte, char, short, long, float, double
    else
    {
        out.println( obj );
    }
    out.flush();
}

As another poster pointed out, in a type that you design a reasonable
implementation of toString() is important.

Even better is when you know that you'll use only arrays of a type that you
design (or subtype thereof). Then you can simplify to a static method of, say,
parent class Foo that can print values of Foo [] as you like. If the array
lister method calls each element's own toString() then the whole listing will
be sensible.

- Lew
Alex Hunsley - 18 Dec 2006 13:07 GMT
> Alex Hunsley wrote:
>>> It can't be done this way, because you can't pass int array (int[]) into
[quoted text clipped - 16 lines]
> can be upcast without fear. Downcasting works if the Object happens to
> be an array at runtime for the downcast.

Whoops, my bad! That'll teach me to not double check....
lex
wesley.hall@gmail.com - 13 Dec 2006 11:01 GMT
> Hello,
> I have following problem:
[quoted text clipped - 15 lines]
> 4
> Does anybody knows how to do it?

If you are using Java 5(+), and you dont mind if the output is in the
format: 1, 2, 3, 4, 5 (because you are just wanting to display the
values to a user), then you can use the toString method on the Arrays
utility class.
Dzikus - 13 Dec 2006 11:24 GMT
Yeah, it's a great hint.
But still I have somehow downcast from Object to array of specified
type ...
tam@lheapop.gsfc.nasa.gov - 13 Dec 2006 14:35 GMT
> Yeah, it's a great hint.
> But still I have somehow downcast from Object to array of specified
> type ...

It's not trivial to do this, but it's more tedious than difficult
to handle an arbitrary input object if you allow a
recursive solution.

I believe you are correct that you will have to do explicit downcasts
to each of the primitive types.  You may also want to handle
arrays of objects specially (which will get you multi-dimensional
arrays of all types as well).

E.g.,

   void method(Object o) {

         if (o instanceof Object[]) {
                Object[] oa = (Object[]) o;
                for (Object ox: oa) method(ox);
         } else if (o instanceof int[]) {
                ... process int array ..
         } else if (o instanceof double[]) {
         ... handle all 7 primitive arrays explictly
         } else {
               ... Handle a non-array Object
         }
   }

This is one example where it would be nice to have double-dispatch but
that's not available in Java.  [Double dispatch would allow you to
select from among overloaded 'method's the one whose signature
matched the actual rather than the declared class of the argument.]

   Regards,
   Tom McGlynn
Eric Sosman - 13 Dec 2006 14:21 GMT
> Hello,
> I have following problem:
[quoted text clipped - 15 lines]
> 4
> Does anybody knows how to do it?

    void f(Object obj) {
       // optional test
       if (! obj.getClass().isArray())
           throw new IllegalArgumentException("not array");

       if (obj instanceof int[]) {
           int[] arr = (int[])obj;
           ...
       } else if (obj instanceof long[]) {
           long[] arr = (long[])obj;
           ...
       } else if ...
       ...
       else
           throw new IllegalArgumentException("phphhbbbh!");
    }

    A slightly different approach might look like

    void f(Object obj) {
       String className = obj.getClass().getName();
       if (className.charAt(0) != '[')
           throw new IllegalArgumentException("not array");
       switch (className.charAt(1)) {
       case 'I':
           int[] iarray = (int[])obj;
           ...
           break;
       case 'J':
           long[] larray = (long[])obj;
           ...
           break;
       ...
       default:
           throw new IllegalArgumentException("phphhbbbh!");
       }
    }

    Still another approach would be to change the way the method
is defined.  Instead of writing one method to handle every possible
type of array, write a method for each array type you care about
and let the compiler figure out which to call:

    void f(int[] array) { ... }
    void f(long[] array) { ... }
    ...

However, this approach only works if you actually know the array
type at compile time, that is, if you actually have an int[]
reference or a long[] reference or whatever at the point when you
make the call.  If you really, truly have an Object reference and
nothing more, you need to make the determination at run time.

Signature

Eric Sosman
esosman@acm-dot-org.invalid

Dzikus - 13 Dec 2006 14:43 GMT
> If you really, truly have an Object reference and
> nothing more, you need to make the determination at run time.

This is what I am looking for. I suspect that in such powerfull
language like java it is possible to avoid those switch - cases with
downcasting.
How can I do such determination?
Eric Sosman - 13 Dec 2006 14:51 GMT
>> If you really, truly have an Object reference and
>> nothing more, you need to make the determination at run time.
[quoted text clipped - 3 lines]
> downcasting.
> How can I do such determination?

    In either of the ways I showed, or perhaps in some other
way I didn't think of: I'm only a user of Java, not a guru.
The documentation for java.lang.Class is likely to be helpful.

    One way or another, you will need to determine the actual
class of the array your Object reference refers to.  You said
you only cared about arrays of primitive types, which makes
things a little easier: There is a fixed number of primitive
types to check for, and writing the code for each of them (or
for the subset that interests you) may take you a few minutes
but doesn't require much ingenuity.

Signature

Eric Sosman
esosman@acm-dot-org.invalid

Oliver Wong - 13 Dec 2006 15:19 GMT
> Hello,
> I have following problem:
[quoted text clipped - 15 lines]
> 4
> Does anybody knows how to do it?

   Here's a solution that does not do any downcasting, nor use any switch
statement. However, it does use an exception for control flow, which is
somewhat frowned upon.

<SSCCE>
import java.lang.reflect.Array;

public class ArrayTest {
public static void main(String[] args) {
 f(new int[] { 1, 2, 3 });
 f(new byte[] { 4, 5, 6 });
 f(new char[] { 'a', 'b', 'c' });
}

public static void f(Object o) throws IllegalArgumentException {
 if (!o.getClass().isArray()) {
  throw new IllegalArgumentException("Not an array.");
 }
 int index = 0;
 try {
  while (true) {
   System.out.println(Array.get(o, index));
   index++;
  }
 }
 catch (ArrayIndexOutOfBoundsException aioobe) {
  // do nothing
 }
}
}

</SSCCE>

The issue is that I can't figure out how to get the length of the array
without performing a cast. The following does not work:

o.getClass().getField("length").getInt(o);

It throws a NoSuchFieldException, which surprises me, because I'm pretty
sure arrays have a field called "length". But maybe it has to do with the
fact that arrays are somewhat "magical" and not pure objects?

   - Oliver
Dzikus - 13 Dec 2006 15:37 GMT
Thanks for help.
This is what I was looking for :)
Array length we can get using Array.getLength function.

import java.lang.reflect.Array;
class ArrayTest{
    public static void f(Object o) {
          Class c =o.getClass();
          if(c.isArray()){
              for(int i = 0; i < Array.getLength(o); ++i){
                     System.out.println(Array.get(o, i));
                   }
              }
          }

    public static void main(String[] args) {
        f(new int[] { 1, 2, 3 });
        f(new byte[] { 4, 5, 6 });
        f(new char[] { 'a', 'b', 'c' });
    }
}
Oliver Wong - 13 Dec 2006 16:08 GMT
> Array length we can get using Array.getLength function.

   I can't believe I missed that function.

   Oh well. Hooray for teamwork! =)

   - Oliver


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.