这个范型调用为什么不对?

theoffspring 2009-10-10 10:29:48
 public  void takeList(List<? extends String> list){
list.add("foo");
}



...全文
178 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
theoffspring 2009-10-14
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 thc1987 的回复:]
LZ请看下面的:
Java codeCollection<?> c=new ArrayList<Integer>();
c.add(new Integer(1));// 编译错误
因为这个“?”代表的是未知类型,不能将任何类型的对象添加到其中,但是可以从未知类型的集合中取出元素:
Java codeList<Integer> l=new ArrayList<Integer>();
l.add(new Integer(1));
List<?> l2= l;
Object o= l2.get(0);
System.out.println(o);
使用“?”时,也可以限定条件:
Java codestaticvoid f(Collection<?extends Number> c) {for (Number number : c) {
System.out.println(number);
}
}
这时f方法只能接受元素类型是Number或其子类的属于Collection的泛型集合参数

查看Collections.copy(dest, src);方法时会发现:
Java codepublicstatic<T>void copy(List<?super T> dest, List<?extends T> src){}
这里的"? super T"表示的是这个未知类型“?”必须是T或者它的父类

在泛型中有个比较重要的一点:
如果A是B的子类,T是一个泛型类(或接口),那么G <A>并不是G <B>的子类型

希望这些能对你有用
[/Quote]
谢谢,有用,是否能讲讲? super String的时候,为什么List.add("foo")没问题,这个时候类型也是未知的呀。
猿敲月下码 2009-10-14
  • 打赏
  • 举报
回复
LZ请看下面的:
Collection<?> c = new ArrayList<Integer>();
c.add(new Integer(1)); // 编译错误

因为这个“?”代表的是未知类型,不能将任何类型的对象添加到其中,但是可以从未知类型的集合中取出元素:
List<Integer> l = new ArrayList<Integer>();
l.add(new Integer(1));
List<?> l2 = l;
Object o = l2.get(0);
System.out.println(o);

使用“?”时,也可以限定条件:
	static void f(Collection<? extends Number> c) {
for (Number number : c) {
System.out.println(number);
}
}

这时f方法只能接受元素类型是Number或其子类的属于Collection的泛型集合参数

查看Collections.copy(dest, src);方法时会发现:
public static <T> void copy(List<? super T> dest, List<? extends T> src){}

这里的"? super T"表示的是这个未知类型“?”必须是T或者它的父类

在泛型中有个比较重要的一点:
如果A是B的子类,T是一个泛型类(或接口),那么G<A>并不是G<B>的子类型

希望这些能对你有用
portnet 2009-10-14
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 theoffspring 的回复:]
引用 19 楼 portnet 的回复:
引用楼主 theoffspring 的回复:
Java codepublicvoid takeList(List <?extends String> list){
        list.add("foo");
    }


这个写法是不是可以改成
public  <T extends String> void takeList(List <T> list){
  list.add("foo");
}
这里同样出错,但是这样看起来更明显一些。list.add(T);才是正确的。“foo”是String,但是不代表只有这一种String.虽然String是final的。但是去掉这个特殊性,这种用法很显然是不对的。不能用parent的对象代替child对象。

那么,为什么? super String的时候,就对了?
[/Quote]
super和extends是取值相反的两个关键字,可以用child代表parent. String就是这个集合中的child.
24K純帥 2009-10-13
  • 打赏
  • 举报
回复
up..第一次见到这么写的
theoffspring 2009-10-13
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 portnet 的回复:]
引用楼主 theoffspring 的回复:
Java codepublicvoid takeList(List <?extends String> list){
        list.add("foo");
    }



这个写法是不是可以改成
public <T extends String> void takeList(List <T> list){
  list.add("foo");
}
这里同样出错,但是这样看起来更明显一些。list.add(T);才是正确的。“foo”是String,但是不代表只有这一种String.虽然String是final的。但是去掉这个特殊性,这种用法很显然是不对的。不能用parent的对象代替child对象。
[/Quote]
那么,为什么? super String的时候,就对了?
wfd1314 2009-10-12
  • 打赏
  • 举报
回复
学习了...
theoffspring 2009-10-12
  • 打赏
  • 举报
回复
那LS能不能解释一篇讲? extends 和?super的文章看看,我看到的例子都是用来取某些东西,而不会对参数进行一些修改,如list.add这种操作。不是很明白。
portnet 2009-10-12
  • 打赏
  • 举报
回复
[Quote=引用楼主 theoffspring 的回复:]
Java codepublicvoid takeList(List<?extends String> list){
list.add("foo");
}



[/Quote]
这个写法是不是可以改成
public <T extends String> void takeList(List<T> list){
list.add("foo");
}
这里同样出错,但是这样看起来更明显一些。list.add(T);才是正确的。“foo”是String,但是不代表只有这一种String.虽然String是final的。但是去掉这个特殊性,这种用法很显然是不对的。不能用parent的对象代替child对象。
theoffspring 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 viszl 的回复:]
Java codepublicvoid takeList(List<?extends String> list){
list.add("foo");
}
list是一个带上线通配符泛型参数的List,然后调用add,add的参数就是“? extends String”,编译器并不能理解这个时候需要那个String的子类型,因此就不会接受任何类型的参数,所以报错。
[/Quote]
改成Object为什么也不行,字符串难道不是Object的子类?

 public  void takeList(List<? extends Object> list){
list.add("foo");
}
djjlove_2008 2009-10-11
  • 打赏
  • 举报
回复
哎,看你们在JAVA中有如此造诣了,我太惭愧,路过,呵呵。。。
Spring源码解析 2009-10-11
  • 打赏
  • 举报
