如果变量已经是那种类型,为什么要将变量重新转换为类型?

时间:2013-05-08 20:25:32

标签: java casting

我正在检查一些专业编写的代码,并发现了这个片段。 (我希望这个片段足以回答我的问题 - 如果不让我知道的话)

...yada yada yada ....

private ITypedElement format(final ITypedElement elementToFormat) {
        try {
            if (elementToFormat instanceof IStreamContentAccessor) {
                final IStreamContentAccessor resNode = (IStreamContentAccessor) elementToFormat;
                final InputStream contentIs = resNode.getContents();
                final String contentsString = fromInputStreamToString(contentIs);
                final Map options = JavaCore.getOptions();
.... etc....

if段仅在elementToFormatIStreamContentAccessor的实例时才会运行。那么为什么程序在if语句“final IStreamContentAccessor resNode = (IStreamContentAccessor)elementToFormat;"

之后发出第一个语句

什么可能是将某些东西投射到它必须已经存在的类型?

5 个答案:

答案 0 :(得分:5)

程序员可能知道它是IStreamContentAccessor,但没有强制转换,编译器不知道它是IStreamContentAccessor,所以它不会让程序员访问任何字段/方法特定于IStreamContentAccessor类。

class ClassA {
    Object field1;
}

class ClassB extends ClassA
    Object field2;
}

ClassA obj = new ClassB();
obj.field1;  // This is fine, the compiler knows it's a ClassA
obj.field2;  // This isn't allowed - as far as the compiler knows it's a ClassA, not a ClassB
((ClassB)obj).field2;  // This is allowed - now the compiler knows it's a ClassB

答案 1 :(得分:3)

if语句保证该对象是该类型的实例。但是,对于JVM,对象仍为ITypedElement类型。只是因为现在知道它有效并不意味着JVM知道。

演员阵容允许您访问IStreamContentAccessor的方法。您会注意到,如果您没有演员,如果仅使用elementToFormat除了ITypedElement之外没有IStreamContentAccessor的方法引用Animal a; a = new Dog(); // "a" contains a Dog in memory, but we only KNOW that it's an Animal // because that is its declared type a.bark(); // fails at compile time - not all Animals can bark Dog d = (Dog) a; // This is a valid cast, because Dog extends Animal, but it's potentially unsafe. // // Another "valid" cast is: // Cat c = (Cat) a // but this would fail at runtime (ClassCastException) because the actual // object in memory (a Dog) cannot be cast to a Cat. if (a instanceof Dog) { // Now we KNOW that it's a Dog and we can cast safely. Dog d2 = (Dog) a; d2.bark(); // this is valid because d2's declared type is Dog } ,您就会收到错误。

例如:

if

总而言之,

  • 该演员表授予您访问子类字段的权限
  • {{1}}语句确保演员表有效
  • 这两个陈述在技术上完全独立
  • 你比JRE更聪明

答案 2 :(得分:1)

这很烦人,但是Java语言需要它。

变量elementToFormat的类型为ITypedElement。要将它用作IStreamContentAccessor需要强制转换。

在这种特定情况下,我们可以看到local参数必须是强制转换类型。但是,赋值的右侧可能不是局部参数 - 例如,成员变量或函数调用。相同的类型检查规则始终适用于右侧值,无论它来自何处。

这个习惯用法很烦人,因为我们必须重复三次。这对我们来说意味着额外的工作。但是 - 由于向下转化有时会产生代码味道 - 我们可以认为这个成语是一个小的语法盐。

答案 3 :(得分:0)

final IStreamContentAccessor resNode = (IStreamContentAccessor) elementToFormat;是因为elementToFormat不属于IStreamContentAccessor类型,但可以安全地投入其中。

答案 4 :(得分:0)

考虑下面的接口和类:

interface ITypedElement
{
    //...
}

interface IStreamContentAccessor
{
    InputStream getContents();
}

class Demo implements ITypedElement, IStreamContentAccessor
{
    //
}

演示类实现了这两个类,可以发送为:

ITypedElement demoInstance = new Demo();

format(demoInstance);

现在demoInstance也可以用作IStreamContentAccessor实例

编辑1:

好的,让我们说Demo课可以行为,如ITypedElementIStreamContentAccessor。如果我们创建一个Demo类的实例,它可以显示两个接口的行为,并且可以创建一个指向该实例的变量,使其仅提取我们感兴趣的行为。

Demo d = new Demo();
//d is an instance that can perform everything that `Demo` class is supposed to perform which includes behaviour of the two interfaces as well.

ITypedElement iti = (ITypedElement)d;
// Is above valid? Yes, because Demo implements ITypedElement.
// and we just extracted the `ITypedElement` *behaviour* from `d`.

//similarly 
IStreamContentAccessor isa = (IStreamContentAccessor)d;
// Is above valid? Yes, because Demo implements IStreamContentAccessor.
// and we just extracted the `IStreamContentAccessor` *behaviour* from `d`.

//Can we do something like
IStreamContentAccessor isaTough = (IStreamContentAccessor)iti;
// Yes, of course, and this brings up something rather interesting
// Even if we create a variable (`iti`) that *points* to an instance `d`
// it doesn't lose its original nature, rather we only see the behaviour
// we are interested in i.e `ITypedElement`.

基本上itiisadisaTough都受到合同设计强加给他们的行为所限制,即:{{1分别是{},ITypedElementIStreamContentAccessorDemo

我认为我只是让它变得有点复杂,而其他人可能会更好地解释一下?