在Java中的向上转型和向下转型

4

我可以理解什么是向上转型,但是向下转型有些困惑。我的问题是为什么我们需要进行向下转型?你能给我一个现实世界的例子吗?向下转型那么重要吗?

8个回答

9

向下转型是一种必要的恶,例如在处理返回非泛型集合的遗留API时。另一个经典的例子是equals方法:

public class Phleem{

    public Phleem(final String phloom){
        if(phloom == null){
            throw new NullPointerException();
        }
        this.phloom = phloom;
    }

    private final String phloom;

    public String getPhloom(){
        return phloom;
    }

    @Override
    public boolean equals(final Object obj){
        if(obj instanceof Phleem){
            // downcast here
            final Phleem other = (Phleem) obj;
            return other.phloom.equals(phloom);
        }
        return false;
    }

    // ...

}

我无法想象出必须使用向上转型的例子。当然,从方法中返回尽可能不太具体的对象是一种好的实践,但这完全可以在没有强制类型转换的情况下完成:

public Collection<String> doStuff(){
    // no casting needed
    return new LinkedHashSet<String>();
}

一个需要进行向上转型的情况是当您想要将引用类型传递给一个重载方法时。根据重载和参数,可能需要进行向上转型以消除歧义或强制选择特定的重载。 - Stephen C

3

在过滤器中访问ServletResponse的头方法,您需要将其向下转换为HttpServletResponse。

按其扩展类声明对象是很好的,这样您可以随时更改实现。但是,如果您需要访问任何特定于实现的方法,则需要向下转换。


1
你需要记住的是,只有在运行时可能成功时才允许向下转型。
这将起作用:
Object o = doStaff();
String s = (String) o; 

这将会失败:
Object o = new Object();
String s = (String) s;

Q1:为什么我们应该使用向下转型?
通常情况下,是否要使用向下转型取决于开发人员。有时方法返回对象或者作为参数使用,比如equal方法,然后通过子类转型我们可以恢复到特定的类型。
Q2:向下转型重要吗?
就像编码中的任何事物一样,但更好的说法是有用的,在我看来它是重要的。

0

当你接收到一个对象,你知道它有更具体的类型(在类层次结构中向下),并且你想将其转换为该类型时,就需要进行向下转型。

例如:你从某个服务接收到 Object,你知道它实际上是 String,然后你将其向下转型为 String。在向下转型之前,你应该始终检查类型,否则你会冒着 ClassCastException 的风险:

Object receivedObject = receiveFromSomewhere();
if(receivedObject instanceof String){
    receivedString = (String) receivedObject;
}

0

向下转型示例

//: RTTI.java
// Downcasting & Run-Time Type
// Identification (RTTI)
import java.util.*;

class Useful {
  public void f() {}
  public void g() {}
}

class MoreUseful extends Useful {
  public void f() {}
  public void g() {}
  public void u() {}
  public void v() {}
  public void w() {}
}

public class RTTI {
  public static void main(String[] args) {
    Useful[] x = {
      new Useful(),
      new MoreUseful()
    };
    x[0].f();
    x[1].g();
    // Compile-time: method not found in Useful:
    //! x[1].u();
    ((MoreUseful)x[1]).u(); // Downcast/RTTI
    ((MoreUseful)x[0]).u(); // Exception thrown
  }
} ///:~ 

请查看源链接以获取更多信息。


0

你需要使用它的一个场景是当你重写从Object继承的equals方法时。由于传递给该方法的参数是Object类型,因此你必须将其强制转换为类的类型以便能够访问其中定义的方法和变量。只需特别注意所引用的对象即可。也就是说,实例化的对象被传递到equals()方法中,而不是它的引用。

class MySuperClass
{
    private int num1;

    public MySuperClass() {}

    public MySuperClass(int num1)
    {
        this.num1 = num1;
    }
}

class MySubClass extends MySuperClass
{
    private int num;

    public MySubClass(int num)
    {
        this.num = num;
    }

    public boolean equals(Object o)
    {
        if (!(o instanceof MySubClass))
            return false;

        MySubClass mySub = (MySubClass)o;

        return(mySub.num == num);
    }

    public static void main(String[] args)
    {
        Object mySub = new MySubClass(1);
        MySuperClass mySup = new MySubClass(1);

        System.out.println(mySub.equals(mySup));
    }

}

0

你问题的最佳解决方案是阅读一本好书。你将学习关于多态性、对象、模式...
一个很好的开始是"Beginning java objects 2nd edition"


0

随着泛型的引入,它比以前不那么重要了,但有时你仍然需要它。

例如,当你从ObjectInputStream读取一个对象时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接