17

RedAlertYellowAlert、 と呼ばれる 3 つのクラスがありBlueAlertます。

クラス内で、AlertController次のようなメソッドが必要です。

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

たとえば、私はしたい:

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

クラス名をパラメーターとしてどのように取り込み、そのクラス名に基づいて、クラス名から適切なオブジェクトを作成しますか?

4

12 に答える 12

23

リフレクションを使用することは可能です。ここでは、指定された className (文字列として渡されます) についてです。このクラスはメモリ内で検索されます (すでにロードされているはずです)。

文字列として渡されるときにインスタンス化されるクラスの名前は、完全修飾されている必要があります

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


        Class classTemp = Class.forName(className);

        Object obj =classTemp.newInstance();



    }
}
于 2013-07-25T05:09:33.103 に答える
20

クラス名を渡す代わりに、クラス自体を渡し、リフレクションを使用してクラスの新しいインスタンスを作成できます。基本的な例を次に示します (すべてのXxxAlertクラスがクラスから拡張されていると仮定しますAlert)。

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

次のようにメソッドを呼び出すだけです。

setAlert(RedAlert.class);

パラメータでスーパークラスを使用する方が良いことに注意してTください。そうしないと、あなた(または別のプログラマ)がこれを行うことができます:

setAlert(Object.class);

これは明らかに間違っています。

于 2013-07-25T05:07:58.590 に答える
2

リフレクションなどを使用して作成できますが、いくつかの作成設計パターンを調査することをお勧めします。

具体的には工場パターン

これは(非常に)大雑把な例です:

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;
    }
}

そして、メソッドから次を使用できます。

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

とにかく、これは本当に醜い例ですが、Creational Patterns を見て、クラス名を渡さずに別の方法で問題を解決できる可能性があることを強調したいと思います。

于 2013-07-25T05:07:53.387 に答える
2

ファクトリ パターン アプローチを使用してみませんか。

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();
}

次に、このようなことができます。

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

java.lang.Class#newInstanceを使用してアプローチを使用することは可能です。

于 2013-07-25T05:18:59.267 に答える
1

次のように、メソッド シグネチャに Class の参照を含めることができます。

public void SetAlert(Class class)

次に、メソッドで newInstance メソッドを使用して入力クラスのインスタンスを作成できます。

Object obj = class.newInstance();
于 2013-07-25T05:04:25.070 に答える
1

これはどうですか -

public void SetAlert(Class<?> class){
     Object obj = class.newInstance();
     if(obj isInstanceOf RedAlert){
         RedAlert ra= (RedAlert)obj;
     }
     ...
}
于 2013-07-25T05:06:28.720 に答える
0

リフレクションを使用せずにこれを行う別の方法は、インターフェイスに Alert を指定し、クラス (RedAlert、YellowAlert、および BlueAlert) に Alert インターフェイスを実装させることです。
したがって、AlertController のメソッドは次のようになります。

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

これで次のことができます:

setAlert(new RedAlert());
setAlert(new YellowAlert());
setAlert(new BlueAlert());
于 2013-07-25T05:18:09.997 に答える
0

列挙型を使用:

public enum AlertType {RED_ALERT, YELLOW_ALERT, BLUE_ALERT};

// ...

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

// ...

AlertController aController = new AlertController();
SetAlert(AlertType.RED_ALERT);
于 2013-07-25T05:10:21.113 に答える
0

内部の依存関係と初期化を避ける:

AlertController aController = new AlertController(new RedAlert());
于 2013-07-25T05:05:56.193 に答える
0

多くのオプション:

  1. 標準のファクトリ アプローチを見てください: http://en.wikipedia.org/wiki/Factory_method_pattern
  2. クラスの列挙型 Alert{Red, Yellow, Green;} の代わりに列挙型を使用します。
于 2013-07-25T05:12:02.273 に答える
0

Java Reflection を使用して、Class オブジェクトからオブジェクトを作成します。次のようにメソッドを宣言します。

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

その後、

 AlertController aController = new AlertController();
    SetAlert(RedAlert.class);
于 2013-07-25T05:15:54.050 に答える
0

これは、クラス名を使用してインスタンスを作成する方法です。の具象型にAlertは、引数を取らないパブリック コンストラクターが必要です。

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);
  }
}

呼び出し元は次のように使用します。

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

特定のパラメーターのセットをコンストラクターに渡すための規則を作成する場合は、それを行うこともできますが、getConstructor()それを見つけるために呼び出しで少し余分な作業を行う必要があります。公開されていないコンストラクターを使用することもできますが、これも少し余分な作業が必要です。

クラス リテラルを渡すという提案はRedAlert.classあまり意味がありません。RedAlertコンパイル時に呼び出し元がクラスを使用できる場合は、そのコンストラクターを使用するだけnew RedAlert()です。

于 2013-07-25T05:16:12.473 に答える