如何使用Java泛型方法

发布时间:2022-05-20 10:36:34 作者:zzz
来源:亿速云 阅读:340

这篇“如何使用Java泛型方法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何使用Java泛型方法”文章吧。

泛型方法

一般定义如下,即方法的前面加了个<T>

public class FTest {
	public <T> List<T> f(T t){...};
}

三种泛型参数推断方式:

1、直接在f()前面加确定泛型

fTest.<Integer>f(xxx)

2、通过输入参数确定, 下面这个推断为Integer

int number = 0;
fTest.f(number)

3、可通过 返回值 确定

List<Integer> list = fTest.f(xxx);

Q: 下面这段代码哪里有问题? 是toString()那里吗?

public class A<T> {
	public static void  test(T t){
  		System.out.println(t.toString());  
  }
}

A:test是static方法, 因此无法感知A<T>实例里的T
需要改成
public static <T> void test(T t)

toString()那里没问题,toString就是Object的方法。

泛型参数和类型消除

Q: 泛型参数T在运行时,会变成什么?
A: 统一变成Object且不包含任何类型信息。

Q: 泛型参数T可以可以使用instanceof做比较吗?

class A<T> {
   void f(Object arg)
   if(arg instanceof T) {
	  ...
   }
}

A: 不能,编译器会报错。

Q: 泛型参数T可以进行new T()或者new T[]操作吗?
A: 不能,编译器会报错。

如何使用Java泛型方法

Q: 能调用泛型参数对象里的方法吗?

T.f();

A: 只能调用Object的方法。

Q: 可以用T做强制转化吗?

T t = (T)object;

A: 能运行, 但不会真正发生转型, 编译时会触发waring警告。

新建泛型对象时的问题

先假定有2个类, 基类Parent 和子类Child

class Parent{}
class Child extends Parent{}

回答以下问题:
Q:下面这句话有问题吗?

List<Parent> list = new ArrayList<Child>()

A:有问题,编译就错误了。 List<Parent>和ArrayList<Child>并不存在父子类的关系

Q:

List<? extends Parent> list = new ArrayList<Child>();

这个list有什么特点?

A:这个list可以调用A a = list.get(), 但是不能list.add(new Parent())

Q:

List<? super Child> list = new ArrayList<Parent>();

这个list有什么特点?
下面谁会报错

list.add(new Child())
list.add(new Parent())
Parent a= list.get();
Child b = list.get()

A:截图如下:

如何使用Java泛型方法

Q:

List<?> list = new ArrayList<A>();

这个list有什么特点?

A:get和add都不行,只能做remove等无返回值无输入A的操作。
PS: 注意,不是说不能调用get或add方法, 而是调用get或add时,不能使用A这个对象去操作。
即无法做add(A) 或者 A a = get(0)
但是可以做add(object) 或者Object o = get(0)
因为?可以转为Object, 但是无法转为A。

Q:下面这个代码会报错吗?

   List<Fruit> fruitList = new ArrayList<>();
   fruitList.add(new Fruit());
   List<Apple> appleList = new ArrayList<>();
   appleList.add(new Apple());
   fruitList.addAll(appleList);
   System.out.println(fruitList);

A:不会报错。会正常打印结果。

如何使用Java泛型方法

PECS原则
注意PECS原则和上面的区别!
上面之前提到的? extend或者? supert, 都是在声明对象的时候用的。
而PECS原则是用于泛型对象的方法输入参数!

假设有一个类定义如下:

public static class MyList<T> {
    List<T> list = new ArrayList<>();

    // 把输入参数塞给自己,类似于生产操作
    public void pushList(List<T> t) {
        list.addAll(t);
    }

    // 把自己的内容塞给输入参数,类似于让输入参数做消费。
    public void pollList(List<T> t) {
         t.addAll(list);
    }
}

则T就是泛型参数。

Q:下面代码能正常运行吗?

MyList<Number> myList = new MyList<>();

List<Integer> intList = new ArrayList<>();
myList.pushList(intList);

List<Object> objectList = new ArrayList<>();
myList.pollList(objectList);

A:不能正常运行, pushList和pollList都会报错

因为编译器检查后,认为 List<Integer>和List<Number>不是一个东西!

Q: 如果上文要支持pushList,应该怎么修改pushList方法的定义?
A:改成这样:

// 把输入参数塞给自己,类似于生产操作
public void pushList(List<? extends T> t) {
    list.addAll(t);
}

即编译器认为,List<Integer> 和List<? extend Number>是一个东西,允许!

Q: 如果要支持pollList,怎么修改定义?
A:

// 把自己的内容塞给输入参数,类似于让输入参数做消费。
public void pollList(List<? super T> t) {
    t.addAll(list);
}

因为是把自己的东西塞给输入参数, 而想要能塞进去,必须保证自己这个T,是输入参数的子类,反过来说,输入参数必须是T的父类,所以用super
于是编译器认为,List<Object> 和List<? super Number>是一个东西,允许!

PECS原则出自Effective Java, 注意只是一个编程建议而已!

以上就是关于“如何使用Java泛型方法”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

推荐阅读:
  1. Java 泛型示例 - 泛型方法,类,接口
  2. Java定义泛型方法实例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:java webstart问题怎么解决

下一篇:java中如何用一个for循环实现输出99乘法表

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》