开发者

How do I call a method of a generic type object?

开发者 https://www.devze.com 2023-02-13 10:44 出处:网络
The below code gives me the error: SceneNode.java:17: cannot find symbol symbol: method execute() location:

The below code gives me the error:

SceneNode.java:17: cannot find symbol
symbol  : method execute() location:
class java.lang.Object
                operation.execute();
                         ^ 1 error

Code:

import java.util.LinkedList;
import java.util.Iterator;

public class SceneNode<T>{
    T operation;    
    public SceneNode() {
    }   
    public SceneNode(T operation) {
        this.operation = operation;
    }
    public void setOperation(T operation) {
        this.operation = operation;
    }
    public void doOperation() {
        operation.execute();
    }
}

It's a cut down (for your readability) start of a simple scene graph. The node could be a model, transformation, switch, etc., so I made a variable called operation that's type is开发者_高级运维 defined by the T class variables. This way I can pass a Transformation / Model / Switch object (that has an execute method) and pass it like this:

SceneNode<Transformation> = new SceneNode<Transformation>(myTransformation);

I'm pretty sure having a base class of SceneNode and subclassing for all the various types of nodes would be a better idea (I was trying out generics, only learnt about them recently). Why doesn't this work? I must be missing something fundamental about generics.


It doesn't work because T could be any type, and Java is statically typed. The compiler has no idea whether you'll try to create a SceneNode<String> - then what would execute do?

One option is to create an appropriate interface, e.g.

public interface Executable {
    void execute();
}

and then to constrain T in SceneNode to implement Executable:

public class SceneNode<T extends Executable> {
    ...
}

(I find it a little bit odd that T has to extend Executable rather than implement it in the source code, but then T could end up being an interface itself, so I guess it makes sense.)

Then it should work fine. Of course you could make Executable an abstract superclass instead - or even a (non-final) concrete class - if you wanted, but I would generally prefer to use an interface unless I had some reason not to.


I'm guessing you come from a C++ background.

The compiler has no idea what kind of a thing T might be because you haven't told it.

If you had an interface called, for example, Executable which defines your execute() method, then you would need to do:

public class SceneNode<T extends Executable> {
    // ... 
}

Now, the compiler will know that T is an Executable, and will give you access to all the methods on that interface.


Recently I came across a situation where I had to call a method on generic object. Getting reflection in action worked for me.

public class SceneNode<T>{
    T operation;    
    public SceneNode() {
    }   
    public SceneNode(T operation) {
        this.operation = operation;
    }
    public void setOperation(T operation) {
        this.operation = operation;
    }
    public void doOperation() {
        Method m = operation.getClass().getMethod("execute");
        m.invoke(operation);
    }
}


Java is statically typed language. You must know the type at compile-time in order to be able to invoke a method. Instead of a subclass you can have an interface Executable that defines the execute() method. T (without any <T extends SomeClass>) has only the methods defined by java.lang.Object.

0

精彩评论

暂无评论...
验证码 换一张
取 消