简体   繁体   中英

Using an Object as argument on unbounded wildcard reference object

Simple class:

class Box<T> {
    private T t;

    public Box(T t) {
        this.t = t;
    }

    public void put(T t) {
        this.t = t;
    }
}

trying to execute put() method passing an instance of Object

Box<?> box = new Box<String>("abc");
box.put(new Object());

Compiler points out an error:

The method put(capture#1-of ?) in the type Box<capture#1-of ?> is not applicable for the arguments (Object)

Compiler in fact does not know what type to expect, but one thing is sure - it will be an Object or a subclass of it. Why is the error raised then?

thank you

Your example clearly explains why.

The actual type of the box is Box<String> . So you really don't want to be able to put something other than String instances to this box.

Box<?> means: "a box of some type that is unknown to the compiler". So you can get anything you want from such a box, and you'll get Object instances, but you may not store anything into the box, because the compiler can't guarantee that the object you're storing has the appropriate type:

class Box<T> {
    private T t;

    public Box(T t) {
        this.t = t;
    }

    public void put(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }
}

Box<?> box = new Box<String>("abc");
Object o = box.get(); // no problem
box.put(new Object()); // fail

The goal of generics is to make your code type-safe. If you could add arbitrary objects to a box that is actually a Box<String> , you wouldn't have any type-safety anymore.

This tutorial states that:

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Same compile time error as yours

"Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.

On the other hand, given a List, we can call get() and make use of the result. The result type is an unknown type, but we always know that it is an object. It is therefore safe to assign the result of get() to a variable of type Object or pass it as a parameter where the type Object is expected."

To explain, basically you can call get() to return the type, but you cannot add because the compiler doesn't know what type it is and the passed parameter needs to extend the unknown type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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