简体   繁体   中英

Cast an Object into a class

I'm trying to cast an Object into a class instance. The Object of the classes instance should of course inherit all the methods.

So here's my problem in sample code (2) because I can't exactly explain what I mean:

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");

    }

}

Thank you in advance!

When you assign an object reference to a variable, any further operations you'll do with the reference variable are limited to the ones that are defined for its type.

So you can assign a Fish to an Object variable. But as long as you use the Object variable, you can only use methods that are defined in Object , such as toString() , hashCode() etc.

But you noted in your comments that you want to run a similar method in two classes. I assume that means your Dog and Fish classes have a method with similar names, parameters and return type, for example getLegCount() which would return 4 for Dog and 0 for Fish .

When this situation arises, you either have to declare both types as subclasses of another class, that has the required method:

public abstract class Animal {

    public abstract int getLegCount();

}

class Fish extends Animal {

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

And then the return type from your getInstance() should be Animal , not Object . And you put the result in an Animal variable, and then you can use the getLegCount() method.

Another option is to define the required common methods as an interface. It works the same way, and is preferable if there are no implementation details in the expected Animal type, only method definitions:

public interface Animal {

    int getLegCount();

}

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

Again, you would declare your return type from getInstance as Animal and your variable as Animal rather than Object .

The java compiler will prevent you from using any methods on fishObj other than those of Object , because you declared your variable fishObj to be of type Object . The compiler can't predict what type of object will actually be referenced by that variable at run time, so it goes by the declaration.

Of course, you and I can figure out that fishObj will be holding a reference to a Fish at the moment the method is invoked, but figuring such things out in general is not always possible, and the Java compiler doesn't try.

Your cast does nothing. It informs the compiler that the value of the expression is in fact Fish , but then you assign that value to a variable of type Object , and nothing has changed in terms of how the compiler views that variable. (The only possible impact of your cast would be if #getInstance actually returned something that was not a Fish , in which case you'd get a ClassCastException at runtime.)

You can use Java's reflection classes to get at methods of the object that are not accessible via the variable's declared type. Eg:

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

Let's take a look at some of your code:

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

So why can you assign an Object of the class Fish, to a variable with the datatype Object ? In Java, every class derives from the class Object, so Object is the superclass of every class. We can assign objects of a subclass, to variables of a superclass. That's just what you are doing here.

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

You assign an Object of the class Fish to the variable fishObj. This is possible because Fish extends Object (even though you didn't note it explicitly). So we could say that fishObj has the static type Object (the general datatype in this case), and the dynamic type Fish (the Object which is assigned to the variable).

The static type defines which methods are accessible, while the dynamic type defines how the methods are behaving.

Now what does that mean ? Lets take a look at the Oracle Documentation for the class Object . We can see that it has a variety of methods like hashCode() or equals(). All these Methods can be called if the static type is Object, because every subclass needs to have these methods. So no matter what happens, the call shouldn't fail.

Let's say that your class Fish has the method swim() and take a look at some code again.

Object fishObj = new Fish();

So whats the static and what's the dynamic type here ? Object would be the static type, fish the dynamic type again. Now we wan't to do the following call.

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

Why is that so ? The class of the static type, Object, doesn't have a method called swim(). So we cannot say for sure that every Object we could assign to the variable fishObj would certainly have the mehtod swim() implemented.

Summed up we can say, that since your static type is Object, specific methods of the class Fish are being hidden from you, to ensure that calls on the Object assigned to the Variable fishObj will always work.

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

The object is cast to a Fish with (Fish), but as your reference is an Object reference, it is then widened back to Object, hence those are the only methods you see.

((Fish)fishObj ).printFish();

First of all ,your Instances in = new Instances(); should be static, since you are using it in a static variable

You have assgineed an Fish object to a basic java Object

This is called Runtime polymorphism or Dynamic Method Dispatch is a process in which a call to an overridden method is resolved at runtime rather than compile-time. More

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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