how to write array elements to console

D

Dzikus

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
 
A

Andrew Thompson

Dzikus said:
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.
 
D

Dzikus

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):
 
D

Dzikus

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 + " : "
+ types.getName() + " = " + args);
if(types.getName().compareTo("[B") == 0)
{
System.out.print("Byte table:");
byte[] data = (byte[])(args);
for(int j = 0; j < data.length; ++j){
System.out.print(data[j]);
}
System.out.println("");
}
}
}
System.out.println("=====================================");
}
before() : Call() {
write(thisJoinPoint);
}

}
 
A

Alex Hunsley

Dzikus said:
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?

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
 
A

Alex Hunsley

Dzikus said:
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
 
D

Dzikus

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);
}
 
W

wesley.hall

Dzikus said:
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?

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.
 
D

Dzikus

Yeah, it's a great hint.
But still I have somehow downcast from Object to array of specified
type ...
 
E

Eric Sosman

Dzikus said:
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?

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.
 
T

tam

Dzikus said:
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
 
D

Dzikus

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?
 
E

Eric Sosman

Dzikus said:
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?

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.
 
O

Oliver Wong

Dzikus said:
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?

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
 
D

Dzikus

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' });
}
}
 
L

Lew

Alex said:
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);
}

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
 
A

Alex Hunsley

Lew said:
Alex said:
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);
}

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.

Whoops, my bad! That'll teach me to not double check....
lex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top