Java Forum / General / December 2006
how to write array elements to console
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 MagazinesGet 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 ...
|
|
|