Java基础知识之泛型简单介绍
Posted smileNicky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础知识之泛型简单介绍相关的知识,希望对你有一定的参考价值。
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());
}
以上是关于Java基础知识之泛型简单介绍的主要内容,如果未能解决你的问题,请参考以下文章