java–基础–11.1–泛型–基本使用
1、定义
是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。
2、泛型高级
2.1、通配符
?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E:向下限定,E及其子类
? super E:向上限定,E极其父类
2.2、通配符限制边界补充
一个类型变量或者通配符可以有多个限定类型,限定类型用与分割,限定类型可以有多个接口类型,至多一个类类型,且类类型要放在最左边,案例如下
? extend comparable & serializable
? extend comparable & serializable
? extend User
? extend User
2.3.1、案例
限定通配符的上边界
正确:Vector<? extends Number> x = new Vector<Integer>();
错误:Vector<? extends Number> x = new Vector<String>();
限定通配符的下边界
正确:Vector<? super Integer> x = new Vector<Number>();
错误:Vector<? super Integer> x = new Vector<Byte>();
2.3、?无限制通配符
2.3.1、?相当于 ? extend Object
注意 :
List<?> list2 = new ArrayList<String>();
// 只能增加null
list2.add(null);
2.3.2、list<?>和list区别
- List<?>:不管?是什么,list里元素是一样的。都是同一种类型
- list:没有限制,同一个list里,list(0)可以是Iteger,而list(1)可以是String,即其每个元素可以不一样。
3、泛型与反射API
4、泛型反射的经验法则
使用的的Java的泛型通常分为两种不同的情况:
- 声明一个可参数化的类/接口。
- 使用参数化的类。
当写一个类或接口时,可以指定它应该是可参数化的。就像java.util.List接口那样,可以参数化java.util.List来创建一个String列表而不是创建Object列表。
java.util.List在运行时会检查参数化的类型,但是没有办法知道参数化的是什么类型。这是因为在相同的应用程序中类型可以被参数化为所有的类型。但是,当你检查方法或字段所声明使用的参数化类型,你可以在运行时看到可参数化的类型被参数化为什么类型。总之,你不能在运行时看到类型本身被参数化为什么类型,但你可以在使用和参数化它的字段和方法中看到它。
5、泛型方法的返回值类型
如果你获取到一个java.lang.reflect.Method 对象,可以获取它的返回值类型信息。
下面是一个示例,一个类有一个有参数化返回值类型的方法:
public class MyClass {
protected List<String> list = null;
public List<String> getList() {
return this.list;
}
public void setList(List <String> list){
this.list = list;
}
public static void main(String[] args) throws Exception {
Method method = MyClass.class.getMethod("getList", null);
//返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。
Type returnType = method.getGenericReturnType();
//returnType 是不是表示参数化类型
if (returnType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) returnType;
//返回表示此类型实际类型参数的 Type 对象的数组。
Type[] typeArguments = type.getActualTypeArguments();
for (Type typeArgument : typeArguments) {
Class typeArgClass = (Class) typeArgument;
System.out.println("参数类型是" + typeArgClass);
}
}
}
}
输出:
参数类型是class java.lang.String
6、泛型方法的参数类型
通过Java的的反射可以在运行时访问参数类型的泛型类型
下面的示例中,类有一个使用参数化的列表作为参数的方法
public class MyClass {
protected List<String> list = null;
public List<String> getList() {
return this.list;
}
public void setList(List<String> list) {
this.list = list;
}
public static void main(String [] args)throws Exception {
Method method = MyClass.class.getMethod("setList",List.class);
//按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。
Type[] genericParameterTypes = method.getGenericParameterTypes();
for(Type genericParameterType : genericParameterTypes){
if(genericParameterType instanceof ParameterizedType){
ParameterizedType type =(ParameterizedType)genericParameterType;
//返回表示此类型实际类型参数的 Type 对象的数组。
Type[] typeArguments = type.getActualTypeArguments();
for(Type typeArgument:typeArguments){
Class typeArgClass =(Class)typeArgument;
System.out.println("参数类型是 "+ typeArgClass);
}
}
}
}
输出:
参数类型是 =class java.lang.String
7、泛型字段类型
可以访问公共字段的泛型类型字段即类的成员变量。
下面是一个例子,类有一个实例变量stringList。
public class MyClass {
public List<String> list = null;
public static void main(String [] args)throws Exception {
Field field = MyClass.class.getField("list");
//返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。
Type type = field.getGenericType();
if(type instanceof ParameterizedType){
ParameterizedType pType = (ParameterizedType) type;
//返回表示此类型实际类型参数的 Type 对象的数组。
Type[] typeArguments = pType.getActualTypeArguments();
for(Type typeArgument : typeArguments){
Class typeArgClass = (Class) typeArgument;
System.out.println("参数类型是" + typeArgClass);
}
}
}
}
结果:
参数类型是class java.lang.String
8、自定义泛型 案例
8.1、自定义泛型类,泛型方法
package cn;
/**
* 泛型类:把泛型定义在类上
*
* @author Administrator
*
*/
public class ObjectTest<T> {
private T object;
public T getObject() {
return object;
}
public void setObject(T object) {
this.object = object;
}
/**
* 自定义泛型方法
* @return
*/
public <E> E show(E e) {
return e;
}
}
8.2、自定义接口泛型
package cn;
/**
*
*自定义泛型接口
*/
public interface IObjectTest<T> {
public abstract void method(T t);
public abstract <E> E method2(E e);
}
8.3、自定义泛型接口实现
package cn;
/**
* 自定义泛型接口实现
*/
public class ObjectTestImpl<T> implements IObjectTest<T> {
@Override
public void method(T t) {
System.out.println(t);
}
@Override
public <E> E method2(E e) {
return e;
}
}
泛型测试1
package cn;
public class Test {
/**
*泛型高级(通配符)
* ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
* ? extends E:向下限定,E及其子类
* ? super E:向上限定,E极其父类
*/
public static void main(String[] args) {
//自定义泛型类测试
System.out.println("------自定义泛型类测试---------");
ObjectTest<String> objectString=new ObjectTest<String>();
objectString.setObject("自定义类型String");
System.out.println(objectString.getObject());
ObjectTest<Integer> objectInteger=new ObjectTest<Integer>();
objectInteger.setObject(12);
System.out.println(objectInteger.getObject());
//自定义泛型方法测试
System.out.println("-----自定义泛型方法测试-----");
System.out.println(objectInteger.show("String"));
System.out.println(objectInteger.show(12));
System.out.println("-----泛型接口测试-----");
IObjectTest<String> ObjectTestImpl=new ObjectTestImpl<String>();
System.out.println(ObjectTestImpl.method2("接口"));
System.out.println(ObjectTestImpl.method2(12));
ObjectTestImpl.method("只能String");
}
}
泛型测试2