如何将 `Class<T>` 用于子 class,其中 T 是父 class
How to used `Class<T>` with a child class, where T is the parent class
假设我有以下设置
public class Parent{
}
public class Child1 extends Parent{
}
public class Child2 extends Parent{
}
我可以做到以下几点
Class<Parent> test = Parent.class
但是下面给我一个错误。
Class<Parent> test = Child1.class
我该如何解决这个问题?
试试这个
Class<? extends Parent> test1 = Child1.class;
其他人已经说过了
Class<? extends Parent> test1 = Child1.class;
是解决方案。
所以现在问题可能出现了,为什么
Class<Parent> test1 = Child1.class;
一开始没用?或者,让我换个说法,为什么任何 Generic<T>
只适用于恰好 T
而不是它的子 class?
嗯,这与你能用它做什么有关。想象一个 class 像
public class Generic<T> {
private T content
public void accept(T stuff) { content = stuff; }
public void accept(Supplier<T> stuff) { content = stuff.get(); }
public T get() { return content; }
public void put(Consumer<T> c) { c.put(content); }
}
现在我们使用它并期望 Generic<Number>
能够在两个方向上正常工作:
Supplier<Integer> si = () -> 42;
Supplier<Number> sn = () -> 42;
Consumer<Integer> ci = n -> System.out.println(c);
Consumer<Number> cn = n -> System.out.println(c);
Generic<Integer> gi = new Generic<Integer>();
Generic<Number> gn = new Generic<Number>();
gi.accept(si); // works
gi.accept(sn); // won't work (1), that's ok
gi.put(ci); // works
gi.put(cn); // won't work (2), but should
gn.accept(si); // won't work (3), but should
gn.accept(sn); // works
gn.put(ci); // won't work (4), that's ok
gn.put(cn); // works
如果类型系统允许组合所有内容,那么所有 (1) (2) (3) (4) 都可以工作,这就太宽容了。所以你必须明确说明你希望它工作的方向,要宽容:
public class Generic<T> {
private T content
public void accept(T stuff) { content = stuff; }
public void accept(Supplier<? extends T> stuff) { content = stuff.get(); }
public T get() { return content; }
public void put(Consumer<? super T> c) { c.put(content); }
}
现在,accept()
接受所有提供 T
或 subclass 的内容,put()
接受所有提供 T
或 super[ 的内容=50=]es.
这样,
gi.put(cn); // (2)
gn.accept(si); // (3)
两者都有效(gi.put()
接受 Consumer<Number>
和 gn.accept()
接受 Supplier<Integer>
),而
gi.accept(sn); // still won't work (1), that's ok
gn.put(ci); // still won't work (4), that's ok
不起作用,因为分配存在兼容性问题。
假设我有以下设置
public class Parent{
}
public class Child1 extends Parent{
}
public class Child2 extends Parent{
}
我可以做到以下几点
Class<Parent> test = Parent.class
但是下面给我一个错误。
Class<Parent> test = Child1.class
我该如何解决这个问题?
试试这个
Class<? extends Parent> test1 = Child1.class;
其他人已经说过了
Class<? extends Parent> test1 = Child1.class;
是解决方案。
所以现在问题可能出现了,为什么
Class<Parent> test1 = Child1.class;
一开始没用?或者,让我换个说法,为什么任何 Generic<T>
只适用于恰好 T
而不是它的子 class?
嗯,这与你能用它做什么有关。想象一个 class 像
public class Generic<T> {
private T content
public void accept(T stuff) { content = stuff; }
public void accept(Supplier<T> stuff) { content = stuff.get(); }
public T get() { return content; }
public void put(Consumer<T> c) { c.put(content); }
}
现在我们使用它并期望 Generic<Number>
能够在两个方向上正常工作:
Supplier<Integer> si = () -> 42;
Supplier<Number> sn = () -> 42;
Consumer<Integer> ci = n -> System.out.println(c);
Consumer<Number> cn = n -> System.out.println(c);
Generic<Integer> gi = new Generic<Integer>();
Generic<Number> gn = new Generic<Number>();
gi.accept(si); // works
gi.accept(sn); // won't work (1), that's ok
gi.put(ci); // works
gi.put(cn); // won't work (2), but should
gn.accept(si); // won't work (3), but should
gn.accept(sn); // works
gn.put(ci); // won't work (4), that's ok
gn.put(cn); // works
如果类型系统允许组合所有内容,那么所有 (1) (2) (3) (4) 都可以工作,这就太宽容了。所以你必须明确说明你希望它工作的方向,要宽容:
public class Generic<T> {
private T content
public void accept(T stuff) { content = stuff; }
public void accept(Supplier<? extends T> stuff) { content = stuff.get(); }
public T get() { return content; }
public void put(Consumer<? super T> c) { c.put(content); }
}
现在,accept()
接受所有提供 T
或 subclass 的内容,put()
接受所有提供 T
或 super[ 的内容=50=]es.
这样,
gi.put(cn); // (2)
gn.accept(si); // (3)
两者都有效(gi.put()
接受 Consumer<Number>
和 gn.accept()
接受 Supplier<Integer>
),而
gi.accept(sn); // still won't work (1), that's ok
gn.put(ci); // still won't work (4), that's ok
不起作用,因为分配存在兼容性问题。