Java Theory and Practice: Using wildcard characters to simplify generics use

Source: Internet
Author: User

Since generics have been added to the JDK 5 language, it has been a controversial topic. Some people think generics simplify programming, extend the type system so that the compiler can verify type safety, and others think generics add a lot of unnecessary complexity. We have experienced some painful memories of generics, but there is no doubt that wildcards are the trickiest part.

General Introduction to wildcard characters

A generic is a method that represents the type constraints of a class or method behavior for an unknown type. For example, "regardless of the parameter x and Y of this method, they must be of the same type", "The parameter of the same type must be supplied for these methods" or "The Return value of Foo () and the parameter of Bar () are of the same type."

Wildcard character-use a strange question mark to represent a type parameter-is a method that represents a type constraint of an unknown type. The wildcard character is not included in the original generic design (originating from the Generic Java ()), completing the design process over a period of more than five years from the formation of JSR 14 to the release of its final version and being added to the generics.

Wildcard characters are important in type systems, and they provide a useful type range for a collection of types specified by a generic class. For generic class ArrayList, for any (reference) type t,arraylist<?> type is a arraylist<t> type (similar to the original type ArrayList and root type Object, but these types are in the execution type The inference aspect is not very useful).

Wildcard type list<?> are not the same as the original type List and the specific type list<object>. If the variable x has a list<?> type, it means there are some T types, where x is the list<t> type and x has the same structure, although we do not know the exact type of its elements. This does not mean that it can have arbitrary content, but that we do not understand the type limitations of the content-but we know there is a limit. On the other hand, the original type List is heterogeneous and we cannot have any type restrictions on its elements, and the specific type list<object> indicates that we know clearly that it can contain any object (of course, the generic type system does not have the concept of "list content", but you can A collection type like this easily understands generics.

The role of wildcards in a type system is derived from the feature that does not occur covariant (covariant). The array is covariant because the Integer is a subtype of number, and the array type integer[] is a subtype of number[, so you can provide a integer[value wherever you want the number[value. On the other hand, generics are not covariant, and list<integer> is not a subtype of list<number>, attempting to provide list<integer> in a location that requires list<number> is a type error. This is not a serious problem-and not a mistake everyone thinks of-but the different behavior of generics and arrays does cause a lot of confusion.

I've used a wildcard character-what's next?

Listing 1 shows a simple container (container) type Box that supports put and get operations. box is parameterized by type parameter T, which represents the type of the box content, and box<string> can only contain String-type elements.

Listing 1. Simple generic Box type

public interface Box<T> {
   public T get();
   public void put(T element);
}

One advantage of wildcards is that it allows you to write code that can manipulate generic type variables without having to understand their specific types. For example, suppose you have a variable of type box<?>, such as the box argument in the Listing 2 Unbox () method. Unbox () How do I handle the passed box?

Listing 2. A Unbox method with wildcard parameters

public void unbox(Box<?> box) {
   System.out.println(box.get());
}

It turns out that the Unbox method can do a lot of work: it can call the Get () method, and it can call any method inherited from Object (such as hashcode ()). The only thing that it can't do is call the put () method, because it cannot verify the security of the operation without knowing the type parameter T of the Box instance. Since box is a box<?> rather than an original box, the compiler knows that there are some type parameters that T acts as box, but because you do not know what T is, you cannot invoke put () because you cannot verify that doing so does not violate box type security restrictions (in fact, You can invoke put () in a special case: when you pass a null letter. We may not know what the T type represents, but we know that the null letter is a null value for any reference type.

What do unbox () know about the return type of Box.get ()? It knows that Box.get () is a t of some unknown t, so it can infer that the return type of Get () is the erasure of T (Erasure), and that a wildcard with no upper bounds is Object. So the expression in Listing 2 Box.get () has an Object type.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.