繁体   English   中英

将对象转换成类

[英]Cast an Object into a class

我正在尝试将Object转换为类实例。 当然,classes实例的Object应该继承所有方法。

所以这是示例代码(2)中的问题,因为我无法确切解释我的意思:

Class Fish {}
Class Dog {}

class Instances() {

    private Fish fish = new Fish();
    private Dog dog = new Dog();

    public Object getInstance(String className) {

        if( className.equals("fish") ) 

            return fish;

        else

            return dog;

    }

}

class test() {

    Instances in = new Instances();

    public static void main(String[] args) {

        // 1: works (transmits all the methods of fish)
        Fish fish = (Fish)in.getInstance("fish");

        // 2: doesn't work (fishObj only has access to the methods of an object and can't access the methods of Fish!)
        Object fishObj = null;
        fishObj = (Fish)in.getInstance("fish");

    }

}

先感谢您!

当您将对象引用分配给变量时,对引用变量所做的任何进一步操作都将限于为其类型定义的操作。

因此,您可以将Fish分配给Object变量。 但是,只要使用Object变量,就只能使用Object中定义的方法,例如toString()hashCode()等。

但是您在注释中指出要在两个类中运行类似的方法。 我假设这意味着您的DogFish类具有名称,参数和返回类型相似的方法,例如getLegCount() ,对于Dog ,该方法将返回4 ;对于Fish ,将返回0

当出现这种情况时,您要么必须将这两种类型都声明为另一个具有必需方法的类的子类:

public abstract class Animal {

    public abstract int getLegCount();

}

class Fish extends Animal {

    @Override
    public int getLegCount() {
        return 0;
    }
}

然后, getInstance()的返回类型应该是Animal ,而不是Object 然后将结果放入Animal变量中,然后可以使用getLegCount()方法。

另一种选择是将所需的通用方法定义为接口。 它的工作方式相同,如果预期的Animal类型中没有实现细节,而仅方法定义, Animal可取:

public interface Animal {

    int getLegCount();

}

class Fish implements Animal {
    @Override
    public int getLegCount() {
        return 0;
    }
}

再次,您将从getInstance的返回类型声明为Animal而将变量声明为Animal而不是Object

Java编译器会阻止你使用任何方法fishObj比其他Object ,因为你宣布你的变量fishObj为类型的Object 编译器无法预测在运行时该变量实际上将引用哪种类型的对象,因此它由声明决定。

当然,您和我都可以发现,在调用该方法时, fishObj将保留对Fish的引用,但是通常不总是能够找出这种情况,并且Java编译器不会尝试。

你的演员什么也没做。 它通知编译器该表达式的值实际上是Fish ,但是随后将该值分配给Object类型的变量,就编译器如何查看该变量而言,没有任何改变。 (您的#getInstance的唯一可能影响是,如果#getInstance实际上返回的内容不是FishClassCastException在运行时会收到ClassCastException 。)

您可以使用Java的反射类获取无法通过变量的声明类型访问的对象的方法。 例如:

fishObj.getClass().getMethod("swim").invoke(fishObj);

让我们看一下您的一些代码:

Object fishObj = null;
fishObj = (Fish)in.getInstance("fish");

那么,为什么可以将Fish类的Object分配给数据类型为Object的变量呢? 在Java中,每个类都派生自Object类,因此Object是每个类的超类。 我们可以将子类的对象分配给超类的变量。 这就是您在这里所做的。

fishObj = (Fish)in.getInstance("fish");

您将Fish类的Object分配给变量fishObj。 这是可能的,因为Fish扩展了Object(即使您没有明确指出它)。 因此,我们可以说fishObj具有静态类型Object(在这种情况下为通用数据类型),以及动态类型Fish(分配给变量的Object)。

静态类型定义可访问的方法,而动态类型定义方法的行为方式。

这是什么意思 ? 让我们看一下Object类Oracle文档 我们可以看到它具有多种方法,例如hashCode()或equals()。 如果静态类型为Object,则可以调用所有这些方法,因为每个子类都需要具有这些方法。 因此,无论发生什么情况,通话都不会失败。

假设您的Fish类具有方法swim()并再次查看一些代码。

Object fishObj = new Fish();

那么什么是静态类型,什么是动态类型? 对象将是静态类型,再次获取动态类型。 现在我们不愿进行以下呼叫。

fishObj.swim(); //won't work

为什么会这样 ? 静态类型的类Object没有一个称为swim()的方法。 因此,我们不能肯定地说我们可以分配给变量fishObj的每个对象肯定都实现了mehtod swim()。

总结一下,我们可以说,由于您的静态类型是Object,因此Fish类的特定方法对您隐藏了,以确保对分配给Variable fishObj的Object的调用始终有效。

  Object fishObj = null; fishObj = (Fish)in.getInstance("fish"); 

该对象被强制转换为具有(Fish)的Fish,但由于您的引用是一个Object引用,因此它又被扩展回Object,因此,这是您看到的唯一方法。

((Fish)fishObj ).printFish();

首先,您的实例在= new Instances();中。 应该是静态的,因为您正在静态变量中使用它

您已将Fish对象关联到基本的Java对象

这被称为运行时多态或动态方法调度,是一个在运行时而不是编译时解决对覆盖方法的调用的过程。 更多

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM