简体   繁体   English

如何从Java中的函数返回通用Collection?

[英]How to return generic Collection from a function in Java?

So I can across this piece of code which is a demostration for generic methods in Java: 因此,我可以遍历这段代码,这是Java中通用方法的演示:

public static <T> T addAndReturn(T element, Collection<T> collection){
    collection.add(element);
    return element;
}

....

String stringElement = "stringElement";
List<String> stringList = new ArrayList<String>();
String theElement = addAndReturn(stringElement, stringList); 

But instead of returning the element I want to send back the whole collection object . 但是,我不想返回元素,而是要发回整个集合对象 I have tried few giving return type as Collection but it is somehow not working, 我尝试了很少的给定返回类型作为Collection的方法,但是它不起作用,

public static <T> Collection<T> addAndReturn(T element, Collection<T> collection) {
        collection.add(element);
        System.out.println(collection);
        return collection;
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        // your code goes here
        String stringElement = "stringElement";
        List<String> strList = new ArrayList<String>();

        ArrayList<String> strRes = addAndReturn(stringElement, strList);
        System.out.println(strRes);
    }

and received this error: 并收到此错误:

Main.java:22: error: incompatible types: no instance(s) of type variable(s) T exist so that Collection conforms to ArrayList ArrayList strRes = addAndReturn(stringElement, strList); Main.java:22:错误:不兼容的类型:不存在类型变量T的实例,因此Collection符合ArrayList ArrayList strRes = addAndReturn(stringElement,strList); ^ where T is a type-variable: T extends Object declared in method addAndReturn(T,Collection) 1 error ^其中T是类型变量:T扩展在方法addAndReturn(T,Collection)中声明的对象1错误

can anyone help me with the solution ? 谁能帮助我解决这个问题?

code sample is from Jenkov.com 代码示例来自Jenkov.com

Edit, given the comments from the OP: one has to understand that ArrayList derives from Collection. 根据OP的评论进行编辑:必须理解ArrayList从Collection派生的。 So when the interface of a method returns Collection<T> , then of course, you can only assign the result to a Collection , but not to a List/ArrayList. 因此,当方法的接口返回Collection<T> ,当然,您只能将结果分配给Collection ,而不能分配给List / ArrayList。 The fact that you pass in a List instance isn't known. 您不知道传入List实例的事实。 The compiler only sees that a Collection comes back! 编译器只会看到Collection回来了!

Coming back to the first question: your code is returning the element that got added: 回到第一个问题:您的代码正在返回添加的元素:

public static <T> T addAndReturn(T element, Collection<T> collection){
    collection.add(element);
    return element;
}

Simply change the signature and the returned thing: 只需更改签名和返回的内容:

public static <T> Collection<T> addAndReturn(T element, Collection<T> collection){
    collection.add(element);
    return collection;
}

Done? 做完了吗 Not really. 并不是的。

As in: that isn't good practice. 如:这不是一个好习惯。 Returning something that came in as parameter can quickly lead to confusion for readers of your code. 返回以参数形式出现的内容会很快导致代码阅读者感到困惑。 Confusing your readers is a bad thing to do. 混淆读者是一件坏事

Beyond that: the whole method is simply bogus itself, as callers of the method could as well just write: 除此之外:整个方法本身就是伪造的 ,因为方法的调用者也可以这样写:

thatCollection.add(thatElement);

themselves. 他们自己。 Your method doesn't add any value to the above! 您的方法不会为上述方法增加任何价值! It rather obscures things for the readers. 对于读者而言,这相当模糊。

Why would anybody want to write: 为什么有人要写:

addAndReturn(someX, listOfXes);

instead of 代替

listOfXes.add(someX);

If the point would be to do: 如果要这样做:

addAndReturn(someX, listOfXes).addAndReturn(someOtherX, listOfXes);

You rather go: 您宁愿去:

listOfXes.addAll(Arrays.asList(someX, someOtherX));

for example. 例如。 Don't invent "utilities" for things that can be dealt with using standard library calls. 不要为可以使用标准库调用处理的事情发明“实用程序”。

Is this what you are looking for? 这是你想要的?

public static <T> Collection<T> addAndReturn(T element, Collection<T> collection) {
    collection.add(element);
    return collection;
}

It goes like in the listing below. 就像下面的清单一样。

public static <T> Collection<T> addAndReturn(final T element, final Collection<T> collection) {
    collection.add(element);
    return collection;
}

@Test
public void test() {
    final String stringElement = "stringElement";
    final List<String> stringList = new ArrayList<String>();
    final List<String> nextList = (List<String>) addAndReturn(stringElement, stringList);
    assertThat(nextList.get(0), is(equalTo(stringElement)));
}

All you have to care about is the right return parameter Collection<T> . 您只需要关心正确的返回参数Collection<T> Maybe you have to cast if you want it from a child class or interface like List final List<String> nextList = (List<String>) addAndReturn(stringElement, stringList); 如果您想从子类或接口(如List final List<String> nextList = (List<String>) addAndReturn(stringElement, stringList); .

The error message is pointing to this line: 错误消息指向此行:

 ArrayList<String> strRes = addAndReturn(stringElement, strList); 

And it is telling you (in non-Compilerese plain English) that it could not find a generic type that would allow this assignment to happen. 它告诉您(使用非Compilerese普通英语),它找不到允许该分配发生的通用类型。

Your method returns a Collection<T> (in this case a Collection<String> ). 您的方法返回Collection<T> (在本例中为Collection<String> )。 Collection<String> is not a subtype of ArrayList<String> , ergo, you are not allowed to assign an object of type Collection<String> to a field of type ArrayList<String> . Collection<String>不是ArrayList<String>的子类型,因此您不允许将Collection<String>类型的对象分配给ArrayList<String>类型的字段。 Your method returns a Collection<String> , so the easiest fix is to just assign it to a field of type Collection<String> : 您的方法返回Collection<String> ,因此最简单的解决方法是将其分配给Collection<String>类型的字段:

Collection<String> strRes = addAndReturn(stringElement, strList);

Alternatively, you could make use of local variable type inference (assuming you are using a current version of Java): 或者,您可以使用局部变量类型推断(假设您使用的是Java的当前版本):

var strRes = addAndReturn(stringElement, strList);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM