1

I use an init method per classes.

Spam[] spam1 = new Spam[13];
Spam[] spam2 = new Spam[7];
Spam[] spam3 = new Spam[5];

initSpamArray(spam1);
initSpamArray(spam2);
initSpamArray(spam3);

void initSpamArray (Object[] a) {
    for (int i = 0, len = a.length; i < len; i++) {
        a[i] = new Spam();
    }
}


Ham[] ham1 = new Ham[13];
Ham[] ham2 = new ham[7];
Ham[] ham3 = new Ham[5];

initHamArray(ham1);
initHamArray(ham2);
initHamArray(ham3);

void initHamArray (Object[] a) {
    for (int i = 0, len = a.length; i < len; i++) {
        a[i] = new Ham();
    }
}

Is it possible to define a kind of "universal" method to init any kind of object?

Like at least:

void initObjArray (Object[] a, <s.g. which suitable to transfer Class>) {
    for (int i = 0, len = a.length; i < len; i++) {
        a[i] = new <s.g. which suitable to transfer Class>();
    }
}

I tried to Google a lot and to play with java reflection also (Object.getClass(); Constructor.newInstance(); Class.newInstance() ). However I have not been successful.

osiixy
  • 144
  • 1
  • 8
  • Well usually you *don't* just want to call a parameterless constructor... – Jon Skeet Apr 10 '14 at 20:09
  • 1
    "I have not been successful" is not a good problem description. What did you try and where did it go wrong? Aside from that: is it really a problem? How often do you use a parameterless constructor of a self defined type? – Jeroen Vannevel Apr 10 '14 at 20:11
  • Are you trying to follow Sagan's [recipe for apple pie](http://www.goodreads.com/quotes/32952-if-you-wish-to-make-an-apple-pie-from-scratch)? I can't get the crust right either. – Elliott Frisch Apr 10 '14 at 20:23
  • Thank you for your answers. I see your points and probably parameterless constructor not make so much sense. This thing just came into my mind when I was doing some experiments for better understanding. Because this all thing came from exercising I did a lot of overwritings and I could not find my previous achievements but I would try to reconstruct the things with reflection. – osiixy Apr 10 '14 at 20:36

3 Answers3

1

If I understand the question correctly I think you want this (note: handle or propagate the exceptions any way you wish to):

public static <T> T[] newDefaultArray( Class<T> type, int N ) {
    T[] array = (T[])Array.newInstance(type, N);
    for ( int at = 0; at != N; ++at ) {
        try {
            array[at] = type.newInstance();
        }
        catch ( Exception e ) {
           throw new RuntimeException( e );
        }
    }

    return array;
}

Then you can use it like this (very simple):

   User[] users = newDefaultArray( User.class, 100 );

The class will need to have a default constructor.

robert_difalco
  • 4,821
  • 4
  • 36
  • 58
  • [`Class.newIntance`](http://stackoverflow.com/questions/195321/why-is-class-newinstance-evil) has a specification bug in that it silently converts checked exceptions to unchecked. – Mike Samuel Apr 10 '14 at 20:25
1

Using a Supplier to specify the way to create an instance:

public static <T> T[] fullArray(Class<T> componentType, int n,
                                Supplier<? extends T> constructor) {
  // This introduces no new type-unsafety.
  // Array.newInstance has to return Object since it can take a primitive
  // component type and !(new int[0] instanceof Object[]), but we know that
  // the result is a reference type since type parameters like T can only
  // bind to reference types.
  @SuppressWarnings("unchecked")
  T[] array = (T[]) Array.newInstance(componentType, n);
  for (int i = 0; i < n; ++i) {
    array[i] = constructor.get();
  }
  return array;
}

Instead of

Foo[] foos = new Foo[42];
for (int i = 0; i < foos.length; ++i) {
  foos[i] = new Foo();
}

you could do

Foo[] foos = fullArray(
    Foo.class, 42,
    new Supplier<Foo>() { public Foo get() { return new Foo(); } });

or in Java 8

Foo[] foos = fullArray(Foo.class, 42, () -> new Foo());
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • 1
    When using Java 8, the [`Supplier`](http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html) interface is now part of the language. Which means a lambda can be used. – Giovanni Botta Apr 10 '14 at 20:32
0

Here is a possible solution. To prevent using Class.newInstance() as Mike suggest in his comment, I changed the implementation. It would also support a constructor with possible parameters

public <T> void fillArray(T[] a, ArrayFillFunction<? extends T> f)
{
    for (int i = 0, len = a.length; i < len; i++)
    {
        a[i] = f.fill(i);
    }
}

public interface ArrayFillFunction<T> {
    T fill(int idx);
}

Your call would look like this:

Ham[] ham1 = new Ham[13];
fillArray(ham1, new ArrayFillFunction<Ham>()
{
    public Ham fill(int idx)
    {
        return new Ham();
    }
});

Or with custom constructor parameters:

Ham[] ham1 = new Ham[13];
fillArray(ham1, new ArrayFillFunction<Ham>()
{
    public Ham fill(int idx)
    {
        return new Ham(getParameterForIndex(idx));
    }
});

With Java 8 you can do this even more elegantly using Lambdas:

Ham[] ham1 = new Ham[13];
fillArray(ham1, idx -> new Ham());
fillArray(ham1, idx -> new Ham(getParameterForIndex(idx)));
Gregor Koukkoullis
  • 2,255
  • 1
  • 21
  • 31