As described in the Java Programming Idea (4th edition), generics appear to be motivated by:
There are many reasons for the emergence of generics, and one of the most noticeable reasons is to create container classes.
Generic class
The container class should be one of the most reusable class libraries. Let's take a look at how a container class is defined without a generic type:
Public classContainer {PrivateString Key; PrivateString value; PublicContainer (string k, string v) {key=K; Value=v; } PublicString GetKey () {returnkey; } Public voidSetkey (String key) { This. Key =key; } PublicString GetValue () {returnvalue; } Public voidSetValue (String value) { This. Value =value; }}
Container
class holds a pair of key-value
A key-value pair, but the type is dead, and it says if I want to create a key-value pair Yes String-Integer
type of, current this Container
cannot be done and must be customized. So this obviously reusability is very low.
Of course, I can use it Object
instead String
, and we can only do that before Java SE5, because Object
it's all types of base classes, so it's a straightforward transformation. But this flexibility is not enough, because the type is still specified, but this time the specified type level is higher, is it possible not to specify the type? Is it possible to know what the specific type is at run time?
As a result, generics are present.
Public classContainer<k, v> { PrivateK Key; PrivateV value; PublicContainer (k K, v V) {key=K; Value=v; } PublicK GetKey () {returnkey; } Public voidSetkey (K key) { This. Key =key; } PublicV GetValue () {returnvalue; } Public voidSetValue (V value) { This. Value =value; }}
At compile time, it is impossible to know K
V
what the type is, and only when the runtime actually constructs and allocates memory based on the type. You can look at Container
the current classes for different types of support situations:
Public classMain { Public Static voidMain (string[] args) {Container<string, string> c1 =NewContainer<string, string> ("name", "Findingsea"); Container<string, integer> c2 =NewContainer<string, Integer> ("Age", 24); Container<double, double> c3 =NewContainer<double, Double> (1.1, 2.2); System.out.println (C1.getkey ()+ " : " +C1.getvalue ()); System.out.println (C2.getkey ()+ " : " +C2.getvalue ()); System.out.println (C3.getkey ()+ " : " +C3.getvalue ()); }}
Output:
241.1:2.2
Generic interface
In a generic interface, the generator is a good understanding, see the following builder interface definition:
Public Interface Generator<t> { public T Next ();}
Then define a generator class to implement this interface:
Public class Implements Generator<string> { privatenew string[]{"Apple", "Banana", "Pear"}; @Override public String Next () { new Random (); return fruits[rand.nextint (3)];} }
Call:
Public class Main { publicstaticvoid main (string[] args) { new fruitgenerator (); System.out.println (Generator.next ()); System.out.println (Generator.next ()); System.out.println (Generator.next ()); System.out.println (Generator.next ());} }
Output:
Bananabananapearbanana
Generic methods
A basic principle is that whenever you can do it, you should try to use a generic method. That is, if the generic method can be used instead of generalizing the entire class, then the generic method should be limited. Here's a simple definition of a generic method:
Public class Main { publicstaticvoid -out (T-t) { System.out.println (t); } publicstaticvoid main (string[] args) { out ("Findingsea" ); Out (123); Out (11.11); Out (true);} }
You can see that the parameters of the method are thoroughly generalized, the process involves the compiler's type deduction and automatic packaging, but also said that the original needs our own type of judgment and processing, now the compiler to help us do. This greatly increases the flexibility of programming by not having to think about which types of parameters to handle later in the process of defining the method.
Let's look at an example of a generic method and a mutable parameter:
Public class Main { publicstaticvoid out (t ... args) { for (T t : args) { System.out.println (t); } } Public Static void Main (string[] args) { out (true); }}
The output is the same as the previous piece of code, and you can see that generics can be perfectly combined with variable parameters.
Above, the end of the first part of the generics.
Java generics: Generic classes, generic interfaces, and generic methods