Dan Ciborowski - MSFT
Dan Ciborowski - MSFT

Reputation: 7207

How to replace two Java Constructors with one generic Constructor

I have the following two java methods(simplified). I would like to replace these two methods with one method. The reason for wanting to do this is one method is used for local testing, and one method is using during run on a Hadoop cluster. I just spent a while debugging my code before realising I had adjusted one method and not the other, and would like to know how to avoid this silly mistake in the future.

public MyObject(ArrayList<String> values){
    for(String val: values){
        System.out.println(val.toString());
    }
}

public MyObject(Iterable<Text> values){
    for(Text val: values){
        System.out.println(val.toString());
    }
}

Text is an apache hadoop class. Here is a link to source code. http://grepcode.com/file/repository.cloudera.com/content/repositories/releases/com.cloudera.hadoop/hadoop-core/0.20.2-737/org/apache/hadoop/io/Text.java

Upvotes: 1

Views: 108

Answers (5)

Braj
Braj

Reputation: 46841

Try with Generic.

ArrayList also implements Iterable so any thing that implements Iterable can pass in the constructor.

There is no need for any other constructor. This single constructor can serve the purpose of all type of Iterable classes.

public class MyObject<T> {

    public MyObject(Iterable<T> values) {
        for (T val : values) {
            System.out.println(val.toString());
        }
    }
}

Upvotes: 2

Victor Suarez
Victor Suarez

Reputation: 45

You could just try...

public MyObject(Collection collection) {

   for (Object obj : collection) {
      System.out.println(obj.toString());
   }
}

Upvotes: 0

Tim B
Tim B

Reputation: 41168

You could just do:

public MyObject(Iterable<? extends Object> values){
    for(String val: values){
        System.out.println(val.toString());
    }
}

And lose the first constructor entirely.

Alternatively look at whether you can have one constructor modify the parameters and then call the other.

Upvotes: 2

Paul
Paul

Reputation: 3058

Is Text a class in your own code base? If so, could you make it implement CharSequence which java.util.String already does (in later versions of Java - not sure since when). Then your one ctor would be:

public MyObject(Iterable<? extends CharSequence> values) { ... }

(I am assuming your real code is doing more in the ctor than just printing the objects; otherwise why would you be creating an MyObject instance in the first place?)

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726489

Since you are not using anything specific to String or Text (whatever that is) in your constructors, you could take Iterable<? extends Object> as the parameter:

public MyObject(Iterable<? extends Object> values){
    for(Object val: values){
        System.out.println(val.toString());
    }
}

Upvotes: 5

Related Questions