Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to apply generics in Java

2025-03-04 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the knowledge of "how to apply generics in Java". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Overview of generics

Generics play an important role in java and are widely used in object-oriented programming and various design patterns.

What is generics? Why use generics?

Generics, or "parameterized types". When it comes to parameters, the most familiar thing is to have formal parameters when defining a method, and then pass arguments when you call this method. So how do you understand parameterized types? As the name implies, the type is parameterized by the original specific type, similar to the variable parameters in the method, and the type is also defined as a parameter (which can be called a type parameter). Then pass in the specific type (type argument) when using / calling.

The essence of generics is to parameterize types (the types of specific restrictions on formal parameters are controlled by different types specified by generics without creating new types). In other words, in the use of generics, the data type of the operation is specified as a parameter, which can be used in classes, interfaces, and methods, which are called generic classes, generic interfaces, and generic methods, respectively.

A chestnut.

An example that has been cited countless times:

List arrayList = new ArrayList (); arrayList.add ("aaaa"); arrayList.add (100); for (int I = 0; I < arrayList.size (); iTunes +) {String item = (String) arrayList.get (I); Log.d ("generic Test", "item =" + item);}

There is no doubt that the running result of the program will end in a crash:

Java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

ArrayList can store any type. In the example, a String type is added, an Integer type is added, and the program crashes when it is reused in the way of String. In order to solve problems like this (which can be solved at compile time), generics emerge as the times require.

Let's change the first line of code that declares that the list is initialized, and the compiler will be able to help us find problems like this during the compilation phase.

ListarrayList = new ArrayList ()

...

/ / arrayList.add; during the compilation phase, the compiler will report an error

Characteristics

Generics are only valid during the compile phase. Look at the following code:

List stringArrayList = new ArrayList (); List integerArrayList = new ArrayList (); Class classStringArrayList = stringArrayList.getClass (); Class classIntegerArrayList = integerArrayList.getClass (); if (classStringArrayList.equals (classIntegerArrayList)) {Log.d ("generic test", "same type");}

As can be proved by the above example, the program will take measures to de-generalize after compilation. In other words, generics in Java are only valid during the compile phase. During compilation, after correctly verifying the generic results, the relevant information about the generics is erased, and methods of type checking and type conversion are added at the boundaries where the object enters and leaves the method. That is, generic information does not enter the runtime phase.

This can be summed up in one sentence: generic types are logically regarded as many different types, but in fact they are all the same basic types.

Generics can be used in three ways: generic classes, generic interfaces, and generic methods.

Generic class

Generic types are used in the definition of classes and are called generic classes. Through generics, you can open the same interface to the operation of a set of classes. The most typical are various container classes, such as List, Set, Map.

The most basic way to write a generic class (which may be a little dizzy in this way, which will be explained in more detail in the following example):

Class class name {private generic ID / * (member variable type) * / var;. }

One of the most common generic classes:

/ / T can be written as any logo here, and common parameters such as T, E, K, V are often used to represent generics.

