[英]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.