1、什么是java泛型?
java泛型:英文名稱是generics,泛型是jdk5引入的一個新特性,java泛型的本質就是引數化型別,就是所有的操作資料型別被指定為一個引數,對引數化型別進行操作的物體(例如類、介面或方法)稱為泛型物體,
2、java泛型類
泛型類:必須先宣告,再使用;宣告是通過
<T,E, ...>實作的;約定泛型可以使用單個大寫字母T、E、K、V等表示
import java.lang.reflect.Field;
public class GenericsSimpleExample {
public static void main(String[] args) {
A<String , Integer> a0 = new A<>();
a0.t= "testStr";
A<Integer , Integer> a1 = new A<>();
a1.t = 100;
// 泛型引數在使用時要參考資料型別,不能是基本資料型別,比如int等等
//A<Integer , int> a2 = new A<>();
// 泛型類如果不指定具體的引數型別,默認資料型別是object
Class<A> cls = A.class;
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName() + ":" + field.getType().getSimpleName());
}
// 泛型類在具體實作上可以看出不同資料型別,實踐上是相同的資料型別,可以通過hashcode進行驗證
System.out.println(a0.getClass().hashCode());
System.out.println(a1.getClass().hashCode());
}
static class A <T , E> {
public T t;
public void test0(T t) {
}
}
}
注意要點:
- 泛型類的引數型別不能是基本資料型別,要使用參考資料型別
- 泛型類在不指定具體資料型別時候,默認是使用object型別的
- 泛型類具體使用上可以使用不同的資料型別,實踐上是相同的資料型別
3、從泛型類派生子類
- 1、子類是泛型的情況,子類要和父類的泛型型別一致
class A<T> extends B<T>{}
- 2、子類不是泛型的情況,父類要明確泛型的資料型別
class A extends B<String>{}
4、泛型介面
泛型介面語法:
interface 介面名稱 <泛型標識,泛型標識, ...>{
泛型標識 方法名();
...
}
- 1、實作類也是泛型類,泛型型別要和介面一致
interface B <T,V> {}
class A<T,V> implements B<T,V>{}
- 2、實作類不是泛型類,介面要指定具體的型別
class B implements B<String,Integer>{}
5、泛型方法
泛型方法語法:
修飾符 <T,E,...> 回傳值型別 方法名 (形參串列){
方法體;
}
泛型方法特征:
- 只有宣告了
<T>的方法才是泛型方法,僅僅傳參使用了泛型的,不是泛型方法 - 和泛型類一樣,也可以使用K、V、T、E等等引數表示泛型
public class GenericsMethodExample {
public static void main(String[] args) {
A0 a0 = new A0();
a0.test0("hello");
A1<Integer> a1 = new A1<>();
a1.test("hi", "hello");
A1.test1("hello world");
}
static class A0 {
public <T, E> T test0(T t) {
System.out.println("t = " + t);
return null;
}
}
static class A1<K> {
/**
* 泛型方法的型別和泛型類一致時,以具體方法的為準
* @param k
* @param t
*/
public <T, K> T test(T t , K k) {
System.out.println("t = " + t);
System.out.println("k = " + k);
return null;
}
/**
* static方法要使用泛型,必須指定為泛型方法加上{@code <K>}
* @param k
*/
public static <K> void test1(K k) {
}
}
}
歸納:
- 泛型方法的型別和泛型類一致時,以具體方法的為準
- static方法要使用泛型,必須指定為泛型方法加上
6、泛型通配符
型別通配符一般是使用?代替具體的型別實參,所以型別通配符是型別實參,而不是型別形參
public class GenericsWildcardExample {
public static void main(String[] args) {
A<String> a0 = new A<>();
show(a0);
A<Integer> a1 = new A<>();
show(a1);
}
public static void show(A<?> a){
System.out.println(a.getClass());
}
static class A<T> {
}
}
7、型別通配符上限
語法:
類/介面 <? extends 實參型別>
要求改泛型型別只能是實參型別或者實參的子型別別
public class GenericsWildcardExample {
public static void main(String[] args) {
A<A1> a11 = new A<>();
A<A2> a12 = new A<>();
A<A3> a13 = new A<>();
// 只能使用A2及其子類
show0(a12);
show0(a13);
}
public static void show0(A<? extends A2> a) {}
static class A<T> {
}
static class A1{}
static class A2 extends A1{}
static class A3 extends A2{}
}
8、型別通配符下限
語法:
類/介面 <? super 實參型別>
要求改泛型型別只能是實參型別或者實參的父型別別
public class GenericsWildcardExample {
public static void main(String[] args) {
A<A1> a11 = new A<>();
A<A2> a12 = new A<>();
A<A3> a13 = new A<>();
// 只能使用A2及其父類
show1(a11);
show1(a12);
}
public static void show1(A<? super A2> a){}
static class A<T> {
}
static class A1{}
static class A2 extends A1{}
static class A3 extends A2{}
}
9、什么是泛型擦除?
泛型資訊只存在于代碼編譯階段,在進入JVM之前,與泛型有關的資訊會被擦除
掉,我們稱之為 型別擦除
9.1、無限制型別擦除

import java.lang.reflect.Field;
public class GenericsWipeExample {
public static void main(String[] args) {
Class<?> cls0 = A.class;
Field[] fields = cls0.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName() + ":" + field.getType().getSimpleName());
}
}
static class A <T>{
T t;
}
}
列印:
t:Object
9.2、有限制型別擦除

import java.lang.reflect.Field;
public class GenericsWipeExample {
public static void main(String[] args) {
Class<?> cls1 = A1.class;
Field[] fields1 = cls1.getDeclaredFields();
for (Field field : fields1) {
System.out.println(field.getName() + ":" + field.getType().getSimpleName());
}
}
static class A1<T extends Number> {
T t;
}
}
列印:
t:Number
9.3、方法型別擦除

import java.lang.reflect.Method;
public class GenericsWipeExample {
public static void main(String[] args) {
Class<?> cls2 = A2.class;
Method[] methods = cls2.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName() + ":" + method.getReturnType().getSimpleName());
}
}
static class A2<T extends Number> {
T t;
public <K extends Number> K test(K k) {
return null;
}
}
}
列印
test:Number
9.4、橋接方法

interface MyInter<T>{
T fun1();
}
class DD implements MyInter<String>{
@Override
public String fun1() {
return null;
}
}
import java.lang.reflect.Method;
public class GenericsWipeExample {
public static void main(String[] args) {
Class<?> cls3 = A3.class;
Method[] methodss = cls3.getDeclaredMethods();
for (Method method : methodss) {
System.out.println(method.getName() + ":" + method.getReturnType().getSimpleName());
}
}
interface MyInter<T>{
T test();
}
class A3 implements MyInter<String> {
@Override
public String test() {
return null;
}
}
}
列印:
test:String
test:Object
10、泛型和反射
Class<?> cls0 = A.class;
Field[] fields = cls0.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName() + ":" + field.getType().getSimpleName());
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/293353.html
標籤:java
上一篇:C#實作的打飛機游戲(課程設計)
