如何在 Java 中将类型作为方法参数传递

2022-08-31 10:37:39

在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 中的代码将非常小(一行或两行),并且将使用一些私有类变量。


答案 1

你可以传递一个 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()


答案 2

我有一个类似的问题,所以我在下面做了一个完整的可运行的答案。我需要做的是将类(C)传递给不相关类的对象(O),并在我请求类(C)时让该对象(O)发出类(C)的新对象。

下面的示例演示如何完成此操作。有一个MagicGun类,您可以使用弹丸类的任何子类型(Pebble,Bullet或NuclearMissle)加载。有趣的是,您加载了弹丸的子类型,但不是该类型的实际对象。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;
}