这是一个玩具类,它返回与您放入其中的内容相反的内容。目前它适用于整数,但只需要非常小的更改即可适用于字符串。
public class Mirror {
int value;
public int get() {
return reverse(value);
}
private int reverse(int value2) {
String valueString = value + "";
String newString = reverse(valueString);
return Integer.parseInt(newString);
}
private String reverse(String valueString) {
String newString = "";
for (char c : valueString.toCharArray()) {
newString = c + newString;
}
return newString;
}
public void set(int value) {
this.value = value;
}
}
我想做的是使类通用,但仅适用于两种或三种可能的类型。所以我想写的是:
public class Mirror<X, where X is one of Integer, String, or MagicValue {
X value
public X get(){
[...]
正确的语法是什么?
不幸的是java并没有直接提供这样的功能。不过,我可以建议您采取以下解决方法:
使用私有构造函数和 3 个静态工厂方法创建参数化类
Mirror
,这些方法使用特定参数创建 Mirror
的实例:
public class Mirror<T> {
private T value
private Mirror(T value) {
this.value = value;
}
public static Mirror<Integer> integerMirror(Integer value) {
return new Mirror(value);
}
public static Mirror<String> stringMirror(String value) {
return new Mirror(value);
}
public static Mirror<MagicValue> magicMirror(MagicValue value) {
return new Mirror(value);
}
}
编辑 显然,您可以(并且可能应该)将类
Mirror
与其创建分开,例如将工厂方法放在单独的类中MirrorFactory
。在这种情况下,构造函数应该受到包保护。
如果您想支持大量但数量有限的类,您可以仅实现一种通用工厂方法
public static <T> Mirror<T> createMirror(T value) {
checkTypeSupported(value);
return new Mirror(value);
}
方法
checkTypeSupported(value);
可能会使用某种元数据(例如属性、JSON等文件)来获取支持的类型。然而在这种情况下,您将无法享受编译时验证。
其他解决方案是要求所有受支持的类型扩展某些基类或实现接口:
public class Mirror<T extends MyInterface> {}
但是这个解决方案似乎不符合您的要求,因为您需要
Integer
,String
和MagicValue
。
有多种方法可以满足您的需求...这是另一种选择。没有 getter 或 setter。
每种要处理的类型都有一个 Mirror 实例。一种reverse()方法。
根据需要进行调整。添加错误检查/处理。
public class Mirror<T> {
public T reverse(final T value) {
T result = null;
while (true) {
if (value instanceof String) {
System.out.println("Do for String");
result = value;
break;
}
if (value instanceof Integer) {
System.out.println("Do for Integer");
result = value;
break;
}
if (value instanceof JFrame) {
System.out.println("Do for JFrame");
result = value;
break;
}
throw new RuntimeException("ProgramCheck: Missing handler for type " + value.getClass().getSimpleName());
}
return result;
}
测试员:
final Mirror<String> testerString = new Mirror<>();
testerString.reverse("string");
final Mirror<Integer> testerInteger = new Mirror<>();
testerInteger.reverse(41);
testerInteger.reverse(42);
testerInteger.reverse(43);
final Mirror<JFrame> testerJFrame = new Mirror<>();
testerJFrame.reverse(new JFrame());
结果:
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
另一种选择是接受您无法控制 String/Integer 的类型层次结构的事实,并创建一个接口来为您可以控制的类提供通用类型
public int reverse(int value) {
return Integer.valueOf(new StringBuilder(value + "").reverse()
.toString());
}
public String reverse(String value) {
return new StringBuilder(value + "").reverse().toString();
}
public <T extends Reversible> T reverse(T value) {
value.reverse();
return value;
}
public interface Reversible {
public void reverse();
}
如果您只想要 Mirror 类的一个实例...请使用通用方法。
public class Mirror {
public <T> T reverse(final T value) {
T result = null;
while (true) {
if (value instanceof String) {
System.out.println("Do for String");
result = value;
break;
}
if (value instanceof Integer) {
System.out.println("Do for Integer");
result = value;
break;
}
if (value instanceof JFrame) {
System.out.println("Do for JFrame");
result = value;
break;
}
throw new RuntimeException("ProgramCheck: Missing handler for type " + value.getClass().getSimpleName());
}
return result;
}
测试员:
final Mirror tester = new Mirror();
String s = tester.reverse("string");
Integer i41 = tester.reverse(41);
Integer i42 = tester.reverse(42);
Integer i43 = tester.reverse(43);
JFrame j = tester.reverse(new JFrame());
结果:
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
您无法将通用参数绑定到值范围。但是,您可以通过编程方式限制它:
public abstract class AbstractMirror<T> {
T value;
protected AbstractMirror(Class<T> clazz) {
if (clazz != Integer.class && clazz != String.class && clazz != MagicValue.class)
throw new IllegalArgumentException();
}
public abstract T get();
protected abstract T reverse(T value);
}
您可以使用所谓的“见证”类型来使编译器执行您想要的操作。
public interface Reversible< T > {
public static final class IntReversible implements Reversible< Integer > {}
public static final class StringReversible implements Reversible< String > {}
public static final class MagicReversible implements Reversible< MagicValue > {}
}
public abstract class Mirror< T, R extends Reversible< T > > {
// ...
}
public class IntMirror extends Mirror< Integer, IntReversible > {
// ...
}
但是,您的示例没有任何意义的原因是因为在这种情况下使用泛型几乎没有任何好处。有什么算法可以反转整数、字符串或 MagicValue,而不需要采用糟糕的运行时类型检查和转换?该代码将是所有三种反向算法,并用一个可怕的
if
梯子包裹起来。
所以这就是为什么(在工作中解决了)
泛型总是来自子类,尽管它看起来像
Public class Thing<T> {}
将允许其中存在任何类型,实际上它的意思是它将允许对象的任何子类型。 IE。
Public class Thing<T extends Object> {}
这实际上是作为继承起作用的,事实上,Oracle 网站向我们展示了当语法糖被删除时会发生这种情况:
在以下示例中,通用 Node 类使用有界类型 参数:
public class Node<T extends Comparable<T>> { private T data; private Node<T> next; public Node(T data, Node<T> next) { this.data = data; this.next = next; } public T getData() { return data; } // ... }
Java 编译器将有界类型参数 T 替换为第一个 绑定类,可比较:
public class Node { private Comparable data; private Node next; public Node(Comparable data, Node next) { this.data = data; this.next = next; } public Comparable getData() { return data; } // ... }
...所以答案是,你不能以这种方式限制类型的原因是因为它实际上变成了多重继承,这是令人讨厌的,我很乐意避免......