简体   繁体   English

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

[英]How do I call a method of a generic type object?

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.节点可以是模型、转换、开关等,所以我创建了一个名为operation的变量,它的类型由T类变量定义。 This way I can pass a Transformation / Model / Switch object (that has an execute method) and pass it like this:这样我就可以传递一个Transformation / Model / Switch对象(它有一个execute方法)并像这样传递它:

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).我很确定有一个SceneNode基类和所有各种类型节点的子类会是一个更好的主意(我正在尝试泛型,最近才了解它们)。 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.它不起作用,因为T可以是任何类型,而 Java 是静态类型的。 The compiler has no idea whether you'll try to create a SceneNode<String> - then what would execute do?编译器不知道您是否会尝试创建SceneNode<String> - 那么会execute什么?

One option is to create an appropriate interface, eg一种选择是创建一个适当的界面,例如

public interface Executable {
    void execute();
}

and then to constrain T in SceneNode to implement Executable :然后在SceneNode约束T以实现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.) (我觉得T必须扩展Executable而不是在源代码中实现它有点奇怪,但是T最终可能会成为一个接口本身,所以我想这是有道理的。)

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.当然,如果您愿意,您可以使Executable成为抽象超类 - 甚至是(非最终)具体类 - 但我通常更喜欢使用接口,除非我有理由不这样做。

I'm guessing you come from a C++ background.我猜你来自 C++ 背景。

The compiler has no idea what kind of a thing T might be because you haven't told it.编译器不知道 T 可能是什么东西,因为你没有告诉它。

If you had an interface called, for example, Executable which defines your execute() method, then you would need to do:例如,如果您有一个名为Executable的接口,它定义了您的execute()方法,那么您需要执行以下操作:

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.现在,编译器会知道 T 是一个Executable ,并且会让您访问该接口上的所有方法。

Java is statically typed language. Java 是静态类型语言。 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.您可以使用定义execute()方法的接口Executable来代替子类。 T (without any <T extends SomeClass> ) has only the methods defined by java.lang.Object . T (没有任何<T extends SomeClass> )只有java.lang.Object定义的方法。

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

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

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