如何调用泛型类型对象的方法?

Cal*_*lum 10 java generics

以下代码给出了错误:

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

码:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的场景图的缩减(为了您的可读性).节点可以是模型,转换,开关等,所以我创建了一个变量,称为operation类型由T类变量定义.这样我就可以传递一个Transformation/ Model/ Switch对象(有一个execute方法)并像这样传递它:

SceneNode<Transformation> = new SceneNode<Transformation>(myTransformation);
Run Code Online (Sandbox Code Playgroud)

我很确定SceneNode为所有各种类型的节点都有一个基类和子类是一个更好的主意(我正在尝试泛型,最近才了解它们).为什么这不起作用?我必须遗漏一些关于泛型的基本知识.

Jon*_*eet 10

它不起作用,因为T可以是任何类型,Java是静态类型的.编译器不知道你是否会尝试创建一个SceneNode<String>- 然后会execute做什么?

一种选择是创建适当的接口,例如

public interface Executable {
    void execute();
}
Run Code Online (Sandbox Code Playgroud)

然后约束TSceneNode落实Executable:

public class SceneNode<T extends Executable> {
    ...
}
Run Code Online (Sandbox Code Playgroud)

(我发现它有点奇怪,T必须扩展 Executable而不是在源代码中实现它,但T最终可能最终成为一个接口本身,所以我想它是有道理的.)

那它应该工作正常.当然你可以Executable改为创建一个抽象超类 - 甚至是一个(非最终的)具体类 - 如果你愿意,但我通常更喜欢使用一个接口,除非我有一些理由不这样做.


dty*_*dty 8

我猜你是来自C++背景.

编译器不知道T可能是什么样的东西,因为你没有告诉它.

如果您有一个名为(例如,Executable定义了您的execute()方法)的接口,那么您需要执行以下操作:

public class SceneNode<T extends Executable> {
    // ... 
}
Run Code Online (Sandbox Code Playgroud)

现在,编译器将知道T是一个Executable,并且将允许您访问该接口上的所有方法.


App*_*tri 5

最近我遇到了一种情况,我必须调用通用对象的方法。在行动中反思对我来说很有效。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)