We all know that Java introduced generics in 1.5. The essence of generics is parameterized typing, that is, the type of a variable is a parameter, and then specified as a specific type when used. Generics can be used for classes, interfaces, and methods, making code simpler and safer by using generics. This article by referring to “Java Programming ideas” in the use of generics need to pay attention to the problems are summarized and to provide you with some generics related interview questions for you to learn to use.

Generics related issues

1. Generic type reference passing problem

In Java, passing a reference like the following is not allowed:

Let’s look at the first case and expand the first case into the following form:

In fact, at line 4, there will be a compilation error. So, let’s assume it compiled correctly. So when we use the arrayList2 reference to get(), we return String objects, but we’ve already stored Object objects in it, so we have a ClassCastException. So to avoid this easy error, Java does not allow such reference passing. (That’s why generics came in, to solve the problem of type conversions, and we can’t defeat their purpose.)

Looking at the second case, expand the second case into the following form:

Yes, this is much better than the first case. At the very least, we don’t get a ClassCastException when we use arrayList2 because we’re converting from String to Object. But what’s the point? Generics were invented to solve the problem of type conversions. We use generics, and in the end, we end up trying to override them, defeating what generics were designed to do. So Java doesn’t allow it. Besides, if you add() a new Object with arrayList2, how do I know if I’m retrieving a String or an Object? Therefore, pay special attention to reference-passing problems in generics.

2. Generic type variables cannot be primitive data types

So for example, there’s no ArrayList, there’s only ArrayList. Because when the type is erased, the type variable (T) in the original class of ArrayList is replaced with Object, but Object cannot store a double.

3. Run time type query

Because the type is erased, the ArrayList is left with the original type, and the generic String information is gone.

4. Problems with generics in static methods and classes

Static methods and static variables in a generic class may not use the generic type parameters declared by the generic class

Because the instantiation of generic parameters in a generic class is specified when an object of generic type (such as ArrayList) is defined, static variables and static methods do not need to be invoked using objects. Object is not created, how to determine what type this generic parameter is, so of course it is wrong.

But be careful to distinguish between the following:

Because this is a generic method, the T used in the generic method is the T defined in the method itself, not the T in the generic class.

Generic interview questions

1. What are generics in Java? What are the benefits of using generics?

Generics are a mechanism for parameterizing types. It allows you to write more generic code, such as collections frameworks, by making code applicable to a variety of types. Generics are a compile-time type validation mechanism. It provides compile-time type safety, ensuring that only objects of the correct type can be used on generic types (usually collections of generic types), and avoiding classcastExceptions at runtime.

How do Generics work in Java? What is type erasure?

Generics rely on the compiler compiling the source code by checking the type, erasing the type, and inserting instructions for casts where type parameters appear.

The compiler erases all type-specific information at compile time, so there is no type-specific information at run time. For example, a List is represented at run time by a single List type. Why do I erase it? This is to avoid type bloat.

3. What are qualified and unqualified wildcards in generics?

Qualified wildcards restrict types. There are two qualified wildcards, one in which it sets an upper bound on a type by ensuring that it must be a subclass of T, and the other in which it sets a lower bound on a type by ensuring that it must be a superclass of T. A generic type must be initialized with a qualified type, otherwise a compilation error will result. The other hand represents unqualified wildcards because <? > can be substituted with any type.

4. List<? Extends T> and List <? What’s the difference between super T>?

This relates to the last interview question, which is sometimes used by interviewers to assess your understanding of generics rather than directly asking you what qualified and unqualified wildcards are. Both List declarations are examples of qualified wildcards, List<? Extends T> accepts any List of type inherited from T, and List<? Super T> can accept any List of T’s superclasses. For example the List <? Extends Number> can take a List or List. You can find more information in the links that appear in this section.

5. How do I write a generic method that accepts generic parameters and returns generic types?

It’s not difficult to write generic methods. You need to replace primitive types with generic types, such as T, E or K,V, which are generally accepted type placeholders. See the Java Collection Class Framework for an example of generic methods. In the simplest case, a generic method might look like this:

6. How to write classes with parameters using generics in Java?

