我试图将一些使用(有界)通配符泛型的Java代码转换为C#.我的问题是,Java似乎允许泛型类型在与通配符一起使用时既是协变的又是逆变的.
[这是关于一个更简单的有界通配符案例的前一个问题的衍生物]
Java - 作品:
class Impl { }
interface IGeneric1<T extends Impl> {
void method1(IGeneric2<?> val);
T method1WithParam(T val);
}
interface IGeneric2<T extends Impl> {
void method2(IGeneric1<?> val);
}
abstract class Generic2<T extends Impl> implements IGeneric2<T> {
// !! field using wildcard
protected IGeneric1<?> elem;
public void method2(IGeneric1<?> val1) {
val1.method1(this);
//assignment from wildcard to wildcard
elem = val1;
}
}
abstract class Generic<T extends Impl> implements IGeneric1<T>, IGeneric2<T> {
public void method1(IGeneric2<?> val2) {
val2.method2(this);
} …Run Code Online (Sandbox Code Playgroud) 所以我正在阅读泛型方法,我感到困惑.我先说一下这个问题:
在这个例子中:假设我需要一个适用于任何类型T的selectionSort版本,通过使用调用者提供的外部可比较.
第一次尝试:
public static <T> void selectionSort(T[] arr, Comparator<T> myComparator){....}
Run Code Online (Sandbox Code Playgroud)
假设我有:
现在,我这样做:
selectionSort(arr, myComparator);
Run Code Online (Sandbox Code Playgroud)
并且它不起作用,因为myComparator不适用于Vehicle的任何子类.
然后,我这样做:
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator){....}
Run Code Online (Sandbox Code Playgroud)
这个声明会起作用,但我不完全确定我一直在做什么......我知道使用是要走的路.如果"?super T"的意思是"一个未知的超类型T",那么我是强加上限还是上限?为什么超级?我的目的是让T的任何子类使用myComparator,为什么"?super T".如此困惑......如果您对此有任何见解我会很感激..
谢谢!
以下陈述:
URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> uclc = ucl.getClass();
Run Code Online (Sandbox Code Playgroud)
失败并出错:
Type mismatch: cannot convert from Class<capture#2-of ? extends URLClassLoader> to Class<URLClassLoader>
Run Code Online (Sandbox Code Playgroud)
我为什么需要演员?
我发现了几个帖子解释了为什么你不能反过来(将T分配给a),但那种(有点)是显而易见的.
注意:我在eclipse Luna下编码,所以我不知道它是否是Luna Quirk,或者是否有一些我在仿制药中真的不理解的东西.
(如果这是重复的,请指出我正确的答案!我搜索并阅读了几个(> 5)相关问题,但似乎没有出现在标记上.还查看了泛型常见问题和其他来源...)
显然这是一种正确的做法,当集合类使用比较器时,它应该具有Comparator<? super T>参数化类型的类型T.你可以看到很多地方,例如TreeMap.好的.
我的问题是使用Comparator.naturalOrder()哪个参数化,T extends Comparable<? super T>但返回一个Comparator<T>.我正在尝试在我的集合类中有一个字段,它包含用户指定的比较器或Comparator.naturalOrder比较器.
我无法让它发挥作用.我的问题都是相关的:
Comparator.naturalOrder正确使用?
naturalOrder比较器的字段吗?T没有参数化T implements Comparable<? super T>,所以选择的设计模式是多么naturalOrder有用,因为它需要后一个有界通配符,而不是无约束类型参数?谢谢!
下面是编译器错误的实际示例:
所以:如果我在某些类中有这样的代码,其中T没有边界(如在所有现有的集合类中):
class Foo<T> {
private Comparator<? super T> comparator;
public void someMethod(Comparator<? super T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
Run Code Online (Sandbox Code Playgroud)
有这个错误:
Error:(331, 50) java: incompatible …Run Code Online (Sandbox Code Playgroud) 我有一个带有类型参数的类。
class MyObject<IdType> {
@Setter
@Getter
private IdType id;
}
Run Code Online (Sandbox Code Playgroud)
我想我可以添加一些方便的方法,所以我做到了。
<T extends MyObject<? super IdType>> void copyIdTo(T object) {
object.setId(getId());
}
< T extends MyObject<? extends IdType>> void copyIdFrom(T object) {
object.copyIdTo(this);
}
Run Code Online (Sandbox Code Playgroud)
我只是意识到我可以做到这一点。
void copyIdTo(MyObject<? super IdType> object) {
object.setId(getId());
}
void copyIdFrom(MyObject<? extends IdType> object) {
object.copyIdTo(this);
}
Run Code Online (Sandbox Code Playgroud)
这两套方法是否等效?首选哪种方式(或样式)?
这不是功课.
是否可以编写泛型方法,如下所示:
<T extends Number> T plusOne(T num) {
return num + 1; // DOESN'T COMPILE! How to fix???
}
Run Code Online (Sandbox Code Playgroud)
没有使用一堆instanceof和演员,这可能吗?
以下3种方法编译:
Integer plusOne(Integer num) {
return num + 1;
}
Double plusOne(Double num) {
return num + 1;
}
Long plusOne(Long num) {
return num + 1;
}
Run Code Online (Sandbox Code Playgroud)
是否有可能编写约束仿制药T只Integer,Double或Long?
我在使用java泛型时遇到问题 - 特别是使用通配符捕获.这是我所拥有的代码的简化版本,它展示了我所看到的问题.这让我抓狂:
public class Task {
private Action<ActionResult, ? extends ActionSubject> action;
private ActionSubject subject = new ActionSubjectImpl();
private List<ActionResult> list = new ArrayList<>();
public static void main(String[] args) {
Task task = new Task();
task.setAction(new ActionImpl());
task.doAction();
}
public void setAction(Action<ActionResult, ? extends ActionSubject> action) {
this.action = action;
}
public void doAction() {
list.add(action.act(subject));
}
public static class ActionResult { }
public interface Action<T, U> {
public T act(U argument);
}
public interface ActionSubject {
public String …Run Code Online (Sandbox Code Playgroud) 如果您需要将接口类型的参数传递给方法,您可以使用两个 impl。
使用有界类型参数:
public static <I extends InterfaceObj> void isTrue(boolean expression, I interfaceobj) {
if(!expression){
throw new RunTimeException(interfaceobj);
}}
Run Code Online (Sandbox Code Playgroud)
否则你可以使用接口类型:
public static void isTrue(boolean expression, InterfaceObj interfaceobj) {
if(!expression){
throw new RunTimeException(interfaceobj);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,如果我有一个实现 InterfaceObj 的类,我可以在第一个和第二个示例中使用它,这样我就看不到其中一个或另一个的差异、优点和缺点。
我正在阅读Java中的通配符主题,我在下面的代码中遇到了困难
static <T> void type(List<? super T> list){
//...
}
static <T> void type2(List<? extends T> list){
//...
}
Run Code Online (Sandbox Code Playgroud)
如果您通过此代码调用这些方法,则会出错并且这是可以理解的
List<?> unbounded=new ArrayList<Long>();
//! type(unbounded); //:Error here
//! type2(unbounded); //:Same Error here
Run Code Online (Sandbox Code Playgroud)
但是如果你通过添加一个额外的arg来改变这些方法的签名,就像这样
static <T> void type(List<? super T> list, T arg){
//...
}
static <T> void type2(List<? extends T> list, T arg){
//...
}
Run Code Online (Sandbox Code Playgroud)
然后打电话给他们
List<?> unbounded=new ArrayList<Long>();
Long lng=90L;
//! type(unbounded,lng); //:Error here
type2(unbounded,lng); //No error in this one now
Run Code Online (Sandbox Code Playgroud)
为什么这种行为只需添加一个额外的arg?有限的列表如何通过添加一个xtra arg来接受无界的?
鉴于:
public class Testcase {
public static <E> List<List<E>> transform(List<List<E>> list) {
return list;
}
public static <E> List<List<? extends E>> transform2(List<List<? extends E>> list) {
return list;
}
public static void main(String[] args) {
List<List<Integer>> known = new ArrayList<>();
List<List<? extends Number>> unknown = new ArrayList<>();
transform(known); // works
transform(unknown); // fails
transform2(known); // fails
transform2(unknown); // works
}
}
Run Code Online (Sandbox Code Playgroud)
编译器接受transform(known)但抱怨:
cannot infer type-variable(s) E
(argument mismatch; List<List<? extends Number>> cannot be converted to List<List<E>>)
where E …Run Code Online (Sandbox Code Playgroud) bounded-wildcard ×10
java ×10
generics ×8
extends ×2
wildcard ×2
.net ×1
comparator ×1
covariance ×1
java-8 ×1