0

I'm trying to create a lot of objects, but using new ObjectName(...) over and over is not what I'm looking for.

new Obj("String", 0, true);
new Obj("Diff", 9, true);
new Obj("Changed", 2, false);
...

I would like something similar to:

massCreateObj({
    {"String",  0, true },
    {"Diff",    9, true },
    {"Changed", 2, false}
    ...
});

I want to do this because it will be easier to manage for multiple objects, such as:

massCreateObjs({
    "Obj" => {
        {"str", 0, false},
        {"sss", 1, true}
    },
    "Obj2" => {
        {false, "different"},
        {true, "diff"}
    }
});

Otherwise, I would have to flatten this:

new Obj("str", 0, false);
new Obj("sss", 1, true);
new Obj2(false, "different");
new Obj2(true, "diff");

This is just simply not scalable. With an array, I can easily see which objects are being created, and there isn't text repeated (the new object name).

Is there a way I can use Hashmaps, Arrays, or tuples to accomplish this? (Open to other solutions too)

I've taken a look at hashmaps but it's essentially only a K->V setup.

I've also looked at wrappers, but then, it's back to where I've started. If I create a class/interface, I still need to use new class name or whatever, which is what I'm avoiding in the first place.

4
  • Nope, there's not really a way to do this. Commented Feb 20, 2015 at 4:14
  • Yep, I've been using Java for a while, but I still can't get PHP out of my head. Thanks for the confirmation :P Commented Feb 20, 2015 at 4:15
  • 2
    An alternative if you have a lot of objects and are willing to do so, is reading the data in from a JSON or CSV or the like. Then it's a simple for loop over the imported data. Commented Feb 20, 2015 at 4:16
  • Would anyone recommend this: A huge nested Object[] array, and because I know all the resulting types, simply cast everything afterwards. I might go for this approach, but it seems like a code smell. Commented Feb 20, 2015 at 7:12

6 Answers 6

1

You can use Reflections, but you'd have to define your own function as follows:

public static <T> Object[] multipleConstructor(Class<T> type,
        Object[]... initargs) {
    ArrayList<T> list = new ArrayList<>();
    @SuppressWarnings("unchecked")
    Constructor<T>[] ctors = (Constructor<T>[]) type.getConstructors();
    for (int i = 0; i < initargs.length; i++) {
        for (Constructor<T> c : ctors) {
            try {
                list.add(c.newInstance(initargs[i]));
                break;
            } catch (Throwable t) {
                continue;
            }
        }
    }
    return list.toArray();
}
Sign up to request clarification or add additional context in comments.

3 Comments

I didn't notice your answer when I wrote mine :P. Looking at it, it looks very close to mine. (Only difference is I specify which constructor I want to use, and yours checks all the constructors) I'm still on the fence about this kinda method however.
@DaveChen I'm not sure if this is the best strategy either. It just happens to be the only way I know of doing this.
It seems to be the only method at this point. I still haven't fully adapted into the "Java" way of thinking yet, but if there's no alternative, then I'll just stick with what I know, and what I know is using nested arrays to create objects.
1

If you want to hard code the parameters in your code but want to avoid repeating the "new" keyword, then a simple loop will do.

String[] args1 = {"hello", "bye", "potatoe"};
int[] args2 = {5,2,7};
boolean[] args3 = {true,false,true};

Obj[] objects = new Obj[3];

for (int i = 0; i < 3; i++) {
    objects[i] = new Obj(args1[i], args2[i], args3[i]);
}

Not that this is good code, but the idea can be applied in better ways :)

1 Comment

Thanks for this. I think your answer lead me to create my final version.
1

Rather than specifying the objects in Java, read their parameters from a file. that file can be in any format you like, and can parse. Write Java code to call from the constructor for the object containing the array that reads the file and generates the array from it.

As a variation on this, write a separate program that reads and parses the file, and generates a Java program from it. That way, you could literally copy over initializers like Color.BLUE.

2 Comments

I'm probably going to have to do something exactly like this. For the moment I'm struggling to do this change because of dependencies within constructors. What I mean is, one of the parameters in the constructor is Color. So, I can't exactly put in a JSON/xml/txt, "Color.BLUE". There's other dependencies too, so if there is a way to not parse anything...
@DaveChen Why not "Color.BLUE" as long as you have a consistent syntax? You can use either a map or reflection to turn it into a Color.
0

Make an inner class called "Node" if the input data follow specific types e.g. str, int, boolean, str, int, bool and create each Node object and put it in HashMap if object has names or in HashTable incase no names.

2 Comments

But when I create the Node objects, I still have to use "new Node(................)", which is pretty much the same thing if I just stick with "new ObjectName(...)".
its basically the same...but u can use a for loop if you have consistency in ur data.
0

If you want to create the array inline, you can always do

Obj[] objects = new Obj[] {
    new Obj("String", 0, true),
    new Obj("Diff", 9, true),
    new Obj("Changed", 2, false)
};

There's no way to get around using new (or some wrapper factory function that calls it) if you're trying to create a new object.

On a broader scale, by the way, your use case sounds like what you really want is immutable data structure, and you should consider Guava's ImmutableList instead of a bare array.

Comments

0

Here's my solution. I know this isn't codereview, but is this OK?

import java.lang.reflect.Constructor;
import java.util.Array;

public class MassCreate {
    private Array<Obj> objs = new Array<Obj>();

    public MassCreate(Object[][][] components) {
        Constructor<?> construct = null;
        try {
            for (int i = 0; i < components.length; i++)
                for (int i2 = 0; i2 < components[i].length; i2++)
                    if (i2 == 0) {
                        Class<?>[] classes = new Class[components[i][i2].length - 1];
                        for (int i3 = 1; i3 < components[i][i2].length; i3++)
                            classes[i3 - 1] = (Class<?>) components[i][i2][i3];
                        construct = ((Class<?>) components[i][i2][0])
                                .getConstructor(classes);
                    } else
                        objs.add((Obj) construct
                                .newInstance(components[i][i2]));
        } catch (Exception e) {}
    }

    public Obj[] getObjs() {
        Obj[] export = new Obj[objs.size];
        for (int i = 0; i < objs.size; i++)
            export[i] = objs.get(i);
        return export;
    }
}

Now for the fun part, here is where I can spawn new objects using an Object[][][].

Object[][][] components = {
        {
            {Obj.class, String.class, int.class, boolean.class},
            {"test 1", 0, true},
            {"test 2", 3, false}
        },
        {
            {Obj2.class, boolean.class, String.class},
            {true, "hello"},
            {false, "diff"}
        }
};

new MassCreate(components).getObjs(); //Obj2 extends Obj

Here's what it means:

{Obj.class, String.class, int.class, boolean.class}

The first class indicates what to make, and the rest indicate which constructor to use. So for this, the constructor for Obj.class would be:

 public Obj(String str, int num, boolean bool);

The following items in the first level array are objects to be, so:

{"test 1", 0, true},
{"test 2", 3, false}

Would invoke the above constructor twice with these values.

What do you guys think?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.