Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
泛型类中的Java泛型方法_Java_Generics_Language Design_Generic Method_Raw Types - Fatal编程技术网

泛型类中的Java泛型方法

泛型类中的Java泛型方法,java,generics,language-design,generic-method,raw-types,Java,Generics,Language Design,Generic Method,Raw Types,如果在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 <

如果在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);
  }
}
但是,如果我尝试使用
MyGenericClass
的实例而不指定泛型类型, 我调用
doSomething(K)
返回一个
对象
,无论传入了什么
K

MyGenericClass untyped = new MyGenericClass();
// this doesn't compile - "Incompatible types. Required: String, Found: Object"
String string = untyped.doSomething("String");
奇怪的是,如果返回类型是一个泛型类,它将编译-例如
List
(实际上,这可以解释-请参阅下面的答案):

MyGenericClass untyped=新建MyGenericClass();
List List=untyped.makeSingletonList(“字符串”);//这就编译了
此外,如果键入泛型类,即使仅使用通配符,它也会编译:

MyGenericClass<?> wildcard = new MyGenericClass();
String string = wildcard.doSomething("String"); // this compiles
MyGenericClass通配符=新的MyGenericClass();
字符串字符串=通配符。doSomething(“字符串”);//这就编译了
  • 在非类型化泛型类中调用泛型方法不起作用有什么好的理由吗

  • 是否有一些关于泛型类和泛型方法的巧妙技巧是我所缺少的

编辑:

为了澄清,我希望非类型化或原始类型的泛型类不遵守泛型类的类型参数(因为它们尚未提供)。然而,我不清楚为什么非类型化或原始类型的泛型类意味着不尊重泛型方法

据了解,这一问题已在SO,c.f.上提出。这个问题的答案解释了当一个类是非类型化/原始形式时,所有泛型都会从类中移除,包括泛型方法的类型

然而,对于为什么会出现这种情况,并没有真正的解释。请允许我澄清我的问题:

  • 为什么Java要删除非类型或原始类型泛型类上的泛型方法类型?这是一个很好的理由,还是只是一个疏忽
编辑-JLS讨论:

有人建议(在回答前一个SO问题和本问题时)在中处理这一问题,其中指出:

未从其超类或超接口继承的原始类型C的构造函数(§8.8)、实例方法(§8.4,§9.4)或非静态字段(§8.3)M的类型是对应于在对应于C的泛型声明中删除其类型的原始类型

我很清楚这与非类型化类的关系——类泛型类型替换为擦除类型。如果类泛型被绑定,则擦除类型对应于这些绑定。如果未绑定,则擦除类型为Object-例如

// unbound class types
public class MyGenericClass<T> {
  public T doSomething(T t) { return t; }
}
MyGenericClass untyped = new MyGenericClass();
Object t = untyped.doSomething("String");

// bound class types
public class MyBoundedGenericClass<T extends Number> {
  public T doSomething(T t) { return t; }
}
MyBoundedGenericClass bounded = new MyBoundedGenericClass();
Object t1 = bounded.doSomething("String"); // does not compile
Number t2 = bounded.doSomething(1); // does compile
//未绑定的类类型
公共类MyGenericClass{
公共T doSomething(T T){return T;}
}
MyGenericClass untyped=新的MyGenericClass();
对象t=非类型化的doSomething(“字符串”);
//绑定类类型
公共类MyBoundedGenericClass{
公共T doSomething(T T){return T;}
}
MyBoundedGenericClass bounded=新的MyBoundedGenericClass();
对象t1=有界。doSomething(“字符串”);//不编译
数字t2=有界。doSomething(1);//编译

虽然泛型方法是实例方法,但我不清楚JLS 4.8是否适用于泛型方法。泛型方法的类型(在前面的示例中为
)不是非类型化的,因为它的类型由方法参数决定-只有类是非类型化/原始类型化的。

对于Java泛型,如果使用泛型类的原始形式,则类上的所有泛型,即使是不相关的泛型方法,如
makeSingletonList
doSomething
方法,也会变成原始方法。据我所知,其原因是提供与Java代码编写的预泛型的向后兼容性


如果泛型类型参数
T
,则只需将其从
MyGenericClass
中删除,将方法保留为带有
K
的泛型。否则,您将不得不接受这样一个事实:类类型参数
T
必须提供给您的类,才能在类中的任何其他内容上使用泛型。

原因是与泛型前代码的向后兼容性。pre-generics代码没有使用泛型参数,而是使用今天看来是原始类型的参数。预泛型代码将使用
Object
引用,而不是使用泛型类型的引用,而原始类型将type
Object
用于所有泛型参数,因此代码确实是向后兼容的

作为例子,考虑这个代码:

List list = new ArrayList();
这是前泛型代码,一旦引入泛型,它就被解释为原始泛型类型,相当于:

List<?> list = new ArrayList<>();
MyGenericClass untyped = new MyGenericClass();
List list = untyped.makeSingletonList("String");
List<String> typedList = list;

在泛型之前使用的
列表
版本使用
对象
来引用列表元素,而这个版本也使用
对象
来引用列表元素,因此保留了向后兼容性。

我找到了完全放弃泛型的一个理由(但这不是很好)。 原因是:泛型可能是有界的。考虑这个类:

public static class MyGenericClass<T> {
    public <K extends T> K doSomething(K k){
        return k;
    }

    public <K> List<K> makeSingletonList(K k){
        return Collections.singletonList(k);
    }
}
公共静态类MyGenericClass{
公共钾剂量计(K){
返回k;
}
公共列表makeSingletonList(K){
返回集合。单音列表(k);
}
}
当使用不带泛型的类时,编译器必须在
doSomething
中丢弃泛型。 我认为所有的泛型都被丢弃了,以符合这种行为


makeSingletonList
编译是因为Java执行了从
List
List
的未经检查的强制转换(但编译器显示警告)。

这并没有回答基本问题,但解决了为什么
makeSingletonList(…)
编译而
doSomething(…)
没有:

MyGenericClass
的非类型化实现中:

MyGenericClass untyped = new MyGenericClass();
List<String> list = untyped.makeSingletonList("String");
MyGenericClass untyped=新建MyGenericClass();
List List=untyped.makeSin
public static class MyGenericClass<T> {
    public <K extends T> K doSomething(K k){
        return k;
    }

    public <K> List<K> makeSingletonList(K k){
        return Collections.singletonList(k);
    }
}
MyGenericClass untyped = new MyGenericClass();
List<String> list = untyped.makeSingletonList("String");
MyGenericClass untyped = new MyGenericClass();
List list = untyped.makeSingletonList("String");
List<String> typedList = list;
MyGenericClass untyped = new MyGenericClass();
List<Integer> list = untyped.makeSingletonList("String"); // this compiles!!!
Integer a = list.get(0);
public class MyGenericClass {
    public Object doSomething(Object k){
        return k;
    }
}
MyGenericClass foo = new MyGenricClass();
NotKType notKType = foo.doSomething(new NotKType());
public class MyGenericClass<T> {
    public <K extends KType> K doSomething(K k){
        return k;
    }
}