0

我正在尝试用 Java 编写一个具有混合返回类型的方法(就像你在 PHP 中一样)。

该方法应该采用简单的用户输入字符串,并使用泛型将其转换为适当的类型并返回该值。

@SuppressWarnings("unchecked")
public static <T> T askUser(String message, Class clazz) throws NumberFormatException {
    // get the user input
    String inputString = JOptionPane.showInputDialog(message),
            className = clazz.getCanonicalName();
    // return a Boolean, Integer or String
    if (className.equals(Boolean.class.getCanonicalName())) {
        return (T) Boolean.valueOf(inputString);
    } else if (className.equals(Integer.class.getCanonicalName())) {
        return (T) Integer.valueOf(inputString);
    } else /*return the String*/ {
        return (T) inputString;
    }
}

我正在运行这样的代码:

    String userName = name_game.<String>askUser("Please enter your name.", String.class);
    Integer userAge = name_game.<Integer>askUser("Please enter your age.", Integer.class);
    tellUser("So your name is %s and your age is %d...", userName, userAge);
    Boolean confirm = name_game.<Boolean>askUser("Is this correct?", Boolean.class);
    tellUser("You said %b.", confirm);

但我不知道如何在没有 (T) 强制转换的情况下让它工作,并且传递 Class 参数似乎也可以避免。

我怎样才能编写这种方法而不必求助于 (T) ?

4

3 回答 3

3
public static <T> T askUser(String message, Class<T> clazz) throws NumberFormatException {
    // ...
}

使用此声明也可以避免方法调用之前的内部强制转换和泛型。

于 2013-10-08T10:42:16.473 回答
2

泛型不会让您能够:

获取一个简单的用户输入字符串,并使用泛型将其转换为适当的类型并返回该值。

例如:如果有人放置 aFile并想将其转换为 aDog怎么办?

您可以创建一个CreatableFromString带有createFromString( String userData)签名的接口,使用给定的字符串实例化适当的对象。

然后,即使不使用泛型,您也拥有完整的类型安全性——而且您不必担心File<->Dog情况,因为只有实现的类CreatableFromString才能放入 askUser 参数中。

此解决方案的缺点是 askForUser 将返回 CreatableFromString,但您可以将其设为通用:

Dog dog = name_game.createByUserAskDialog( "Please enter dog name.", Dog.class );

和:

public static <T extends CreatableFromString> T askUser(String dialogTitle , Class<T> clazz) {
    ...get "data" from user...
    return T.createFromString( data ) ;
}

如果要将用户字符串转换为现有类型,则不能Class<T>作为参数传递,而可以作为工厂传递:

public interface CreatableFromStringFactory<T> {
  public T createFromString( String s );
}

...

public class BooleanFromStringFactory implements CreatableFromStringFactory<Boolean> {
  public Boolean createFromString( String s ) {
    if ( s.equals( "yes" ) ) {
      return Boolean.TRUE;
    }
    return Boolean.FALSE; 
  }
}

...
booleanFromStringFactory  = new BooleanFromStringFactory();
...
Boolean c = name_game.askUser("Is this correct?",booleanFromStringFactory );
于 2013-10-08T10:52:18.327 回答
1

我认为最好编写一些代码将字符串转换为适当的数据类型,并有不同的方法来获取用户的年龄、姓名等。

于 2013-10-08T10:51:13.490 回答