1

我有一个域类,它有很多子类,如下所示( B 是接口类型, B1 和 B2 )实现 B 接口。

正如您在我的主课中看到的那样,它需要转换 (B1 b1 = (B1) a.getB();) 并且我们知道它可以是 B1 或 B2,所以据我所知应该没问题。

我遇到的问题是类型可以增长很多,使用 A 的人需要设置更多条件来检查 B 的实例并访问 B1 或 B2 的特定值……有什么方法可以跳过这个转换,所以它可以未来减少很多条件

public class TestMain
{
  public static void main(String[] args)
  {
    A a = new A();
    //this can be B1 or B2 
    B1 b1 = (B1) a.getB();
  }
}

public class A
{
  private B b;

  protected B getB()
  {
    return b;
  }

  protected void setB(B b)
  {
    this.b = b;
  }
}

public interface B
{
  void test();
}

public class B1 implements B
{
  @Override
  public void test()
  {
    // TODO Auto-generated method stub
  }
}
public class B2 implements B
{
  @Override
  public void test()
  {
    // TODO Auto-generated method stub
  }
}
4

4 回答 4

2

假设您确实需要此功能(上面 Eran 的评论提出了一个很好的观点;多态性可能会完成您需要的大部分或全部功能),答案是泛型。它们是一个稍微高级的主题,但它们是 Java 的核心(JDK 中的所有集合类都使用它们),因此学习它们非常重要。

泛型是一种表示“某种类型”的方式,也可以选择“某种类型是某种其他类型的子类型”。后者是你想要的。

public class A<T extends B>
{
  private T b;

  protected T getB()
  {
    return b;
  }

  protected void setB(T b)
  {
    this.b = b;
  }
}

<T extends B>部分声明了 的泛型参数T,并说它必须是 的子类B。从那时起,您可以将T其用作类中的A类型。对于此类的用户,他们必须指定A它的类型,编译器会自动为您进行向下转换:

A<B1> a = new A<B1>();
a.set(new B1());
B1 b = a.getB();

请注意,在第二行中,如果您这样做了a.set(new B2()),那将是编译时错误:编译器会抱怨a参数化为B1,因此您不能将 a 传递B2给它。在非常高的层次上,您可以想象编译器正在执行搜索和替换,T在原始类中替换为B1. 如果您声明:

A<B2> a = new A<B2>();

然后搜索和替换将类似地T变成B2.

实际上,由于一种叫做擦除的东西,它并不是那么简单。您可以在Java trail on generics 上阅读更多内容,还有很多其他可用资源。这个 PDF是一个很好的中级描述。

于 2013-09-07T06:25:16.950 回答
1

您也可以在不强制转换的情况下执行以下操作。

B b1 = a.getB();
于 2013-09-07T06:13:56.073 回答
0

您需要在执行向下转换时显式添加转换。向上转换是隐含的,并且总是安全的。另外,为什么需要将其显式转换为 B1 或 B2。相反,您可以使用它的基本接口类型作为对对象(即 B)的引用,这不需要您添加强制转换。

此外,您的基本引用类型也是安全的,因为您不必担心实际的对象类型,从而在运行时防止 ClassCastException。

使用基类型作为对象的引用有很多优点:

  • 在运行时避免 ClassCastException。
  • 您不必担心添加演员表
  • 此外,如果您向基类层次结构添加更多类,您仍然可以使用基引用类型访问这些类。这使您的设计更加灵活。
于 2013-09-07T06:16:18.660 回答
0
public class Test {
    public static void main(String[] args) {
        B b = new B1();
        if(B1.class.getName().equals(b.getClass().getName())){
            // implement logic for B1 class
        }else if(B1.class.getName().equals(b.getClass().getName())){
            // implement logic for B2 class         
        }
    }
}

interface B{    
}

class B1 implements B{  
}

class B2 implements B{  
}

或者

做方法覆盖,你可以为不同的类实现不同的逻辑,你可以使用接口引用调用方法而无需任何转换

于 2013-09-07T06:24:25.180 回答