This is an extension of the previous interview question. Instead of writing a generic method, the interviewer may ask you to write a type-safe class using generics. The key is still to use generic types instead of primitive types, and to use the standard placeholders used in the JDK.

7. Write a generic program to implement LRU caching?

This is an exercise for anyone who likes Java programming. As a hint, LinkedHashMap can be used to implement a fixed size LRU cache, and when the LRU cache is full, it removes the oldest key/value pairs from the cache. LinkedHashMap provides a method called removeEldestEntry(), which is called by put() and putAll() to remove the oldest key-value pair.

8. Can you pass a List to a method that takes a List argument? (See instructions above)

For anyone not familiar with generics, this Java generics topic may seem confusing, because at first glance String is an Object, so List should be used where List is needed, but it isn’t. Doing so will result in a compilation error. If you think about it a little bit further, you’ll see that Java makes sense to do this, because lists can store any type of object including Strings, integers, and so on, whereas lists can only store Strings.

9. Can generics be used in Array?

This is probably the easiest interview question for Java generics, assuming you know that Array doesn’t actually support generics, which is why Joshua Bloch in Effective Java recommends using List instead of Array, Because List provides compile-time type safety, Array does not.

10. How do I prevent type unchecked warnings in Java?

If you mix generics with primitive types, as in the following code, Java 5’s Javac compiler will raise a type-unchecked warning, such as List rawList = new ArrayList(). Note: Hello.java uses an unchecked or unsafe operation; Such warnings can be masked using the @SuppressWarnings(“unchecked”) annotation.

What is the difference between a List and a primitive List in Java?

The main difference between primitive types and parameterized types is that at compile time the compiler does not type safety check for primitive types, but for parameterized types. By using Object as a type, you can tell the compiler that the method can accept objects of any type, such as String or Integer. The key to this problem is the correct understanding of primitive types in generics. The second difference is that you can pass any generic type with arguments to a method that accepts the primitive type List, but you can’t pass a List to a method that accepts a List, because a compilation error will occur.

List<? What’s the difference between > and List?

This problem looks like the last one, but it’s completely different. List is a List of unknown type, and List is really a List of any type. You can assign List, List to List, but you can’t assign List to List.

13, The difference between a List and a primitive List.

This question is similar to “what is the difference between primitive type and parameter type”. Parameterized types are type-safe and are guaranteed by the compiler, but primitive List types are not. You can’t store any Object of any type in a List of strings, but you can store any Object of any type in the original List. With generic parameterized types you don’t need to cast, but with primitive types you do need to cast explicitly.

The wildcard

Wildcard upper bound

Routine use of

Output:

2 2

3 0

The illegal use of

List<? Extends Number> can be a List or List. Why not add Integer or Float?

First of all, we know that only integers can be added to a List. And the following code is possible:

Assuming that the previous example did not compile correctly, if we passed list1 or list2 to fillNumberList, we would obviously get a type mismatch.

Therefore, we come to the conclusion that the List<? Extends T> adds any object except null.

So why is List<? Extends T> Extends T> Iterates is ok because a subclass must have the same interface as its parent, which is what we expect.

Wildcard lower bound

Routine use of

You can add any subclass of Number. Why?

List<? Super Number> can stand for List, where T is the parent of Number (although Number has no parent). If T is the parent of Number, we think it’s okay to add a subclass of Number to List.

The illegal use of

For a List <? SuperT > iterating is not allowed. Why is that? Do you know what interface to use to iterate over a List? Only an interface of the Object class can guarantee that all elements in the collection have that interface, which obviously doesn’t make much sense. The application scenarios are omitted.

Unbounded wildcard

Knowing the upper and lower bounds of wildcards is the same as knowing the unbounded wildcards. . Such as the List <? Word-wrap: break-word! Important; “> Can represent any type, “any” is unknown type.

List is not the same as List; List is a subclass of List. And can’t go to List<? > add any object to list except null.

Routine use of

1. When the method takes the original Object type as an argument, it looks like this:

You can choose to implement it as follows:

This is compatible with more output than just a List, as follows:

“Like” to prove you still love me