/ / when instantiating a generic class, you must specify that the specific type of T, public class Generic {/ / can be used throughout the generic class declared in the class, except for the static part, because the generic type is declared when instantiated. / / the code for the static region has been determined at compile time that only the method or class associated with the class class A {T t;} / re-declares that a generic type of the same name is allowed, and that the generic type overrides the parent class's T class B {T t } / / static inner classes can also use generics. The actual type static class C {T t;} public static void main (String [] args) {/ / error is given when instantiating, and T generics cannot be used, because generic T belongs to the instance and does not belong to the class / / T t = null. } / / the type of the member variable private T key; public Generic (T key) {/ / generic constructor parameter key is specified externally by this.key = key;} public T getKey () {/ / the return type of generic method getKey is TMagol T by externally specified return key;}}

12-27 0915 0432 13063-13063? D / generic Test: key is 123456

12-27 0915 0432 13063-13063? D / generic test: key is key_vlaue

For a defined generic class, do you have to pass in generic type arguments? This is not the case. If generic arguments are passed in when using generics, restrictions will be made according to the passed generic arguments. Only then will generics play the limiting role that should have been played. A type defined using generic methods or member variables in a generic class can be any type without passing in generic type arguments.

Look at an example:

Generic generic = new Generic ("111111"); Generic generic1 = new Generic (4444); Generic generic2 = new Generic (55.55); Generic generic3 = new Generic (false); Log.d ("generic Test", "key is" + generic.getKey ()); Log.d ("generic Test", "key is" + generic1.getKey ()); Log.d ("generic Test", "key is" + generic2.getKey ()); Log.d ("generic Test", "key is" + generic3.getKey ()) D / generic test: key is 111111D/ generic test: key is 4444D/ generic test: key is 55.55D/ generic test: key is false

Note:

The type parameters of generics can only be class types, not simple types.

You cannot use instanceof operations on exact generic types. If the following operation is illegal, there will be an error during compilation.

If (ex_num instanceof Generic) {

}

Generic interface

The definition and use of generic interfaces are basically the same as those of generic classes. Generic interfaces are often used in various types of producers. Take a look at an example:

/ / define a generic interface public interface Generator {public T next ();}

When a generic argument is not passed in to a class that implements a generic interface:

When no generic argument is passed in, the definition of the generic class is the same as that of the generic class. When declaring the class, the declaration of the generic type needs to be added to the class * that is: class FruitGenerator implements Generator {* if the generic type is not declared, such as class FruitGenerator implements Generator, the compiler will report an error: "Unknown class" * / class FruitGenerator implements Generator {@ Override public T next () {return null;}}

When a class that implements a generic interface passes in a generic argument:

/ * when passing generic arguments: * define a producer to implement this API. Although we have only created a generic interface Generator *, we can pass numerous arguments to T to form numerous types of Generator interfaces. * when the implementation class implements the generic interface, if the generic type has been passed into the argument type, all places where the generic type is used should be replaced with the passed argument type * that is, the T in Generator,public T next (); should be replaced with the passed String type. * / public class FruitGenerator implements Generator {private String [] fruits = new String [] {"Apple", "Banana", "Pear"}; @ Override public String next () {Random rand = new Random (); return fruits [rand.nextInt (3)];}} generic wildcard

We know that Ingeter is a subclass of Number, and we have verified in the features section that Generic and Generic are actually the same basic type. So the question is, in the method that uses Generic as the formal parameter, can an instance of Generic be passed in? Can logically similar Generic and Generic be regarded as generic types with a parent-child relationship?

To figure this out, let's use the generic class Generic to continue with the following example:

Public void showKeyValue1 (Generic obj) {Log.d ("generic testing", "key value is" + obj.getKey ());} Generic gInteger = new Generic (123); Generic gNumber = new Generic (456); showKeyValue (gNumber); / / showKeyValue this method compiler will report an error for us: Generic// cannot be applied to Generic// showKeyValue (gInteger)

From the prompt, we can see that Generic cannot be regarded as a subclass of `Generic. It can be seen that the same generic type can correspond to multiple versions (because the parameter type is uncertain), and different versions of generic class instances are incompatible.

Going back to the above example, how to solve the above problem? You can't deal with classes of type Generic in order to define a new method, which obviously runs counter to the concept of multiple machines in java. So we need a reference type that logically represents both the Generic and Generic parent classes. This type wildcard arises at the historic moment.

We can change the above method:

Public void showKeyValue1 (Generic obj) {Log.d ("generic test", "key value is" + obj.getKey ())

Type wildcards are generally used? Instead of specific type arguments, note that here? It is a practical type like Number, String and Integer. As the parent of all types. It's a real type.

It can be solved that when the specific type is uncertain, the wildcard is?; when you manipulate the type, you only use the functions in the Object class when you do not need to use the specific functions of the type. So it works? Wildcards to represent unknown types

Public void showKeyValue (Genericobj) {

System.out.println (obj)

}

Generic gInteger = new Generic; Generic gNumber = new Generic; public void test () {/ / showKeyValue (gInteger); this method will report an error showKeyValue1 (gInteger);} public void showKeyValue1 (Generic obj) {System.out.println (obj);} / showKeyValue this method compiler will report an error for us: Generic// cannot be applied to Generic// showKeyValue (gInteger)

.

Generic method

In java, the definition of generic classes is very simple, but generic methods are more complex.

In particular, most of the member methods in generic classes we see also use generics, and some even contain generic methods in generic classes, so it is very easy for beginners to misunderstand generic methods.

A generic class indicates the specific type of a generic type when instantiating a class; a generic method specifies the specific type of a generic type when calling a method.

The return value of the generic argument * @ return T passed in by * @ param tClass is of type T * description: * 1) it is very important between the public and the return value, which can be understood as declaring that this method is a generic method. * 2) only declared methods are generic methods, and member methods in generic classes that use generics are not generic methods. * 3) indicates that the method will use the generic type T before you can use the generic type T in the method. * 4) like the definition of a generic class, T can be written as any identification here, and common parameters such as T, E, K, V are often used to represent generics. * / public T genericMethod (Class tClass) throws InstantiationException, IllegalAccessException {T instance = tClass.newInstance (); return instance;} Object obj = genericMethod (Class.forName ("com.test.test")); basic usage of generic methods

Just looking at the above example, some students may still be very confused. Let's summarize my generics method again through another example.

/ * this is a true generic method. * first of all, it is necessary between the public and the return value, which indicates that this is a generic method and declares a generic T * this T can appear anywhere in the generic method. * the number of generics can also be any number * for example: public K showKeyName (Generic container) {* *} * / public class generic method {@ Test public void test () {test1 (); test2 (new Integer (2)); test3 (new int [3], new Object ()) / / print the result / / null// 2 I@3d8c7aca// java.lang.Object@5ebec15 / [I@3d8c7aca// java.lang.Object@5ebec15} / / this method uses the generic T public void test1 () {T t = null; System.out.println (t) } / / the method uses the generic type T / / and the parameters and return values are of type T public T test2 (T t) {System.out.println (t); return t;} / / the method uses the generic type T public void test3 E / / parameters include TMagneE public void test3 (T t, E) {System.out.println (t); System.out.println (e) Generic methods in class}}

Of course, this is not the whole story of generic methods, which can be used anywhere and in any scenario. But there is a very special case. When a generic method appears in a generic class, let's look at it through another example.

/ / Note that the generic class writes the class name before the generic type, and the generic method writes the generic before the method name / / class A {{T t 1;} A (T t) {this.t = t;} T t; public void test1 () {System.out.println (this.t) is available in members and methods. } public void test2 (ds E) {System.out.println (t); System.out.println (e);}} @ Testpublic void run () {AA = new A (1); a.test1 (); a.test2 (2, "ds"); / / 1static class B / 2pm / ds} static class B {T t Public void go () {System.out.println (t);}} generic methods and variable parameters

Look at another example of generic methods and variable parameters:

Public class generics and variable parameters {@ Test public void test () {printMsg ("dasd", 1, "dasd", 2.0 false); print ("dasdas", "dasdas", "aa");} / / ordinary variable parameters can only be adapted to one type public void print (String... Args) {for (String t: args) {System.out.println (t);}} / / variable parameters of generics can match all types of parameters. A little bit invincible public void printMsg (T. Args) {for (T t: args) {System.out.println (t);}} / / print results: / / dasd / / 1 / / dasd / / 2.0 / / false} static methods and generics

One thing to note about static methods is that static methods in a class use generics: static methods cannot access generics defined on the class; if the reference data type of static method operations is uncertain, generics must be defined on methods.

That is, if static methods are to use generics, static methods must also be defined as generic methods.

Public class StaticGenerator {.... .... / * if you define a static method that uses generics in a class, you need to add an additional generic declaration (defining the method as a generic method) * even if the static method is to use generics that have already been declared in the generic class. * for example: public static void show (T t) {..}, the compiler will prompt an error message: "StaticGenerator cannot be refrenced from static context" * / public static void show (T t) {}} generic method summary

Generic methods can make methods change independently of the class. Here is a basic guiding principle:

Whenever you can do it, you should try to use generic methods. That is, if you use a generic method to generalize the entire class, you should use the generic method. In addition, for a method of static, you cannot access the parameters of a generic type. So if the static method is to use generic capabilities, it must be made generic.

Upper and lower boundaries of generics

When using generics, we can also impose upper and lower boundaries on incoming generic type arguments, for example, type arguments are only allowed to pass in a certain type of parent class or a certain type of subclass.

Add an upper boundary to the generic type, that is, the type argument passed in must be a subtype of the specified type

Public class generic wildcards and boundaries {public void showKeyValue (Generic obj) {System.out.println ("key value is" + obj.getKey ());} @ Test public void main () {Generic gInteger = new Generic (123); Generic gNumber = new Generic (456); showKeyValue (gNumber); / / subclasses in generics cannot be passed in / / showKeyValue (gInteger) as parent class references } / / Direct use? Wildcards can accept any type as a generic type passed into public void showKeyValueYeah (Generic obj) {System.out.println (obj);} / / can only be passed into subclasses of number or number public void showKeyValue1 (Generic

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report