Java Study Notes 10 -- generic summary, java Study Notes 10 -- generic
Java learning notes series:
Java study notes 9-internal class Summary
Java study note 8-interface Summary
Java study notes 7 -- abstract classes and abstract methods
Java study Note 6-class inheritance, Object class
Java study notes 5-Class Method
Java study note 4-object initialization and collection
Java Study Notes 3-Basics of classes and objects
Java study Note 2 -- data type, array
Java study Note 1-Summary of the development environment Platform
URL: http://www.cnblogs.com/archimedes/p/java-study-note10.html.
Data Types in the Collection class
Various types of data can be stored in the Collection class. Once the data is saved, its type is converted to the Object type. When retrieving data from a collection class, you generally need to convert the Object type back to the actual type before storing it
Vector v = new Vector ();
v.add ("zhang san); // Save the string
String name = (String) v.get (0); // Force type conversion, OK
v.add (new Date ()); // Save the current time object, OK
// Since the Date type cannot be converted to String, the following statement will cause an error at runtime, but this error will not be detected at compile
String date = (String) v.get (1); // The compiler will not find the problem
Strongly typed collection
An instance of a traditional collection class can store any type of data, and this collection class is called a weak type collection class. After JDK1.5, a strongly typed collection class was introduced:
In a strongly typed collection class, only data of the specified type can be stored
When taking out data from a strongly typed collection class, there is no need to perform type conversion processing. If the data type is not equipped, an error will be reported directly at compile time
Strongly typed collections do not introduce new class names. You only need to use angle brackets (<>) to indicate the names of the data types they store when you define the original collection object.
for example:
// The following instance of the vector class can only store string type data
Vector <String> v = new Vector <String> ();
v.add ("hello"); // The added string is OK
String name = v.get (0); // No type conversion is required when taking out. If you want to add date data to this strongly typed collection, an error will be reported at compile
v.add (new Date ()); // The compiler will directly report the type mismatch error
Generic class
Define Generics
The strongly typed collection uses the generic syntax introduced by JDK1.5. Generics are equivalent to a special type in a class. The characteristic of this type is that it can be specified as a specific actual type when instantiating the class.
The format of a class that contains generics is as follows:
[Access modifier] class class name <generic 1, generic 2,…> {
Generic 1 Generic member 1;
Generic 2 Generic member 2;
// ....
}
The generic symbols in the declaration, such as generic 1, generic 2, etc., can be any legal Java identifier.
Generic class declaration example
// Here declares a generic class containing a generic T, T represents all possible types, and the actual type of T is specified when the Generic class is instantiated.
class Generic <T> {
private T f; // f is a generic member
public void setF (T f) {// The parameter type of setF method is generic T
this.f = f;
}
public T getF () {// The return type of getF method is generic T
return f;
}
}
Instantiation of generic classes
When creating an instance of a generic class, you can use a pair of angle brackets to specify the true type of the generic
public class test {
public static void main (String args []) {
// The generic T in f1 is specified here as a Boolean type
Generic <Boolean> f1 = new Generic <Boolean> ();
// The generic T in f2 is specified here as the Integer type
Generic <Integer> f2 = new Generic <Integer> ();
// The setF method of f1 can only accept Boolean data
f1.setF (new Boolean (true));
Boolean b = f1.getF ();
System.out.println (b);
// The setF method of f2 can only accept data of type Integer
f2.setF (new Integer (10));
Integer i = f2.getF ();
System.out.println (i);
}
}
The default type of generics at instantiation
When a generic class is instantiated, it is not necessary to indicate the actual type corresponding to the generic, and then Object will be used as the default type
Generic f3 = new Generic ();
f3.setF (new Boolean (false));
The compiler will issue a warning during compilation:
Note: Generic.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint: unchecked for details.
Create an array of type generic
If you want to create an array of generic classes, you need to be careful not to add the actual type name of the generic after the new keyword, as follows:
Generic <String> [] gs; // Declare an array of generic classes
// First initialize the generic array
gs = new Generic [5]; // Do not write new Generic <String> [5]
// Initialize each array element separately
gs [0] = new Generic <String> (); // Assign value for the first array element
// ....
Example of class definition with multiple generics
Contains two generic definitions of class declaration and instantiation:
class Generic2 <T1, T2> {
private T1 f1;
private T2 f2;
// ...
}
// Give the actual type of generic T1, T2
Generic <Integer, Boolean> f = new Generic <Integer, Boolean> ();
// The actual types of generic T1 and T2 are not given
Generic f1 = new Generic (); // T1, T2 will default to Object type
Use of generic members
Generic members in a generic class cannot be instantiated directly, and their instances must be passed to the generic member through the method's parameters:
class Generic <T> {
private T [] array; // The array cannot be instantiated with new T []
public void setArray (T [] array) {
this.array = array;
}
public T [] getArray () {
return array;
}
}
test program:
public class test {
public static void main (String args []) {
String [] strs = {"red", "black", "green"};
Generic <String> f = new Generic <String> ();
// Pass the actual string array to the generic member array
f.setArray (strs);
// Read the value of the generic member array and assign it to the string array variable strs
strs = f.getArray ();
}
}
Available methods for generic members
Since the generic type can only be determined after the class is instantiated, the generic members of the class can only use the methods of the Object type:
class Generic <T> {
T f;
void setF (T f) {this.f = f;}
// ....
void doSome () {
// getClass and toString are methods in Object
System.out.println (f.getClass (). GetName ());
System.out.println (f.toString ());
}
}
test program:
public class javatest {
public static void main (String args []) {
String strs = "hello";
Generic <String> f = new Generic <String> ();
f.setF (strs);
f.doSome ();
}
}
Limit generic upper limit type
The extends keyword is used to specify the upper limit of a generic type. When instantiating a generic class, the actual type specified for the generic type must be a subclass of the specified class or a subinterface of the specified interface
import java.util.List;
public class ListGeneric <T extends List> {
private T list;
public void setList (T list) {
this.list = list;
}
public T getList () {
return list;
}
}
When defining a generic type, regardless of whether the interface or class is to be qualified, use the extends keyword
Test example:
ListGeneric <Vector> f1 = new ListGeneric <Vector> ();
ListGeneric <ArrayList> f2 = new ListGeneric <ArrayList> ();
If it is not of type List, an error will occur during compilation:
ListGeneric <HashMap> f3 = new ListGeneric <HashMap> ();
type parameter java.util.HashMap is not within its bound
ListGeneric <HashMap> f3 = new ListGeneric <HashMap> ();
The default generic restriction type
When defining a generic category, if you only write the following code:
class Generic <T> {
// ...
}
Equivalent to the following definition:
class Generic <T> extends Object {
// ...
}
The available methods for members after limiting the generic upper limit:
Once the upper limit of the generic type is limited, the generic members of the class can use the methods and other available members of the upper type:
class ListGeneric <T extends List> {
private T list;
public void setList (T list) {
this.list = list;
}
public void doSome () {
// ad and get methods are all methods defined in the List interface
list.add (new Integer (0));
System.out.println (list.get (0));
}
}
Object is the parent class of all classes, therefore, all types of instances can be assigned to variables declared as type Object
Boolean f1 = new Boolean (true);
Integer f2 = new Integer (1);
Object f = f1; // ok
f = f2; // ok
When instantiating a generic class, the generic type is specified as the Object type but there is no compatibility with other types:
Generic <Boolean> f1 = new Generic <Boolean> ();
Generic <Integer> f2 = new Generic <Integer> ();
Generic <Object> f = f1; // f1 and f types are not compatible, a compilation error occurs
f = f2; // f2 and f types are also incompatible, and compilation errors will also occur
Generic wildcard (Wildcard)
Incompatibilities between generic class instances can cause inconvenience in use. Using generic wildcards (?) To declare variables of a generic class can solve this problem
Generic <Boolean> f1 = new Generic <Boolean> ();
Generic <Integer> f2 = new Generic <Integer> ();
Generic <Object> f3 = new Generic <Object> ();
Generic <?> F;
f = f1; // ok
f = f2; // ok
f = f3; // ok
Wildcards can also be used for method parameter type declarations, indicating that the parameter can accept any instance of the corresponding generic type.
The printCollection method in the following class definition can print the contents of any strongly typed collection
class test {
// Collection <?> Can match any strongly typed collection
static void printCollection (Collection <?> c) {
for (Object o: c)
System.out.println (o);
}
}
Similar to the upper limit of limiting generics, you can also use the extends keyword to limit the upper limit of wildcard matching types:
Generic <? Extends List> f = null;
f = new Generic <ArrayList> (); // ok
// ...
f = new Generic <Vector> (); // ok
// ...
// The following statement will cause a compilation error because HashMap does not implement the List interface
f = new Generic <HashMap> ();
incompatible types
found: Generic <java.util.HashMap>
required: Generic <? extends java.util.List>
f = new Generic <HashMap> ();
Limit the lower limit of wildcard match types
You can also use the super keyword to limit wildcard matching types to a certain type and its parent type:
// Limit f to only represent the instantiation of the parent class using java.sql.Date
Generic <? Super java.sql.Date> f = null;
f = new Generic <java.sql.Date> (); // ok
// OK, java.util.Date is the parent class of java.sql.Date
f = new Generic <java.util.Date> ();
// Error because String is not a parent class of java.sql.Date
f = new Generic <String> ();
Generic method
Not only can classes declare generics, but methods in classes can also declare generics for their own use. This method is called a generic method. Its definition format is:
Access modifier <generic list> Return type Method name (parameter list) {
Implementation code
}
The generic list is a legal Java identifier separated by commas.
Generics declared in the generic list can be used for the method's return type declaration, parameter type declaration, and type declaration of local variables in method code. Other methods in the class cannot use the generic declared by the current method. Using the generic method can solve the problems caused by the above-mentioned generic wildcards
Generic method declaration example:
class cc {
/ *
The method fun declares a generic T, this method will all
The elements are copied into the corresponding strongly typed set c without causing compilation errors.
The generic declaration T here only acts on the declaration part and the implementation code part of the fun method.
* /
public static <T> void fun (T [] a, Collection <T> c) {
for (T o: a)
c.add (o); // No compilation error like wildcard
}
}
There is no difference between calling a generic method and calling a normal method, you only need to pass an actual parameter that contains a specific type:
Generic method call example:
// Call and test the generic method fun defined in cc
public class javatest {
public static void main (String args []) {
String [] sa = new String [100];
Collection <String> cs = new Vector <String> ();
Collection <Object> co = new Vector <Object> ();
cc.fun (sa, cs); // The generic T in fun now matches the type String
cc.fun (sa, co); // The generic T in fun matches the type Object at this time
}
}
Generic type
The declared generics in the generic method can also use the extends keyword to define the lower limit of its type:
class cc {
// The generic T in the aToC method must be a type that implements a serialized interface
Public static <T extends java.io.Serializable> void fun (T [] a, Collection <T> c) {
for (T o: a)
c.add (o);
}
}
Generics in inheritance
If you need to retain the parent generics during inheritance, you need to add the parent generics when you declare
class subGeneric <T1, T2, T3> extends Generic <T1, T2> {
private T3 f3;
public void setF3 (T3 f3) {
this.f3 = f3;
}
public T3 getF3 () {
return f3;
}
}
If you do not retain the generic declaration in the parent class, the inherited T1 and T2 automatically become the Object type. It is recommended that the generic declaration in the parent class should be retained in the child class
Specify the generic type of the parent class when inheriting
public class SubGeneric <T3> extends Generic <String, Object> {
private T3 f3;
public void setF3 (T3 f3) {
this.f3 = f3;
}
public T3 getF3 () {
return f3;
}
}
Generic interface
Interfaces can also contain generic declarations:
interface I <T1, T2> {
T1 getT1 ();
T2 getT2 ();
// ...
}
When implementing a generic interface, the class may not declare the generic type in the generic interface when it is defined. At this time, the generic type in the interface will automatically become the Object type:
class IC implements I {
public Object getT1 () {}
public Object getT2 () {}
// ...
}
Implementation of generic interface
class IC <T1, T2> implements I <T1, T2> {
public T1 getT1 () {}
public T2 getT2 () {}
// ...
}
I <String, Integer> i = new IC <String, Integer> ();
Specify a generic type when implementing a generic interface
When implementing a generic interface, you can also directly specify the actual type of the generic in the interface:
interface I <T1, T2> {
T1 getT1 ();
T2 getT2 ();
// ...
}
// When implementing interface I, directly specify the type of generic T1, T2
class IC implements I <String, Integer> {
// Since the T1 type in the specified interface I is String, the return type of getT1 must be String
public String getT1 () {}
// As the T2 type in the specified interface I is Integer, the return type of getT2 must be Integer
public Integer getT2 () {}
// ...
}
Generics and enumeration
Since enumeration types cannot be instantiated directly, the definition of enumeration cannot contain generic declarations, but the enumeration can contain the definition of generic methods.
public enum TrafficLight {
Red, Amber, Green;
private int duration;
public static <T> void avgDuration (Collection <T> carType) {
// ....
}
// ....
}