有人可以尽可能详细地解释以下类型之间的差异吗?
List List
让我更具体一点.我什么时候想用
// 1 public void CanYouGiveMeAnAnswer(List l) { } // 2 public void CanYouGiveMeAnAnswer(List
jjohn.. 102
正如其他帖子所指出的那样,您要问的是一个名为泛型的Java功能.在C++中,这称为模板.Java野兽的处理方式更加温和.
让我在功能上回答你的问题(如果这不是OO讨论的顽皮词).
在泛型之前,你有像Vector这样的旧混凝土类.
Vector V = new Vector();
向量包含您给它们的任何旧对象.
V.add("This is an element"); V.add(new Integer(2)); v.add(new Hashtable());
但是,他们通过将您提供的所有内容都转换为Object(所有Java类的根目录)来实现此目的.在您尝试检索存储在Vector中的值之前,这没关系.当你这样做时,你需要将值转换回原始类(如果你想用它做任何有意义的事情).
String s = (String) v.get(0); Integer i = (Integer) v.get(1); Hashtable h = (Hashtable) v.get(2);
铸造变得非常快.更重要的是,编译器向你抱怨未经检查的强制转换.有关这方面的生动示例,请使用Apache的XML-RPC库(无论如何都是版本2).最重要的问题是,Vector的使用者必须在编译时知道其值的确切类,才能正确转换.如果Vector的生产者和消费者彼此完全隔离,这可能是一个致命的问题.
输入泛型.泛型尝试创建强类型类来执行泛型操作.
ArrayListaList = new ArrayList (); aList.add("One"); String element = aList.get(0); // no cast needed System.out.println("Got one: " + element);
现在,如果你看看臭名昭着的四人组合设计模式书,你会注意到从他们的实现类中脱离变量有一些智慧.考虑合同而不是实施更好.所以,你可能会说,所有清单对象做同样的事情:add()
,get()
,size()
等.然而,也有列表的操作是可以选择服从以各种方式(如合同的许多实现ArrayList
).但是,这些对象处理的数据类型将作为运行时考虑因素留给您(泛型类的用户).把它们放在一起,你会经常看到以下代码行:
ListL = new ArrayList ();
您应该读作"L是一种处理String对象的List".当您开始处理Factory类时,处理合同而不是特定的实现是至关重要的.工厂在运行时生成各种类型的对象.
使用泛型很容易(大多数时候).但是,有一天你可能决定要实现泛型类.也许您已经想到了一个很棒的新List实现.定义该类时,可以将其
用作将由方法操作的对象类型的占位符.如果您感到困惑,请使用List的通用类,直到您感到舒服为止.然后,您可以更自信地深入了解实施.或者,您可以查看JRE附带的各种List类的源代码.开源很棒.
查看有关泛型的Oracle/Sun 文档.干杯.
正如其他帖子所指出的那样,您要问的是一个名为泛型的Java功能.在C++中,这称为模板.Java野兽的处理方式更加温和.
让我在功能上回答你的问题(如果这不是OO讨论的顽皮词).
在泛型之前,你有像Vector这样的旧混凝土类.
Vector V = new Vector();
向量包含您给它们的任何旧对象.
V.add("This is an element"); V.add(new Integer(2)); v.add(new Hashtable());
但是,他们通过将您提供的所有内容都转换为Object(所有Java类的根目录)来实现此目的.在您尝试检索存储在Vector中的值之前,这没关系.当你这样做时,你需要将值转换回原始类(如果你想用它做任何有意义的事情).
String s = (String) v.get(0); Integer i = (Integer) v.get(1); Hashtable h = (Hashtable) v.get(2);
铸造变得非常快.更重要的是,编译器向你抱怨未经检查的强制转换.有关这方面的生动示例,请使用Apache的XML-RPC库(无论如何都是版本2).最重要的问题是,Vector的使用者必须在编译时知道其值的确切类,才能正确转换.如果Vector的生产者和消费者彼此完全隔离,这可能是一个致命的问题.
输入泛型.泛型尝试创建强类型类来执行泛型操作.
ArrayListaList = new ArrayList (); aList.add("One"); String element = aList.get(0); // no cast needed System.out.println("Got one: " + element);
现在,如果你看看臭名昭着的四人组合设计模式书,你会注意到从他们的实现类中脱离变量有一些智慧.考虑合同而不是实施更好.所以,你可能会说,所有清单对象做同样的事情:add()
,get()
,size()
等.然而,也有列表的操作是可以选择服从以各种方式(如合同的许多实现ArrayList
).但是,这些对象处理的数据类型将作为运行时考虑因素留给您(泛型类的用户).把它们放在一起,你会经常看到以下代码行:
ListL = new ArrayList ();
您应该读作"L是一种处理String对象的List".当您开始处理Factory类时,处理合同而不是特定的实现是至关重要的.工厂在运行时生成各种类型的对象.
使用泛型很容易(大多数时候).但是,有一天你可能决定要实现泛型类.也许您已经想到了一个很棒的新List实现.定义该类时,可以将其
用作将由方法操作的对象类型的占位符.如果您感到困惑,请使用List的通用类,直到您感到舒服为止.然后,您可以更自信地深入了解实施.或者,您可以查看JRE附带的各种List类的源代码.开源很棒.
查看有关泛型的Oracle/Sun 文档.干杯.
用我自己的简单术语:
名单
将声明一个普通的集合,可以保存任何类型,并将始终返回Object.
列表<对象>
将创建一个可以容纳任何类型对象的列表,但只能分配另一个List
例如,这不起作用;
List
当然你可以添加任何东西,但只能拉对象.
List
最后
名单<?>
会让你指定任何类型,包括
List > l = new ArrayList(); List > l2 = new ArrayList();
这被称为收集未知以来的共同点未知的对象,你就能获取对象(巧合)
当它与子类化一起使用时,未知的重要性来自:
List extends Collection> l = new ArrayList(); // compiles List extends Collection> l = new ArrayList (); // doesn't, // because String is not part of *Collection* inheritance tree.
我希望使用Collection作为类型不会产生混淆,这是我想到的唯一一棵树.
这里的不同之处在于l是属于Collection层次结构的unknow 集合.
我将向您介绍优秀的Java Generics教程,以及Sun Microsystems提供的"高级"泛型教程.另一个很好的资源是Java Generics and Collections一书.
要在这里添加已经很好的答案:
方法参数:
List extends Foo>
如果您不打算更改列表,那么这是一个很好的选择,只关心列表中的所有内容都可以分配给'Foo'.这样,调用者可以传入List
List
如果您打算将Foo对象添加到方法的列表中,那么这是一个不错的选择.调用者可能无法传入List
List super Foo>
如果你打算将Foo对象添加到列表中,这是一个很好的选择,并且列表中的其他内容并不重要(例如,您可以获得包含与Foo无关的'Dog'的List
方法返回值
就像方法论证一样,但好处却逆转了.
List extends Foo>
保证返回List中的所有内容都有'Foo'类型.它可能是List
List
就像List <?扩展Foo>但也允许调用者添加到List.不常见.
List super Foo>
允许调用者将Foo对象添加到List中,但不保证将从list.get(0)返回的内容......它可以是从Foo到Object的任何内容.唯一的保证是这不会是"狗"列表或其他一些阻止list.add(foo)合法的选择.非常罕见的用例.
我希望有所帮助.祝好运!
PS.总结......两个问题......
你需要添加到列表?你关心列表中的内容吗?
是是 - 使用List
. 是否 - 使用清单<?超级富豪>.
不是 - 使用<?扩展Foo> ---最常见.
不能 - 使用<?>.