Summary
According to "Java core technology Volume" summed up from eighth chapter of the book, in the part of the article excerpt the book, as personal notes.
Article not too deep, hope readers will be good reference.
Why use generic programming
Generic programming (Generic programming) code written means can be reused by many different types of objects.
Benefits type of the parameter
In the absence of a generic class, ArrayList class only to maintain an array of Object references:
public class ArrayList {
private Object[] elementData; // 用于存放数据
public Object get(int i) { . . . }
public void add(Object o) { . . . }
...
}
problem
Must be cast Gets a value 1.
2. there is no error checking. You can add the list to an array of objects of any type, if inconsistent with the type of the array, will get the results of mandatory mandatory, an error.
Generics provide a better solution: type parameter:
ArrayList<String> array = new ArrayList<String>():
Information on the use of type parameters, we can maintain the type of unity when adding data, call the get method does not need time to be cast, because when we initialized it defines the type, the compiler will identify the type of the return value help us convert the type.
Defining a simple generic class
public class Pair<T> {
private T num;
public Pair(T num) { this.num = num; }
public T getNum() { return num; }
public void setNum(T num) { this.num = num; }
}
We can see that in the back of the class name added a Pair
public class Pair<T,U> {
...
}
If we instantiate Pair class, for example:
new Pair<String>;
Then we can think of the above-mentioned Pair class as follows:
public class Pair<String> {
private String num;
public Pair(String num) { this.num = num; }
public String getNum() { return num; }
public void setNum(String num) { this.num = num; }
}
Is not it simple? In Java libraries, using the variable E represents the set of element types, K and V respectively represent the type keywords and values table, T, U, S represents any type.
Generic method
The method is defined with a parameter of type
public static <T> T getMiddle(T... a) {
return a[a.length / 2];
}
You can see the type of a variable (<T>) on the back modifier (public static), the return type (T) above. Generic methods can be defined in a generic class or an ordinary class.
Defining a type of the variable
If we need to be constraints on the type of variables such as: passing variables must implement the Comparable interface, because the variable method calls the compareTo needs. So that we can use extends
the keyword to define variables.
public <T extends Comparable> T max(T a) {
a.compareTo(...);
...
}
Whether defined variables need to inherit a class or implements an interface, you are using extends
the keyword limit.
Generic code and virtual machine
Type erasure
Whether we have a generic class, generic method how defined in the code, it provides a corresponding primitive type. Deleting the original type name is the name of the generic class type parameters. The <T>
original type of Object
, <T extends MyClass>
the original type MyClass
.
Code like this:
public class Pair<T> {
private T property;
public Pair(T property) {
this.property = property;
}
}
After type erasure:
public class Pair<Object> {
private Object property;
public Pair(Object property) {
this.property = property;
}
}
Translation generic expression
If you erase the return type, the compiler inserts casts, such as the following:
Pair<Employee> buddies = . .
Employee buddy = buddies.getFirst();
Erase getFirst return after return type of type Object, but the compiler will automatically help us cast to Employee.
So: the compiler to perform operations of this method is divided into two instructions:
Pair.getFirst call to the original method of
the Object return type cast to type Employee
Section Summary:
No generic virtual machine, only the classes and methods common
to all types of the parameters are replaced with their type is defined
as a holding type safety, if necessary insert cast
bridge held synthesis methods are polymorphic (not mentioned herein, but the bridge method can be ignored, Java will have to write non-standard method bridge generation)
Restrictions and Limitations
Examples of the basic types can not use the type of parameter
Eight basic data types can not be used to instantiate a type parameter, you have not seen ArrayList<int>
such a code it. Only ArrayList<Integer>
. The reason is because the basic data type is not Object. So they can only be replaced with a type of packaging.
Run-time type query applies only to the original type
All types of queries produced only primitive type, because no such thing as a generic type in a virtual machine.
E.g:
Pair<String> pair = new Pair<String>("johnson");
if (pair instanceof Pair<String>) {} // Error
if (pair instanceof Pair<T>) {} // Error
if (pair instanceof Pair) {} // Pass
You can not create arrays of parameterized types
Pair<String>[] pairs = new Pair<String>[10]; //error
Why can not this definition? Because pairs
of the type Pair[]
, it can be converted Object[]
, if you try to store other types of elements, an exception will be thrown ArrayStoreException,
pairs[0] = 10L; //抛异常
In a word, not strict. You can not create a parameterized type of array.
Type variable can not instantiate
You can not use new T (...), new T [...] or T.class. Because the type erasure, T will become Object, and we are certainly not want to instantiate Object.
But after Java8, we can use the Supplier<T>
interface, which is a functional interface that represents a parameter and there is no return type of the function T:
public class Pair<T> {
private T first;
private T second;
private Pair(T first, T second) {
this.first = first;
this.second = second;
}
public static <T> Pair<T> makePair(Supplier<T> constr) {
return new Pair<>(constr.get(), constr.get());
}
public static void main(String[] args) {
Pair<String> pair = Pair.makePair(String::new);
}
}
The generic class type variable static context is invalid
You can not reference type variable domain or in a static method. E.g:
public class Pair<T> {
private static T instance; //Error
public static T getInstance() { //Error
if (instance == null)
instance = new Pair<T>();
return instance;
}
}
Because the class type variable (<T>)
is the effective scope of the object, instead of a valid class in scope. If you are using a generic method, the article may refer to the above generic methods oh ~
Not throw or capture instance of a generic class
That can not throw objects can not capture a generic class, even extend Throwable is illegal:
public class Pair<String> extend Exceotion {} //Error
public static <T extends Throwable> void doWork(Class<T> t) {
try {
...
} catch (T e) { //Error
...
}
}
But after throwing an exception to an exception to allow the use of variable types (personal feeling never seen such a code).
public static <T extends Throwable> void doWork(Class<T> t) throw T { //Pass
try {
...
} catch (Exception e) {
throw e;
}
}
Generic type of inheritance rules
Such as Manager
class inheritance Employee
class. But Pair<Employee>
and Pair<Manager>
is not associated. Like the following code, will prompt an error, delivery failures:
Pair<Manager> managerPair = new Pair<Manager>();
Pair<Employee> employeePair = managerPair; //Error
Wildcard type
Wildcard concept
Wildcard type, allowing the change type parameter, using ?
identification wildcard type:
Pair<? extends Employee>
If the class is as follows Pair
public class Pair<T> {
private T object;
public void setObject(T object) {
this.object = object;
}
}
Then you can use wildcards to resolve generic types of rules of succession issues, such as:
Pair<Manager> managerPair = new Pair<Manager>();
Pair<? extends Employee> employeePair = managerPair; //Pass
Manager manager = new Manager();
employeePair.setObject(manager); //Error
Use <? Extends Employee>, the compiler only knows employeePair is a subclass of Employee, but it is unclear what specific sub-categories, so the final step employeePair.setObject(manager)
can not be executed.
Wildcard defining supertype
Wildcard has an additional capability, you may be designated a super-defined type , such as:
public class Pair<T> [
...
public static void salary(Pair<? super Manager> result) {
//...
}
}
<? super Manager>
The wildcard for all types of ultra Manager (including Manger), for example:
Pair<Manager> managerPair = new Pair<Manager>();
Pair<Employee> employeePair = new Pair<Employee>();
Pair.salary(managerPair); //Pass
Pair.salary(employeePair); //Pass
// 假如 ManagerChild为Manager子类
Pair<ManagerChild> managerChildPair = new Pair<ManagerChild>();
Pair.salary(managerChildPair); //Error
Indefinite wildcard
Indefinite wildcards, such as: Pair<?>
when we do not need to care about his actual type when you can use a wildcard indefinite, on the code:
public static boolean hasNull(Pair<?> pair) {
return pair.getObject() == null;
}
To be honest, it made me dizzy wildcards, see the article over and over again, slowly began to understand that I was too hard. . .
Article here came to an end, do not know you did not read the small partner, did not understand the words may be my article writing skills and the ability to be improved, small partners can also take a look "Java core technology Volume" This book it, the feeling is very good. Recently picked up this book point of view is also found that the foundation is very important, first precipitated good foundation, and then learning other technical points will be easier to start with, will know these know the course. Recently very much like a word, he gave us: "oaks from little acorns, not in quicksand high-profile building."
Personal blog URL: https://colablog.cn/
If my articles help to you, I can focus on the public micro-channel number, the first time to share your article