回复
学习了,泛型还可以这样写啊,顶
lz12366 2009-10-11
  • 打赏
  • 举报
回复
这个地方是比较模糊!!!
blliy117 2009-10-11
  • 打赏
  • 举报
回复
这样写还不如这样写
list<String>
反正list<? extends String>也是string

不过String是final的哦
loveofmylife 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 theoffspring 的回复:]
改成Object为什么也不行,字符串难道不是Object的子类?

Java codepublicvoid takeList(List<?extends Object> list){
list.add("foo");
}
[/Quote]
改成什么都不行,上限通配符“? extends Object”只是限定它是一种Object的子类型,至于那种类型,编译器是不知道的,所以不能在形参列表中带有泛型参数的方法中使用那个“?”类型,编译器没那么聪明,他不认识这个“?”
loveofmylife 2009-10-11
  • 打赏
  • 举报
回复
public static void printBuddies(Pair<? extends Employee> p)//请看这里。
{
Employee first = p.getFirst();
Employee second = p.getSecond();
System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
}

p调用的方法public T getSecond() { return second; }的形参列表中不含泛型参数吧
public static void maxminBonus(Manager[] a, Pair<? super Manager> result)
{
minmaxBonus(a, result);
PairAlg.swapHelper(result); // OK--swapHelper captures wildcard type
}

这个事下限通配符,super的,它调用的方法的返回值不含泛型参数吧

综上所述,完全和我说的一样啊

theoffspring 2009-10-11
  • 打赏
  • 举报
回复
/**
* @version 1.00 2004-05-10
* @author Cay Horstmann
*/
public class Pair<T>
{
public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; }

public T getFirst() { return first; }
public T getSecond() { return second; }

public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }

private T first;
private T second;
}
theoffspring 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 viszl 的回复:]
引用 8 楼 theoffspring 的回复:
改成Object为什么也不行,字符串难道不是Object的子类?

Java codepublicvoid takeList(List <?extends Object> list){
        list.add("foo");
    }

改成什么都不行,上限通配符“? extends Object”只是限定它是一种Object的子类型,至于那种类型,编译器是不知道的,所以不能在形参列表中带有泛型参数的方法中使用那个“?”类型,编译器没那么聪明,他不认识这个“?”
[/Quote]
对啊,String是Object的子类型啊。按照书上的讲法是应该可以的,? super String就可以证明。《core java》有个例子,如下:
import java.util.*;

/**
* @version 1.00 2004-05-10
* @author Cay Horstmann
*/
public class PairTest3
{
public static void main(String[] args)
{
Manager ceo = new Manager("Gus Greedy", 800000, 2003, 12, 15);
Manager cfo = new Manager("Sid Sneaky", 600000, 2003, 12, 15);
Pair<Manager> buddies = new Pair<Manager>(ceo, cfo);
printBuddies(buddies);

ceo.setBonus(1000000);
cfo.setBonus(500000);
Manager[] managers = { ceo, cfo };

Pair<Employee> result = new Pair<Employee>();
minmaxBonus(managers, result);
System.out.println("first: " + result.getFirst().getName()
+ ", second: " + result.getSecond().getName());
maxminBonus(managers, result);
System.out.println("first: " + result.getFirst().getName()
+ ", second: " + result.getSecond().getName());
}

public static void printBuddies(Pair<? extends Employee> p)//请看这里。
{
Employee first = p.getFirst();
Employee second = p.getSecond();
System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
}

public static void minmaxBonus(Manager[] a, Pair<? super Manager> result)
{
if (a == null || a.length == 0) return;
Manager min = a[0];
Manager max = a[0];
for (int i = 1; i < a.length; i++)
{
if (min.getBonus() > a[i].getBonus()) min = a[i];
if (max.getBonus() < a[i].getBonus()) max = a[i];
}
result.setFirst(min);
result.setSecond(max);
}

public static void maxminBonus(Manager[] a, Pair<? super Manager> result)
{
minmaxBonus(a, result);
PairAlg.swapHelper(result); // OK--swapHelper captures wildcard type
}
}

class PairAlg
{
public static boolean hasNulls(Pair<?> p)
{
return p.getFirst() == null || p.getSecond() == null;
}

public static void swap(Pair<?> p) { swapHelper(p); }

public static <T> void swapHelper(Pair<T> p)
{
T t = p.getFirst();
p.setFirst(p.getSecond());
p.setSecond(t);
}
}

class Employee
{
public Employee(String n, double s, int year, int month, int day)
{
name = n;
salary = s;
GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
hireDay = calendar.getTime();
}

public String getName()
{
return name;
}

public double getSalary()
{
return salary;
}

public Date getHireDay()
{
return hireDay;
}

public void raiseSalary(double byPercent)
{
double raise = salary * byPercent / 100;
salary += raise;
}

private String name;
private double salary;
private Date hireDay;
}

class Manager extends Employee
{
/**
@param n the employee's name
@param s the salary
@param year the hire year
@param month the hire month
@param day the hire day
*/
public Manager(String n, double s, int year, int month, int day)
{
super(n, s, year, month, day);
bonus = 0;
}

public double getSalary()
{
double baseSalary = super.getSalary();
return baseSalary + bonus;
}

public void setBonus(double b)
{
bonus = b;
}

public double getBonus()
{
return bonus;
}

private double bonus;
}

快乐的2 2009-10-10
  • 打赏
  • 举报
回复
String是final类型,怎么会被继承呢???
Y569778402 2009-10-10
  • 打赏
  • 举报
回复
学习了
chpublish1012 2009-10-10
  • 打赏
  • 举报
回复
?extends XX 是上限是XX
就是说?是XX的子类
加载更多回复(4)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