如果在Java中创建泛型类(该类具有泛型类型参数),您可以使用泛型方法(该方法采用泛型类型参数)吗?
请考虑以下示例:
public class MyClass {
public <K> K doSomething(K k){
return k;
}
}
public class MyGenericClass<T> {
public <K> K doSomething(K k){
return k;
}
public <K> List<K> makeSingletonList(K k){
return Collections.singletonList(k);
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所期望的泛型方法,我可以调用任何对象的doSomething(K)实例MyClass:
MyClass clazz = new MyClass();
String string = clazz.doSomething("String");
Integer integer = clazz.doSomething(1);
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用MyGenericClass 没有指定泛型类型的实例,我调用doSomething(K)返回一个Object,无论K传入什么:
MyGenericClass untyped = new MyGenericClass();
// this doesn't compile - "Incompatible types. Required: String, Found: Object" …Run Code Online (Sandbox Code Playgroud) 我遇到了一些非常基本但今天非常困惑的事情.我需要将列表转换为数组.该列表包含String实例.完美的使用示例List.toArray(T[]),因为我想要一个String[]实例.但是,如果没有明确地将结果转换为,它将无法工作String[].
作为测试场景,我使用了以下代码:
import java.util.Arrays;
import java.util.List;
public class MainClass {
public static void main(String args[]) {
List l = Arrays.asList("a", "b", "c");
String stuff[] = l.toArray(new String[0]);
System.err.println(Arrays.asList(stuff));
}
}
Run Code Online (Sandbox Code Playgroud)
哪个不编译.它几乎是javadoc中示例的精确副本,但编译器说如下:
MainClass.java:7: incompatible types
found : java.lang.Object[]
required: java.lang.String[]
String stuff[] = l.toArray(new String[0]);
^
Run Code Online (Sandbox Code Playgroud)
如果我添加一个强制转换String[]它将编译并运行完美.但是当我查看toArray方法的签名时,这不是我所期望的:
<T> T[] toArray(T[] a)
Run Code Online (Sandbox Code Playgroud)
这告诉我,我不应该投.到底是怎么回事?
编辑:
奇怪的是,如果我将列表声明更改为:
List<?> l = Arrays.asList("a", "b", "c");
Run Code Online (Sandbox Code Playgroud)
它也有效.或者List<Object>.所以它不一定List<String>是建议的.我开始认为使用原始List类型也会改变该类中泛型方法的工作方式.
第二次编辑:
我想我现在明白了.Tom …
如果我有课:
public class GenericClass<TBlah extends Number> {
public List<String> getList() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试从另一个类使用该方法时:
public class OtherClass {
public void test() {
GenericClass a = null;
for (String s : a.getList()) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么a.getList()返回a List<Object>直到我将for循环上面的行更改为:
GenericClass<Number> a = null;
Run Code Online (Sandbox Code Playgroud)
那时a.getList()返回一个List<String>它应该做的事情?
编辑:我不明白为什么指定的合同getList()应该受到如何声明我的变量'a'的影响.getList()永远都会回归List<String>,而TBlah是什么并不重要.
我想创建一个不同类实例的arraylist.如何在不定义类类型的情况下创建列表?(<Employee>)
List<Employee> employees = new ArrayList<Employee>();
employees.add(new Employee());
Employee employee = employees.get(0);
Run Code Online (Sandbox Code Playgroud) 我无法理解为什么java编译器允许为非特定集合分配已指定变量的集合.像这样:
ArrayList list = new ArrayList();
// Operations on list
ArrayList<String> stringList = list;
Run Code Online (Sandbox Code Playgroud)
在这种情况下可能存在各种类型的转换错误,在我看来,如果编译器阻止你首先执行此操作会更有意义.
我只是问,因为我很好奇这个语言的这个有点奇怪的方面,我实际上并没有让代码工作有困难(虽然我可能有一天我需要使用一个包含各种类的ArrayList它).
今天我遇到了javac关于泛型类型推理的奇怪行为.这是用于说明这种奇怪行为的示例类:
import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
public class Test {
protected <T> T strange(T t, Map<String, String> map) {
return t;
}
protected void ok(Map<String, String> map) {}
protected <T> T test(T t) {
T res = strange(t , new HashMap<String, String>());
//Doesn't work
//res = strange(t, new <String, String>HashMap());
ok(new <String, String>HashMap());
res = strange(t, Collections.<String, String>emptyMap());
//Doesn't work
//res = strange(t, Collections.EMPTY_MAP);
res = strange(t, (Map<String, String>) Collections.EMPTY_MAP);
ok(Collections.EMPTY_MAP);
return res;
}
}
Run Code Online (Sandbox Code Playgroud)
注意//Doesn't …
我无法理解为什么我的界面参数化不起作用.我们来看下面的代码:
public interface IType {
public List<String> getAllItems();
}
......
public void function(IType item) {
for (String str : item.getAllItems()) { //DOESN'T WORK! Incompoatible types. Required String, Found: Object
}
}
Run Code Online (Sandbox Code Playgroud)
为什么它会返回List<Object>而不是List<String>?