1110101001
1110101001

Reputation: 5097

Passing class name as parameter

I have 3 classes called RedAlert, YellowAlert, and BlueAlert.

Within my class AlertController I want to have a method like this:

public void SetAlert(//TAKE IN NAME OF CLASS HERE//)
{
    CLASSNAME anInstance = new CLASSNAME();
}

So for example I want to:

AlertController aController = new AlertController();
SetAlert(RedAlert);

How do you take in the class name as a parameter, and based on that class name create the appropriate object from the class name?

Upvotes: 22

Views: 72649

Answers (12)

Sanyam Goel
Sanyam Goel

Reputation: 2180

Using reflection it is possible. Here for a given className (passed as a string) . This class will be searched in memory ( it should be already loaded).

The name of the class to be instantiated when passed as a string should be fully qualified

void createInstanceOfClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException{


        Class classTemp = Class.forName(className);

        Object obj =classTemp.newInstance();



    }
}

Upvotes: 28

Xavier DSouza
Xavier DSouza

Reputation: 2931

Another way you can do this without using reflection is to have an Interface say Alert and have your classes - RedAlert, YellowAlert, and BlueAlert implement the Alert interface.
So now your method in AlertController looks like:

public void setAlert(Alert alert) {
       // Your code goes here
}

Now you can do :

setAlert(new RedAlert());
setAlert(new YellowAlert());
setAlert(new BlueAlert());

Upvotes: 0

erickson
erickson

Reputation: 269637

This is the way to create an instance using a class name. The concrete type of Alert must have a public constructor that takes no arguments.

private Alert alert;

public void setAlert(String className) 
{
  try {
    Class<?> raw = Class.forName(className);
    Class<? extends Alert> type = raw.asSubclass(Alert.class);
    Constructor<? extends Alert> ctor = type.getConstructor();
    this.alert = ctor.newInstance();
  } catch (Exception ex) {
    throw new IllegalArgumentException("Invalid Alert implementation.", ex);
  }
}

The caller would use it like this:

AlertController aController = new AlertController();
controller.setAlert("com.y.foo.RedAlert");

If you create a convention for passing a certain set of parameters to the constructor, you can do that too, but you'll need to do a little extra work in the getConstructor() call to find it. You can also use constructors that aren't public, but, again, that takes a bit of extra work.

The suggestions to pass the class literal, RedAlert.class, don't make much sense. If the RedAlert class is available to the caller at compile time, you'd just use its constructor, new RedAlert().

Upvotes: 0

edwardsmatt
edwardsmatt

Reputation: 2044

While you can create it using Reflection etc... I'd suggest investigating some Creational Design Patterns.

Specifically the Factory Pattern

Here is a (very) crude example:

public interface Alert {
}


public class BlueAlert implements Alert {
}

public class RedAlert implements Alert {
}

public class YellowAlert implements Alert {
}

public final class AlertFactory {

    public <T extends Alert> Alert create(Class<T> clazz) {
        Alert toReturn = null;
        if (RedAlert.class.equals(clazz)) {
            toReturn = new RedAlert();
        } else if (YellowAlert.class.equals(clazz)) {
            toReturn = new YellowAlert();
        } else if (BlueAlert.class.equals(clazz)) {
            toReturn = new BlueAlert();
        }
        return toReturn;
    }
}

And then from your Method you could use:

public void SetAlert(Class alertClass) { 
    Alert theAlert = new AlertFactory().create(alertClass);
}

Anyway, while this is a really ugly example, I'm trying to highlight that maybe you could look at the Creational Patterns and solve your problem a different way without passing classnames around.

Upvotes: 2

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41200

What about this -

public void SetAlert(Class<?> class){
     Object obj = class.newInstance();
     if(obj isInstanceOf RedAlert){
         RedAlert ra= (RedAlert)obj;
     }
     ...
}

Upvotes: 1

raniejade
raniejade

Reputation: 515

Why not use a factory pattern approach.

public interface Alert {}

public class RedAlert implements Alert {}
public class YellowAlert implements Alert {}
public class BlueAlert implements Alert {}

public interface AlertFactory {
    Alert create();
}

public class RedAlertFactory implements AlertFactory {
    public Alert create() {
        return new RedAlert();
    }
}

public class YellowAlertFactory implements AlertFactory {
    public Alert create() {
        return new YellowAlert();
    }
}

public class BlueAlertFactory implements AlertFactory {
    public Alert create() {
        return new BlueAlert();
    }
}

// your setAlert method could probably look like this
public void setAlert(AlertFactory factory) {
    aInstance = factory->create();
}

Then you could do something like this.

setAlert(new RedAlertFactory()); // or YellowAlertFactory, BlueAlertFactory

It's possible to use your approach using java.lang.Class#newInstance.

Upvotes: 2

Ankur Lathi
Ankur Lathi

Reputation: 7836

Use Java Reflection to create object from Class object. Declare your method like this:

public void SetAlert(Class clazz)
{
    Constructor<?> ctor = clazz.getConstructor();
    Object object = ctor.newInstance();
}

And then,

 AlertController aController = new AlertController();
    SetAlert(RedAlert.class);

Upvotes: 0

mavarazy
mavarazy

Reputation: 7735

Many options:

  1. Look at standard factory approach: http://en.wikipedia.org/wiki/Factory_method_pattern
  2. Use enum instead of the class enum Alert{Red, Yellow, Green;}

Upvotes: 0

morgano
morgano

Reputation: 17422

Use enums:

public enum AlertType {RED_ALERT, YELLOW_ALERT, BLUE_ALERT};

// ...

public void SetAlert(AlertType type)
{
    // ...
}

// ...

AlertController aController = new AlertController();
SetAlert(AlertType.RED_ALERT);

Upvotes: 0

Luiggi Mendoza
Luiggi Mendoza

Reputation: 85779

Instead of passing the class name, you can pass the class itself and use reflection to create a new instance of the class. Here's a basic example (assuming all your XxxAlert classes extend from an Alert class):

public <T extends Alert> void setAlert(Class<T> clazzAlert) {
    Alert alert = clazzAlert.newInstance();
    //use the alert object as you want/need...
}

Now you just call the method like this:

setAlert(RedAlert.class);

Note that it would be better using a super class in T parameter, otherwise you (or another programmer) could do this:

setAlert(Object.class);

which would be plain wrong.

Upvotes: 22

s.d
s.d

Reputation: 29436

Avoid internal dependencies and initialztions:

AlertController aController = new AlertController(new RedAlert());

Upvotes: 0

Juned Ahsan
Juned Ahsan

Reputation: 68715

You can have a reference of Class in your method signature, something like this:

public void SetAlert(Class class)

Then in your method you can create the instance of the input class using the newInstance method:

Object obj = class.newInstance();

Upvotes: 1

Related Questions