获取对象类并将其用作通用构造函数的参数

时间:2015-03-27 14:30:55

标签: java

我确定之前已经问过这个问题,但我是Java的新手,并且不熟悉我正在寻找的确切术语。

我有一个BST课程:

public class BinarySearchTree<T extends Comparable> {
    /* ... */
}

然后我为它写了一些测试:

public static void main(String[] args) {
    Integer[] integerItems = {1, 7, 8, 2, -1, -10, 100, 12, 32};
    String[] stringItems = {"jungi", "phil", "bob", "leslie", "tyler", "clarence"};
    Comparable[][] comparableLists = {integerItems, stringItems};

    for (Comparable[] list : comparableLists) {
        BinarySearchTree<>...
    }
}

我很困惑这一步。如何从列表中恢复类型(String [],Integer []等)并将它们用作参数?我想要这样的东西:

for (Comparable[] list : comparableLists) {
    BinarySearchTree<typeOf(list)> root = new BinarySearchTree<typeOf(list)>();
    /* ... tests ... */
}

我发现here的一个选项就是列出所有可能的支持的类型。这看起来很愚蠢,因为我不知道所有支持的类型。也许这些类型会改变,等等,但我把它硬编码了。

我怎样才能最好地处理这个问题?

编辑:

所以,为了更具体一点,这是BST的实施:

public class BinarySearchTree<T extends Comparable> {
    private T value;
    private BinarySearchTree<T> leftChild;
    private BinarySearchTree<T> rightChild;

    public BinarySearchTree() {

    }

    public BinarySearchTree(T v) {
        value = v;
        createChildren();
    }

    public void createChildren() {
        leftChild = new BinarySearchTree<T>();
        rightChild = new BinarySearchTree<T>();
    }

    public void insert(T v) {
        if (value == null) {
            value = v;
            createChildren();
        } else if (v < value) {
            leftChild.insert(v);
        }
        rightChild.insert(v);
    }

    public boolean valueExists(T v) {
        if (value == null) {
            return false;
        } else if (value == v) {
            return true;
        } else if (v < value) {
            return leftChild.valueExists(v);
        }
        return rightChild.valueExists(v);
    }

    public String toString() {
        String bstStringBuilder = "";

        if (value == null) {
            return "";
        }

        bstStringBuilder += leftChild + " ";
        bstStringBuilder += value + " ";
        bstStringBuilder += rightChild;
        return bstStringBuilder;
    }
}

如果我使用@ OldCurmudgeon的建议,main()看起来像这样:

public static void main(String[] args) {
    Integer[] integerItems = {1, 7, 8, 2, -1, -10, 100, 12, 32};
    String[] stringItems = {"jungi", "phil", "bob", "leslie", "tyler", "clarence"};
    Comparable[][] comparableLists = {integerItems, stringItems};

    for (Comparable[] list : comparableLists) {
        BinarySearchTree<Comparable> root = new BinarySearchTree<Comparable>();

        for (Comparable item : list) {
            root.insert(item);
        }

        System.out.println(root);
    }
}

这会产生以下编译器错误:

BinarySearchTree.java:26: error: bad operand types for binary operator '<'
    } else if (v < value) {
                 ^
first type:  T
second type: T
where T is a type-variable:
  T extends Comparable declared in class BinarySearchTree
  BinarySearchTree.java:37: error: bad operand types for binary operator '<'
      } else if (v < value) {
                 ^
first type:  T
second type: T
where T is a type-variable:
  T extends Comparable declared in class BinarySearchTree
2 errors

也许这更有帮助?

3 个答案:

答案 0 :(得分:0)

救援的一般方法!

查找

class BinarySearchTree<T extends Comparable<T>> {
    void put(T item) {}
}

class Test {

    public static <T extends Comparable<T>> void putIntoATree(BinarySearchTree<T> tree, T[] items) {
        for (T item : items)
            tree.put(item);
    }

    public static void main(String[] args) {

        Integer[] integerItems = {1, 7, 8, 2, -1, -10, 100, 12, 32};
        BinarySearchTree<Integer> integerTree = new BinarySearchTree<>();
        putIntoATree(integerTree, integerItems);

        String[] stringItems = {"jungi", "phil", "bob", "leslie", "tyler", "clarence"};
        BinarySearchTree<String> stringTree = new BinarySearchTree<>();
        putIntoATree(stringTree, stringItems);

    }

}

在您的示例中,存在包含泛型类型的数组通常会强制某个地方施放(或者留下“未经检查”的警告)。这就是为什么我在我的例子中避免使用数组。

消除强制转换并使代码类型安全的一种方法是将数组包装到一个通用类中,这将使javac满意:

class BinarySearchTree<T extends Comparable<T>> {
    void put(T item) {}
}

class Test {

    public static <T extends Comparable<T>> void putIntoATree(BinarySearchTree<T> tree, T[] items) {
        for (T item : items)
            tree.put(item);
    }

    private static class ArrayAndATree<T extends Comparable<T>> {
        final T[] contents;
        final BinarySearchTree<T> aTree;

        private ArrayAndATree(T[] contents) {
            this.contents = contents;
            aTree = new BinarySearchTree<>();
        }
    }
    public static void main(String[] args) {

        Integer[] integerItems = {1, 7, 8, 2, -1, -10, 100, 12, 32};
        String[] stringItems = {"jungi", "phil", "bob", "leslie", "tyler", "clarence"};

        ArrayAndATree<Integer> integerArrayAndATree = new ArrayAndATree<>(integerItems);
        ArrayAndATree<String> stringArrayAndATree = new ArrayAndATree<>(stringItems);

        ArrayAndATree<?> taggedArrays[] = {integerArrayAndATree, stringArrayAndATree};
        for (ArrayAndATree<?> a : taggedArrays) {
            putIntoATree(a.aTree, a.contents);
            process(a);
        }
    }

    private static <T extends Comparable<T>> void process(ArrayAndATree<T> a) {
        putIntoATree(a.aTree, a.contents);
    }
}

答案 1 :(得分:0)

这是为多种类型的对象使用通用接口的关键。使用Comparable

    for (Comparable[] list : comparableLists) {
        BinarySearchTree<Comparable> tree = ...

答案 2 :(得分:-1)

您不需要在运行时知道具体类型,在编译时应用泛型。

所以在你的代码中你可以这样做:

public static void main(String[] args) {
    Integer[] integerItems = {1, 7, 8, 2, -1, -10, 100, 12, 32};
    String[] stringItems = {"jungi", "phil", "bob", "leslie", "tyler", "clarence"};
    Comparable[][] comparableLists = {integerItems, stringItems};

    for (Comparable[] list : comparableLists) {
        BinarySearchTree b = BinarySearchTree.class.newInstance();
        for (Object element : list) {
            b.add(element); // or whatever method you want to use
        }
    }
}

您现在需要注意不要使用错误的类型,因为编译器没有给您任何指导