Reputation: 5097
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
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
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
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
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
Reputation: 41200
What about this -
public void SetAlert(Class<?> class){
Object obj = class.newInstance();
if(obj isInstanceOf RedAlert){
RedAlert ra= (RedAlert)obj;
}
...
}
Upvotes: 1
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
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
Reputation: 7735
Many options:
Upvotes: 0
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
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
Reputation: 29436
Avoid internal dependencies and initialztions:
AlertController aController = new AlertController(new RedAlert());
Upvotes: 0
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