Java协作泛型类:我们能避免未经检查的强制转换吗?
编辑:对不起;我急于给大家举一个简单的例子,在我的第一个问题版本中,我没有提供足够的关于需求的信息 我有两个抽象泛型类。他们相互合作,因此相互依赖。有时,一方需要将此传递给另一方。我正试图找到一种类型安全的方法来做到这一点Java协作泛型类:我们能避免未经检查的强制转换吗?,java,generics,compiler-errors,Java,Generics,Compiler Errors,编辑:对不起;我急于给大家举一个简单的例子,在我的第一个问题版本中,我没有提供足够的关于需求的信息 我有两个抽象泛型类。他们相互合作,因此相互依赖。有时,一方需要将此传递给另一方。我正试图找到一种类型安全的方法来做到这一点 public abstract class AbstractA<T extends AbstractB<? extends AbstractA<T>>> { protected void foo() { T aB
public abstract class AbstractA<T extends AbstractB<? extends AbstractA<T>>> {
protected void foo() {
T aB = createB();
aB.setA(this);
}
/** factory method */
abstract public T createB();
}
public abstract class AbstractB<T extends AbstractA<? extends AbstractB<T>>> {
private T theA;
@SuppressWarnings("unchecked")
public void setA(AbstractA<? extends AbstractB<?>> theA) { // dreamed of parameter list (T theA)
// Unchecked cast from AbstractA<capture#1-of ? extends AbstractB<?>> to T
this.theA = (T) theA;
}
protected T getA() {
return theA;
}
}
(
class AbstractA如果我正确理解了您的意思,这应该会创建您想要的绑定
class Demo {
public static void main(String[] args) {
ConcreteA a = new ConcreteA();
ConcreteB b = new ConcreteB();
a.foo(b);
b = (ConcreteB) a.getB();
}
}
abstract class AbstractA<T extends AbstractB<?>>{
private AbstractB<?> b;
public AbstractB<?> getB(){
return b;
}
void foo(AbstractB<?> aB) {
b = aB;
aB.bar(this);
}
}
abstract class AbstractB<T extends AbstractA<?>> {
private AbstractA<?> a;
public AbstractA<?> getA(){
return a;
}
public void bar(AbstractA<?> theA) {
a = theA;
theA.foo(this);
}
}
class ConcreteA extends AbstractA<ConcreteB>{
}
class ConcreteB extends AbstractB<ConcreteA>{
}
类演示{
公共静态void main(字符串[]args){
ConcreteA a=新ConcreteA();
混凝土b=新混凝土b();
a、 傅(乙);;
b=(b)a.getB();
}
}
抽象类AbstractAB;
公共摘要b getB(){
返回b;
}
void foo(AbstractB aB){
b=aB;
aB.bar(本);
}
}
抽象类AbstractB a;
公共摘要a getA(){
返回a;
}
公共空白栏(AbstractA theA){
a=θ;
theA.foo(本);
}
}
类ConcreteA扩展了AbstractA{
}
类ConcreteB扩展了AbstractB{
}
我想这就是你自己的结局。我无法删除对ConcreteB的强制转换,getB()无法确定它所包含的类型。我现在明白了为什么在声明中有多个泛型语句。:)
如果你准备好了,继续搜索,如果你找到了,就发布你自己的答案,我很乐意看到
我希望解决你一半的问题对任何事情都有意义 我想我现在明白了为什么我不能在AbstractB
中声明public void setA(T theA)
,然后在foo()中将其称为aB.setA(this)
。假设我们有:
class IntermediateConcreteA extends AbstractA<ConcreteB> {
@Override
public ConcreteB createB() {
return new ConcreteB();
}
}
class SubConcreteA1 extends IntermediateConcreteA {}
class SubConcreteA2 extends IntermediateConcreteA {}
class ConcreteB extends AbstractB<SubConcreteA2> {}
class IntermediateConcreteA扩展了AbstractA{
@凌驾
公共混凝土b createB(){
返回新的concrete b();
}
}
类subcretea1扩展了IntermediateConcreteA{}
类subcretea2扩展了IntermediateConcreteA{}
类ConcreteB扩展了AbstractB{}
现在,如果我有一个subcretea1
并调用它的foo()
,那么createB()
将返回一个对象,该对象可以作为AbstractB
传递,但不能作为AbstractB
传递。因此,它的setA()
不应该接受this
作为参数。编译器错误消息毕竟是合乎逻辑的。每个抽象类都将使用两个类型参数进行参数化,一个用于A的实际具体类,另一个用于B的实际具体类:
public abstract class AbstractA<A extends AbstractA<A,B>, B extends AbstractB<A,B>> {
protected void foo() {
B aB = createB();
aB.setA(getThis());
}
abstract public A getThis();
abstract public B createB();
}
public abstract class AbstractB<A extends AbstractA<A,B>, B extends AbstractB<A,B>> {
private A theA;
public void setA(A theA) {
this.theA = theA;
}
protected A getA() {
return theA;
}
}
public class ConcreteA extends AbstractA<ConcreteA, ConcreteB> {
@Override
public ConcreteA getThis() {
return this;
}
@Override
public ConcreteB createB() {
return new ConcreteB();
}
public void concreteAMethod() {
// ...
}
}
public class ConcreteB extends AbstractB<ConcreteA, ConcreteB> {
public void bar() {
ConcreteA a = getA();
a.concreteAMethod();
}
}
公共抽象类AbstractA{
受保护的void foo(){
B aB=createB();
刚毛(getThis());
}
抽象公共A getThis();
抽象公共B createB();
}
公共抽象类AbstractB{
私人A theA;
公共无效setA(A theA){
this.theA=theA;
}
保护一个getA(){
返回theA;
}
}
公共类ConcreteA扩展了AbstractA{
@凌驾
公共混凝土{
归还这个;
}
@凌驾
公共混凝土b createB(){
返回新的concrete b();
}
公共空间{
// ...
}
}
公共类ConcreteB扩展了AbstractB{
公共空白栏(){
具体a=getA();
a、 具体方法();
}
}
工厂可以解决此问题:
public abstract class AbstractA {
public void abstractAMethod() {
// ...
}
}
public abstract class AbstractB<A> {
private A theA;
public void setA(A theA) {
this.theA = theA;
}
protected A getA() {
return theA;
}
}
public abstract class AbstractFactory<A extends AbstractA, B extends AbstractB<A>> {
private A theA = createA();
public A getA() {
return theA ;
}
public B getNextB() {
B newB = createB();
newB.setA(theA);
return newB;
}
protected abstract A createA();
protected abstract B createB();
}
公共抽象类AbstractA{
公共空间抽象方法(){
// ...
}
}
公共抽象类AbstractB{
私人A theA;
公共无效setA(A theA){
this.theA=theA;
}
保护一个getA(){
返回theA;
}
}
公共抽象类抽象工厂{
私有A theA=createA();
公共A getA(){
返回theA;
}
公共B getNextB(){
B newB=createB();
新刚毛(theA);
返回新兵;
}
受保护的抽象A createA();
受保护的抽象B createB();
}
现在,用户可以:
public class ConcreteA extends AbstractA {
public void concreteAMethod() {
// ...
}
}
public class ConcreteB extends AbstractB<ConcreteA> {
public void bar() {
ConcreteA a = getA();
a.abstractAMethod();
a.concreteAMethod();
}
}
public class ConcreteFactory extends AbstractFactory<ConcreteA, ConcreteB> {
@Override
protected ConcreteA createA() {
return new ConcreteA();
}
@Override
protected ConcreteB createB() {
return new ConcreteB();
}
}
公共类ConcreteA扩展了AbstractA{
公共空间{
// ...
}
}
公共类ConcreteB扩展了AbstractB{
公共空白栏(){
具体a=getA();
a、 抽象方法();
a、 具体方法();
}
}
公共类ConcreteFactory扩展了AbstractFactory{
@凌驾
受保护的混凝土A createA(){
返回新的ConcreteA();
}
@凌驾
受保护的混凝土B createB(){
返回新的concrete b();
}
}
我不认为这是抽象工厂模式的典型应用,不过
@Chris Wohlert,我确实放弃了我的生产代码,因为我认为工厂太过分了,但我不能放弃理论问题。我开始意识到我的问题其实是因为将两个不属于一起的概念塞进了AbstractA/ConcreteA层次结构中。虽然很多人可能对此不感兴趣,但我之所以发布这篇文章,有两个原因:(1)我觉得我欠Chris Wohlert我自己找到的答案(2)更重要的是,我想激励其他面临类似棘手泛型问题的人,从更高的层面来审视你的设计,而不仅仅是解决泛型和/或类类型转换问题。这当然对我有帮助。cast/泛型问题是一个信号,表明一些更基本的东西并不完全正确
public abstract class AbstractA {
public void foo() {
AbstractB aB = createB();
aB.setA(this);
}
/** factory method */
abstract public AbstractB createB();
}
public abstract class AbstractB {
private AbstractA theA;
public void setA(AbstractA theA) {
this.theA = theA;
}
// methods that use theA
}
没有泛型和类强制转换。将不属于A类层次结构的内容取出到Concrete C中(没有AbstractC):
客户需要比以前多出几行。在我的真实代码中,我需要在AbstractA和Concrete C中复制最后一个字段,但这样做是有意义的。总而言之,我认为这是一个低价格的设计,否则是纯粹和简单。“看起来有点复杂”-确实。我想知道这种嵌套对于应用程序案例是否真的是必要的(或合理地有益的)。省略最后一个extends
已经解决了这个问题,但只要不清楚在何处实际需要这种泛型,
public abstract class AbstractA {
public void foo() {
AbstractB aB = createB();
aB.setA(this);
}
/** factory method */
abstract public AbstractB createB();
}
public abstract class AbstractB {
private AbstractA theA;
public void setA(AbstractA theA) {
this.theA = theA;
}
// methods that use theA
}
public class Client {
public void putTheActTogether() {
ConcreteC theC = new ConcreteC();
// the concrete A
AbstractA theA = new AbstractA() {
@Override
public AbstractB createB() {
return new ConcreteB(theC);
}
};
// call methods in theA
}
}
public class ConcreteB extends AbstractB {
private final ConcreteC c;
public ConcreteB(ConcreteC c) {
super();
this.c = c;
}
public void bar() {
c.concreteCMethod();
}
}
public class ConcreteC {
public void concreteCMethod() { // was concreteAMethod(); moved and renamed
// ...
}
}