Как передать тип в качестве параметра метода в 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 или enum?

Или есть лучший способ?



Edit: вот требование для фу:

В зависимости от типа T, она создает различные короткие, строки XML.

Код в if / else будет очень маленьким (одна или две строки) и будет использовать некоторые частные переменные класса.

590   6  

6 ответов:

вы могли бы пройти Class<T> in.

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

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

обновление: путь ООП зависит от функционального требования. Лучше всего было бы интерфейс, определяющий foo() и две конкретные реализации реализации foo() а потом просто позвоните foo() о реализации у вас под рукой. Другой способ может быть Map<Class<?>, Action> который вы могли бы назвать actions.get(cls). Это легко сочетается с интерфейсом и конкретными реализациями:actions.get(cls).foo().

у меня был аналогичный вопрос, поэтому я разработал полный запускаемый ответ ниже. То, что мне нужно было сделать, это передать класс (C) объекту (O) несвязанного класса и заставить этот объект (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;
}

вы должны пройти 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.ленг.Класс, представляющий тип, т. е.

private void foo(Class cls)

Comments

    Ничего не найдено.