失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java 泛型参数写法_参数化类型——Java泛型

java 泛型参数写法_参数化类型——Java泛型

时间:2020-01-29 16:30:55

相关推荐

java 泛型参数写法_参数化类型——Java泛型

参数化类型:数据的类型会影响程序的行为。

类型限定:程序支持的数据类型是有范围的。

Java里的泛型:GenericType

当我们写出下面这样的代码时,Parent是一个泛型类型,它的参数范围是从顶层类型Object向下到任意一个类型。Parent不是泛型,它是ParameterizedType,它支持的数据类型只有Integer。

package example;

import java.lang.reflect.ParameterizedType;

public class GenericAndParameterized {

static class Parent{}

static class Child extends Parent{}

public static void main(String[]args){

System.out.println(Parent.class.getName());

System.out.println(Parent.class.getTypeParameters()[0].getName());

System.out.println(Child.class.getGenericSuperclass().getTypeName());

System.out.println( Child.class.getGenericSuperclass().getClass().getTypeParameters().length);

System.out.println( Child.class.getGenericSuperclass() instanceof ParameterizedType);

}

}

输出:

example.GenericAndParameterized$Parent

T

example.GenericAndParameterized$Parent

0

true

Java的泛型擦除:下面这个例子解释了什么是泛型的编译期检查,什么是泛型擦除。理解了这些就能明白为什么泛型通配符为什么是这样的含义。这里遗留的一个问题是:Java中ParamterizedType类型在什么时候生成。

package example;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

public class GenericDescription {

static class Parent{}

static class Child extends Parent{}

static class Descriptor{

public void describe(T t){}

}

public static void main (String[]args){

Child child = new Child();

Parent parent = new Parent();

Descriptor descriptor = new Descriptor();

descriptor.describe(child);

// 编译检查不允许使用Parent类型

// descriptor.describe(parent);

try{

Method method = Descriptor.class.getMethod("describe", Object.class);

method.invoke(descriptor, parent);

System.out.println(" it's ok to describe parent type");

method.invoke(descriptor, new Object());

}catch (Exception e){

// e.printStackTrace();

String upperBoundTypeName = Descriptor.class.getTypeParameters()[0].getBounds()[0].getTypeName();

System.out.println(" it can describe an Object type " +

"because the type variable's upper bound is " + upperBoundTypeName);

}

System.out.println("所以,Java的泛型擦除是指 " +

"把 泛型从编译期间的支持特定参数类型 解放到 运行期间的支持定义域内的全部类型");

/**

* 变量a,b满足关系a<=b时,如果函数f(x)满足f(a)<=f(b),那么f(x)是协变的

* 变量a,b满足关系a<=b时,如果函数f(x)满足f(a)>=f(b),那么f(x)是逆变的

* 变量a,b满足关系a<=b时,如果函数f(x)既不满足f(a)<=f(b),又不满足f(a)>=f(b),那么f(x)是不变的

*/

Object[] objects;

Integer[] integers = new Integer[10];

objects = integers;

System.out.println("this means 数组是协变的");

List objectList = new ArrayList<>();

List integerList = new ArrayList();

// objectList = integerList;

System.out.println("we can't refer objectList to integerList because 列表是不变的");

System.out.println("Java泛型的编译期检查是针对特定类型的,这就可以解释下面的几种写法");

List data = new ArrayList();

data.add(new Child());

List extends Child> listWithUpperBounds = data;

List super Child> listWithLowerBounds = new ArrayList<>();

listWithLowerBounds.add(listWithUpperBounds.get(0));

System.out.println("we can't get an element from listWithLowerBounds " +

"because we can't refer to elements with a upper bounds type");

System.out.println("we can't put an element into listWithUpperBounds " +

"because we can't convert parent type to one of children types");

List> list = new ArrayList<>();

list.add(null);

listWithUpperBounds.add(null);

System.out.println("but we always can put an null into a generic list" +

"because any type's value can be null");

List rawList = new ArrayList();

rawList = integerList;

Object everyThing = new Object();

rawList.add(everyThing);

System.out.println("using raw type is unsafe " +

"because we have judge the meaning of codes subjectively " +

"and sometimes it's hard to know the intentions of coders " +

"and we lost protection from the compiler with inspections");

}

/**

* 自限定和参数协变

* java 已经支持 返回值协变

* java 的参数协变可以使用泛型来实现

* 更具体的类型,更丰富的操作

*/

/**

* 这个例子里,T是当前类型的子类,且T的父类是Direction

* @param

*/

abstract class Direction>{

abstract T get();

abstract void set(T t);

}

abstract class KeepDirection> extends Direction{

@Override

T get() {

return null;

}

@Override

void set(T t) {

}

}

class WithDirection extends KeepDirection {

@Override

WithDirection get() {

return super.get();

}

@Override

void set(WithDirection withDirection) {

super.set(withDirection);

}

}

class SameDirection extends Direction{

@Override

SameDirection get() {

return null;

}

@Override

void set(SameDirection sameDirection) {

}

}

}

输出:

it can describe an Object type because the type variable's upper bound is example.GenericDescription$Parent

所以,Java的泛型擦除是指 把 泛型从编译期间的支持特定参数类型 解放到 运行期间的支持定义域内的全部类型

this means 数组是协变的

we can't refer objectList to integerList because 列表是不变的

Java泛型的编译期检查是针对特定类型的,这就可以解释下面的几种写法

we can't get an element from listWithLowerBounds because we can't refer to elements with a upper bounds type

we can't put an element into listWithUpperBounds because we can't convert parent type to one of children types

but we always can put an null into a generic listbecause any type's value can be null

using raw type is unsafe because we have judge the meaning of codes subjectively and sometimes it's hard to know the intentions of coders and we lost protection from the compiler with inspections

标签:Java,Parent,System,println,参数,泛型,class,out

来源: /afraidToForget/p/10727014.html

如果觉得《java 泛型参数写法_参数化类型——Java泛型》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。