Java 泛型 - 参数化 class 与类型化方法
Java generics - parameterized class vs. typed method
我想这是一个重复的问题,但是在浏览了一大堆相关问题之后,我找不到匹配的问题......是的,蹩脚的借口;)
我目前正在为 POIs HSLF/XSLF 实现开发一个通用接口。
使用泛型的原因是为了支持 Iterable 接口,用户代码不需要向下转换到具体实现,即可以决定是使用实现 类 还是公共接口。
当然,如果没有泛型,return 类型缩小会按预期工作。
我的目标是尽量减少 类 用户的参数声明 - 请参阅 main 方法。在内部,通用引用可能更复杂。
所以我想要这样的东西:
(为了简单起见,我没有使用Iterable接口,而是使用了不同类型的参数)
/* 更新:将静态添加到 类 并删除空定义以实际拥有一个 运行 示例 */
public class GenericsTest {
static interface SlideShow {}
static class HSLFSlideShow implements SlideShow {}
static interface Notes<SS extends SlideShow> {}
static class HSLFNotes implements Notes<HSLFSlideShow> {}
static interface Slide<SS extends SlideShow> {
<N extends Notes<SS>> N getNotes();
<N extends Notes<SS>> void setNotes(N n);
}
// compile errors
static class HSLFSlide implements Slide<HSLFSlideShow> {
HSLFNotes notes = new HSLFNotes();
@Override
public HSLFNotes getNotes() { return notes; }
@Override
public void setNotes(HSLFNotes n) { notes = n; }
}
public static void main(String[] args) {
HSLFSlide s = new HSLFSlide();
HSLFNotes n = s.getNotes();
s.setNotes(n);
Slide<HSLFSlideShow> s2 = new HSLFSlide();
Notes<HSLFSlideShow> n2 = s2.getNotes();
}
}
我可以让它与……一起工作,但这似乎有点笨拙:
static interface Slide<SS extends SlideShow, N extends Notes<SS>> {
N getNotes();
void setNotes(N n);
}
static class HSLFSlide implements Slide<HSLFSlideShow,HSLFNotes> {
HSLFNotes notes = new HSLFNotes();
@Override
public HSLFNotes getNotes() { return notes; }
@Override
public void setNotes(HSLFNotes n) { notes = n; }
}
public static void main(String[] args) {
HSLFSlide s = new HSLFSlide();
HSLFNotes n = s.getNotes();
s.setNotes(n);
Slide<HSLFSlideShow,HSLFNotes> s2 = new HSLFSlide();
Notes<HSLFSlideShow> n2 = s2.getNotes();
}
如何最小化 main 方法中所需的类型参数(最小为 JDK6)?
虽然这似乎是一个答案,但请随时添加另一个选择:
public class GenericsTest {
static interface SlideShow {}
static class HSLFSlideShow implements SlideShow {}
static interface Notes<SS extends SlideShow> {}
static class HSLFNotes implements Notes<HSLFSlideShow> {}
static interface Slide<SS extends SlideShow> {
<N extends Notes<SS>> N getNotes();
<N extends Notes<SS>> void setNotes(N n);
}
static class HSLFSlide implements Slide<HSLFSlideShow> {
HSLFNotes notes = new HSLFNotes();
@SuppressWarnings("unchecked")
@Override
public HSLFNotes getNotes() {
return notes;
}
@Override
public <N extends Notes<HSLFSlideShow>> void setNotes(N n) {
notes = (HSLFNotes)n;
}
}
public static void main(String[] args) {
HSLFSlide s = new HSLFSlide();
HSLFNotes n = s.getNotes();
s.setNotes(n);
Slide<HSLFSlideShow> s2 = new HSLFSlide();
Notes<HSLFSlideShow> n2 = s2.getNotes();
}
}
据我所知,没有理由在这里使用泛型方法。用非泛型方法覆盖泛型方法可能并没有按照您认为的那样进行。我已经讨论过这个 and . (See also the generic methods tutorial.)
泛型方法的类型由调用站点决定。出于向后兼容的原因,允许将其覆盖为非泛型。仍然可以出现并执行以下操作:
HSLFSlide slide = ...;
Slide<HSLFSlideShow> oops = slide;
// perfectly legal
// probably throws a ClassCastException somewhere
oops.<SomeOtherNotes>set(new SomeOtherNotes());
例如,泛型方法让我们定义一个方法,returns它接受的类型相同:
static <T> T pass(T t) { return t; }
String s = pass("abc");
Double d = pass(3.14d);
这就是泛型方法的用武之地。
一个更典型的方法来做你想做的事情如下:
interface Slide<SS extends SlideShow> {
Notes<SS> getNotes();
void setNotes(Notes<SS> n);
}
class HSLFSlide implements Slide<HSLFSlideShow> {
Notes<HSLFSlideShow> notes = new HSLFNotes();
@Override
public Notes<HSLFSlideShow> getNotes() { return notes; }
@Override
public void setNotes(Notes<HSLFSlideShow> n) { notes = n; }
}
如果有一些要求notes
的引用类型不能是接口,你应该再看看你的设计。例如,也许 HSLFNotes
实现具有应移至 Notes
接口的功能。
另一种方式如下:
interface Slide<N extends Notes<?>> {
N getNotes();
void setNotes(N n);
}
class HSLFSlide implements Slide<HSLFNotes> {
HSLFNotes notes = new HSLFNotes();
@Override
public HSLFNotes getNotes() { return notes; }
@Override
public void setNotes(HSLFNotes n) { notes = n; }
}
还有问题中的工作示例:
interface Slide<SS extends SlideShow, N extends Notes<SS>> {…}
class HSLFSlide implements Slide<HSLFSlideShow, HSLFNotes> {…}
这其实很好。
我想这是一个重复的问题,但是在浏览了一大堆相关问题之后,我找不到匹配的问题......是的,蹩脚的借口;)
我目前正在为 POIs HSLF/XSLF 实现开发一个通用接口。 使用泛型的原因是为了支持 Iterable 接口,用户代码不需要向下转换到具体实现,即可以决定是使用实现 类 还是公共接口。 当然,如果没有泛型,return 类型缩小会按预期工作。
我的目标是尽量减少 类 用户的参数声明 - 请参阅 main 方法。在内部,通用引用可能更复杂。
所以我想要这样的东西: (为了简单起见,我没有使用Iterable接口,而是使用了不同类型的参数)
/* 更新:将静态添加到 类 并删除空定义以实际拥有一个 运行 示例 */
public class GenericsTest {
static interface SlideShow {}
static class HSLFSlideShow implements SlideShow {}
static interface Notes<SS extends SlideShow> {}
static class HSLFNotes implements Notes<HSLFSlideShow> {}
static interface Slide<SS extends SlideShow> {
<N extends Notes<SS>> N getNotes();
<N extends Notes<SS>> void setNotes(N n);
}
// compile errors
static class HSLFSlide implements Slide<HSLFSlideShow> {
HSLFNotes notes = new HSLFNotes();
@Override
public HSLFNotes getNotes() { return notes; }
@Override
public void setNotes(HSLFNotes n) { notes = n; }
}
public static void main(String[] args) {
HSLFSlide s = new HSLFSlide();
HSLFNotes n = s.getNotes();
s.setNotes(n);
Slide<HSLFSlideShow> s2 = new HSLFSlide();
Notes<HSLFSlideShow> n2 = s2.getNotes();
}
}
我可以让它与……一起工作,但这似乎有点笨拙:
static interface Slide<SS extends SlideShow, N extends Notes<SS>> {
N getNotes();
void setNotes(N n);
}
static class HSLFSlide implements Slide<HSLFSlideShow,HSLFNotes> {
HSLFNotes notes = new HSLFNotes();
@Override
public HSLFNotes getNotes() { return notes; }
@Override
public void setNotes(HSLFNotes n) { notes = n; }
}
public static void main(String[] args) {
HSLFSlide s = new HSLFSlide();
HSLFNotes n = s.getNotes();
s.setNotes(n);
Slide<HSLFSlideShow,HSLFNotes> s2 = new HSLFSlide();
Notes<HSLFSlideShow> n2 = s2.getNotes();
}
如何最小化 main 方法中所需的类型参数(最小为 JDK6)?
虽然这似乎是一个答案,但请随时添加另一个选择:
public class GenericsTest {
static interface SlideShow {}
static class HSLFSlideShow implements SlideShow {}
static interface Notes<SS extends SlideShow> {}
static class HSLFNotes implements Notes<HSLFSlideShow> {}
static interface Slide<SS extends SlideShow> {
<N extends Notes<SS>> N getNotes();
<N extends Notes<SS>> void setNotes(N n);
}
static class HSLFSlide implements Slide<HSLFSlideShow> {
HSLFNotes notes = new HSLFNotes();
@SuppressWarnings("unchecked")
@Override
public HSLFNotes getNotes() {
return notes;
}
@Override
public <N extends Notes<HSLFSlideShow>> void setNotes(N n) {
notes = (HSLFNotes)n;
}
}
public static void main(String[] args) {
HSLFSlide s = new HSLFSlide();
HSLFNotes n = s.getNotes();
s.setNotes(n);
Slide<HSLFSlideShow> s2 = new HSLFSlide();
Notes<HSLFSlideShow> n2 = s2.getNotes();
}
}
据我所知,没有理由在这里使用泛型方法。用非泛型方法覆盖泛型方法可能并没有按照您认为的那样进行。我已经讨论过这个
泛型方法的类型由调用站点决定。出于向后兼容的原因,允许将其覆盖为非泛型。仍然可以出现并执行以下操作:
HSLFSlide slide = ...;
Slide<HSLFSlideShow> oops = slide;
// perfectly legal
// probably throws a ClassCastException somewhere
oops.<SomeOtherNotes>set(new SomeOtherNotes());
例如,泛型方法让我们定义一个方法,returns它接受的类型相同:
static <T> T pass(T t) { return t; }
String s = pass("abc");
Double d = pass(3.14d);
这就是泛型方法的用武之地。
一个更典型的方法来做你想做的事情如下:
interface Slide<SS extends SlideShow> {
Notes<SS> getNotes();
void setNotes(Notes<SS> n);
}
class HSLFSlide implements Slide<HSLFSlideShow> {
Notes<HSLFSlideShow> notes = new HSLFNotes();
@Override
public Notes<HSLFSlideShow> getNotes() { return notes; }
@Override
public void setNotes(Notes<HSLFSlideShow> n) { notes = n; }
}
如果有一些要求notes
的引用类型不能是接口,你应该再看看你的设计。例如,也许 HSLFNotes
实现具有应移至 Notes
接口的功能。
另一种方式如下:
interface Slide<N extends Notes<?>> {
N getNotes();
void setNotes(N n);
}
class HSLFSlide implements Slide<HSLFNotes> {
HSLFNotes notes = new HSLFNotes();
@Override
public HSLFNotes getNotes() { return notes; }
@Override
public void setNotes(HSLFNotes n) { notes = n; }
}
还有问题中的工作示例:
interface Slide<SS extends SlideShow, N extends Notes<SS>> {…}
class HSLFSlide implements Slide<HSLFSlideShow, HSLFNotes> {…}
这其实很好。