如何定义一个具有泛型参数的类,该参数应扩展具有泛型参数的另一个类?

huangapple go评论73阅读模式
英文:

How to define a class that features a generic parameter which extends a class that features a generic parameter?

问题

考虑以下情况

```java
public class PointCloud<T extends Point> { } 

public class PointCloud3d extends PointCloud<Point3d> { }

如何编写一个接受泛型参数 T,它是 PointCloud<T> 的扩展的类?

public class PointCloudReader<T extends PointCloud> { 
    T read(String path);
}

或者

public class PointCloudReader<T extends PointCloud<?>> {
    T read(String path);
}

这两个类定义之间有什么区别?


请注意,这里我只返回了翻译好的部分,没有包括其他内容。

<details>
<summary>英文:</summary>

Consider the following case:

```java
public class PointCloud&lt;T extends Point&gt; { } 

public class PointCloud3d extends PointCloud&lt;Point3d&gt; { }

How would I write a class that takes a generic parameter T that is an extension of PointCloud&lt;T&gt;?

public class PointCloudReader&lt;T extends PointCloud&gt; { 
    T read(String path);
}

or

public class PointCloudReader&lt;T extends PointCloud&lt;?&gt;&gt; {
    T read(String path);
}

What's the difference between the two class definitions?

答案1

得分: 2

这个是不行的:

public class PointCloudReader<P extends Point, T extends PointCloud<P>> { 
    T read(String path);
}

这个不好,因为它使用了 PointCloud原始 类型,并且无论如何都不起作用:

public class PointCloudReader<T extends PointCloud> { 
    T read(String path);
}

这个也不好,因为它使用了一个 未知PointCloud 类型,并且无论如何都不起作用:

public class PointCloudReader<T extends PointCloud<?>> {
    T read(String path);
}
英文:

Neither.

Use this:

public class PointCloudReader&lt;P extends Point, T extends PointClound&lt;P&gt;&gt; { 
    T read(String path);
}

This is no good because it use the raw type of PointCloud, and doesn't work anyway:

public class PointCloudReader&lt;T extends PointCloud&gt; { 
    T read(String path);
}

This is no good because it uses an unknown type of PointCloud, and doesn't work anyway:

public class PointCloudReader&lt;T extends PointCloud&lt;?&gt;&gt; {
    T read(String path);
}

答案2

得分: 1

代码部分不要翻译,只返回翻译好的内容:

首先情况不同之处在于,第一种情况下你使用的是未经处理的类型(raw type),这是不推荐的。而在第二种情况下,你使用了通配符(wildcard),这更加类型安全。

例如,考虑以下代码:

class Test<T extends ArrayList<?>>{
    void test(T t) {
        Object o = t.get(0);
        t.add("someStr"); // 这一行将会出现编译错误
    }
}

如果你使用的是<T extends ArrayList>,尽管不会出现编译错误,但如果你使用了错误类型的ArrayList,在运行时会抛出异常。
但是,如果你使用<T extends ArrayList<?>>,这一行将会出现编译错误,以警告你这行代码是不安全的。

英文:

The difference is that in first case you are using raw type which is not recommonded. In second case you are using wildcard which is more type safe.

for example,consider following code:

class Test &lt;T extends ArrayList&lt;?&gt;&gt;{
        void test(T t) {
            Object o=t.get(0);
            t.add(&quot;someStr&quot;); //this line will be a compile error
        }
    }

If you are using &lt;T extends ArrayList&gt;, you won't get any compile error, but if you are using a wrong type ArrayList, a exception will be thrown ar runtime.
But if you use &lt;T extends ArrayList&lt;?&gt;, there will be a compile error to warn you this line is not type safe.

huangapple
  • 本文由 发表于 2020年9月21日 06:11:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63984125.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定