簡體   English   中英

如何在Java中將類型作為方法參數傳遞

[英]How to pass a type as a method parameter in Java

在Java中,如何將類型作為參數傳遞(或聲明為變量)?

我不想傳遞類型的實例 ,而是傳遞類型本身(例如int,String等)。

在C#中,我可以這樣做:

private void foo(Type t)
{
    if (t == typeof(String)) { ... }
    else if (t == typeof(int)) { ... }
}

private void bar()
{
    foo(typeof(String));
}

Java中有沒有傳遞類型為t的實例的方法?
或者我必須使用自己的int常量或枚舉?
或者,還有更好的方法?

編輯:這是foo的要求:
基於類型t,它生成一個不同的短xml字符串。
if / else中的代碼將非常小(一行或兩行)並將使用一些私有類變量。

你可以傳入一個Class<T>

private void foo(Class<?> cls) {
    if (cls == String.class) { ... }
    else if (cls == int.class) { ... }
}

private void bar() {
    foo(String.class);
}

更新 :OOP方式取決於功能要求。 最好的選擇是定義foo()的接口和實現foo()兩個具體實現,然后在你手頭的實現上調用foo() 另一種方法可能是Map<Class<?>, Action> ,您可以通過actions.get(cls)調用它。 這很容易與接口和具體實現相結合: actions.get(cls).foo()

我有一個類似的問題,所以我在下面編寫了一個完整的可運行答案。 我需要做的是將一個類(C)傳遞給一個不相關的類的對象(O),當我要求它時,讓該對象(O)向我發出類(C)的新對象。

下面的示例顯示了如何完成此操作。 您可以使用Projectile類的任何子類型(Pebble,Bullet或NuclearMissle)加載MagicGun類。 有趣的是你用Projectile的子類型加載它,但不是那種類型的實際對象。 在拍攝時,MagicGun會創建實際物體。

輸出

You've annoyed the target!
You've holed the target!
You've obliterated the target!
click
click

代碼

import java.util.ArrayList;
import java.util.List;

public class PassAClass {
    public static void main(String[] args) {
        MagicGun gun = new MagicGun();
        gun.loadWith(Pebble.class);
        gun.loadWith(Bullet.class);
        gun.loadWith(NuclearMissle.class);
        //gun.loadWith(Object.class);   // Won't compile -- Object is not a Projectile
        for(int i=0; i<5; i++){
            try {
                String effect = gun.shoot().effectOnTarget();
                System.out.printf("You've %s the target!\n", effect);
            } catch (GunIsEmptyException e) {
                System.err.printf("click\n");
            }
        }
    }
}

class MagicGun {
    /**
     * projectiles holds a list of classes that extend Projectile. Because of erasure, it
     * can't hold be a List<? extends Projectile> so we need the SuppressWarning. However
     * the only way to add to it is the "loadWith" method which makes it typesafe. 
     */
    private @SuppressWarnings("rawtypes") List<Class> projectiles = new ArrayList<Class>();
    /**
     * Load the MagicGun with a new Projectile class.
     * @param projectileClass The class of the Projectile to create when it's time to shoot.
     */
    public void loadWith(Class<? extends Projectile> projectileClass){
        projectiles.add(projectileClass);
    }
    /**
     * Shoot the MagicGun with the next Projectile. Projectiles are shot First In First Out.
     * @return A newly created Projectile object.
     * @throws GunIsEmptyException
     */
    public Projectile shoot() throws GunIsEmptyException{
        if (projectiles.isEmpty())
            throw new GunIsEmptyException();
        Projectile projectile = null;
        // We know it must be a Projectile, so the SuppressWarnings is OK
        @SuppressWarnings("unchecked") Class<? extends Projectile> projectileClass = projectiles.get(0);
        projectiles.remove(0);
        try{
            // http://www.java2s.com/Code/Java/Language-Basics/ObjectReflectioncreatenewinstance.htm
            projectile = projectileClass.newInstance();
        } catch (InstantiationException e) {
            System.err.println(e);
        } catch (IllegalAccessException e) {
            System.err.println(e);
        }
        return projectile;
    }
}

abstract class Projectile {
    public abstract String effectOnTarget();
}

class Pebble extends Projectile {
    @Override public String effectOnTarget() {
        return "annoyed";
    }
}

class Bullet extends Projectile {
    @Override public String effectOnTarget() {
        return "holed";
    }
}

class NuclearMissle extends Projectile {
    @Override public String effectOnTarget() {
        return "obliterated";
    }
}

class GunIsEmptyException extends Exception {
    private static final long serialVersionUID = 4574971294051632635L;
}

你應該通過一個Class ......

private void foo(Class<?> t){
    if(t == String.class){ ... }
    else if(t == int.class){ ... }
}

private void bar()
{
   foo(String.class);
}

哦,但那是丑陋的,非面向對象的代碼。 你看到“if / else”和“typeof”的那一刻,你應該考慮多態性。 這是錯誤的方式。 我認為仿制葯是你的朋友。

您打算處理多少種類型?

更新:

如果您只是在談論String和int,那么這是您可以采用的一種方式。 從界面XmlGenerator開始(足夠用“foo”):

package generics;

public interface XmlGenerator<T>
{
   String getXml(T value);
}

並具體實現XmlGeneratorImpl:

    package generics;

public class XmlGeneratorImpl<T> implements XmlGenerator<T>
{
    private Class<T> valueType;
    private static final int DEFAULT_CAPACITY = 1024;

    public static void main(String [] args)
    {
        Integer x = 42;
        String y = "foobar";

        XmlGenerator<Integer> intXmlGenerator = new XmlGeneratorImpl<Integer>(Integer.class);
        XmlGenerator<String> stringXmlGenerator = new XmlGeneratorImpl<String>(String.class);

        System.out.println("integer: " + intXmlGenerator.getXml(x));
        System.out.println("string : " + stringXmlGenerator.getXml(y));
    }

    public XmlGeneratorImpl(Class<T> clazz)
    {
        this.valueType = clazz;
    }

    public String getXml(T value)
    {
        StringBuilder builder = new StringBuilder(DEFAULT_CAPACITY);

        appendTag(builder);
        builder.append(value);
        appendTag(builder, false);

        return builder.toString();
    }

    private void appendTag(StringBuilder builder) { this.appendTag(builder, false); }

    private void appendTag(StringBuilder builder, boolean isClosing)
    {
        String valueTypeName = valueType.getName();
        builder.append("<").append(valueTypeName);
        if (isClosing)
        {
            builder.append("/");
        }
        builder.append(">");
    }
}

如果我運行它,我得到以下結果:

integer: <java.lang.Integer>42<java.lang.Integer>
string : <java.lang.String>foobar<java.lang.String>

我不知道這是不是你的想法。

如果你想傳遞類型,那么就比Java中的等價物要好

java.lang.Class

如果你想使用弱類型的方法,那么你只需使用

java.lang.Object

和相應的操作員

instanceof

例如

private void foo(Object o) {

  if(o instanceof String) {

  }

}//foo

但是,在Java中有原始類型,它們不是類(即您的示例中的int),因此您需要小心。

真正的問題是你真正希望在這里實現的目標,否則很難回答:

或者,還有更好的方法?

您可以傳遞表示類型的java.lang.Class實例,即

private void foo(Class cls)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM