Как передать тип в качестве параметра метода в 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 будет очень маленьким (одна или две строки) и будет использовать некоторые частные переменные класса.
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 из вашего примера), поэтому вам нужно быть осторожным.
реальный вопрос заключается в то, что вы на самом деле хотите достичь здесь, иначе трудно ответить:
или есть лучший способ?
Comments