使Java类成为泛型类,但仅适用于两种或三种类型

使Java类成为泛型类,但仅适用于两种或三种类型,java,generics,Java,Generics,(我很惊讶没有在stackoverflow上找到这个问题,这只能归咎于我的谷歌搜索能力差,无论如何都要指出重复的问题…) 下面是一个toy类,它返回与您输入内容相反的内容。目前,它可以处理整数,但只需要非常小的更改就可以处理字符串 public class Mirror { int value; public int get() { return reverse(value); } private int reverse(int value2) { Stri

(我很惊讶没有在stackoverflow上找到这个问题,这只能归咎于我的谷歌搜索能力差,无论如何都要指出重复的问题…)

下面是一个toy类,它返回与您输入内容相反的内容。目前,它可以处理整数,但只需要非常小的更改就可以处理字符串

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(){
[...]

public-class-Mirror不幸的是,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);
    } 
}
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; }
    // ...
}
支持的方法<代码>检查类型(值)
可能使用某种元数据(例如属性、JSON等文件)来获取支持的类型。但是,在这种情况下,您将无法享受编译时验证

另一种解决方案是要求所有受支持的类型扩展特定的基类或实现接口:

public class Mirror<T extends MyInterface> {}
公共类镜像{}

但此解决方案似乎不符合您的要求,因为您需要
Integer
String
MagicValue

另一种选择是接受您无法控制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();
}
public int reverse(int值){
返回Integer.valueOf(新的StringBuilder(值+“”)。reverse()
.toString());
}
公共字符串反转(字符串值){
返回新的StringBuilder(值+“”)。reverse().toString();
}
公共T反转(T值){
value.reverse();
返回值;
}
公共接口可逆{
公共无效反向();
}

不能将常规参数绑定到值的范围。但是,您可以通过编程方式对其进行限制:

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);

}
公共抽象类AbstractMirror{
T值;
受保护的抽象镜像(clazz类){
if(clazz!=Integer.class&&clazz!=String.class&&clazz!=MagicValue.class)
抛出新的IllegalArgumentException();
}
公共抽象得不到();
保护抽象T反转(T值);
}

各种方法满足您的需要…这里是另一个选项。没有getter或setter。
每个要处理的类型对应一个镜像实例。一个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;
}

如果您只需要镜像类的一个实例,请使用泛型方法

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;
}
结果:

Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
您可以使用所谓的“见证”类型使编译器执行您想要的操作

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 > {
    // ...
}
公共接口可逆{
公共静态final类IntReversible{}
公共静态最终类StringReversible实现可逆的{}
公共静态最终类MagicVersionable实现可逆{}
}
公共抽象类镜像>{
// ...
}
公共类IntMirror扩展镜像{
// ...
}
然而,您的示例没有任何意义的原因是,在这种上下文中使用泛型几乎没有任何好处。有什么可能的算法可以在不使用糟糕的运行时类型检查和强制转换的情况下反转整数、字符串或MagicValue?代码将是所有三个反向算法,用一个可怕的
if
-ladder包装起来。

所以这里是原因(在工作中解决了它)

泛型总是来自子类,尽管它看起来像

Public class Thing<T> {}

…所以答案是,你不能用这种方式限制类型的原因是因为它实际上变成了多重继承,这很糟糕,我很乐意避免……

创建两个或三个方法,返回正确的类型并将正确的类型作为参数。我认为所有类型都需要位于相同的类层次结构中。。对于每个人来说,这都不是一个好的解决方案case@arynaq,我不确定我是否理解-这有什么帮助?@Zavior-等等,你的意思是我可能无意中问了一个原始问题?只是提醒一下:StringBuilder类有一个内置的反向方法,你可以使用它来代替你的方法,所以你可以调用
new StringBuilder(valueString).reverse().toString()
这样就解决了我限制创建的问题,但是我不必在镜像类中放入大量不明确的样板文件来支持所有永远不会实例化的类型吗?(即,我是否还必须编写公共X reverse(X in){return X;}为了实现编译,即使我知道它永远不会被调用?@Joe,请看一下我的编辑。我希望它有帮助。但是我不明白方法
reverse()
do.assert reverse(123)==321;assert reverse(“hello”).equals(“olleh”);assert reverse(new HashMap())==糟糕的程序员…;0)请,将第三个方法名从
integerMirror
更正为
magicValueMirror
,因为我对它的编辑被拒绝了。你不会将构造函数设置为私有的吗?为什么要使用
while(true)
而不是将if块与
else
链接?这两种方法都可以-个人选择-而(true)似乎可以生成更干净的代码。同意吗??
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
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 > {
    // ...
}
Public class Thing<T> {}
Public class Thing<T extends Object> {}
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; }
    // ...
}
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; }
    // ...
}