对于类型T,Java泛型,方法base()未定义

时间:2016-03-29 19:13:08

标签: java generics types undefined

我试图理解java中的泛型,并尝试这个简单的例子,但不能使它工作;它回来时有错误

  

线程中的异常" main" java.lang.Error:未解决的编译问题:           对于类型T,方法base()未定义           在javaTest.Main.testShape(Main.java:21)           在javaTest.Main.main(Main.java:25)

以下是代码

class Shape{
    int id=1;
    void base(){
        System.out.println("Shape.base()");
    }
}

// unrelated class, but same func name
class OtherShape{
    float id=1.1f;
    void base(){
        System.out.println("OtherShape.base()");
    }
}

public class Main {

    static <T>void testShape(T shape){
        shape.base();
    }

    public static void main(String[] args) {        
        testShape(new Shape() );
        testShape(new OtherShape());        
    }
}

关于如何使其发挥作用的任何想法?

4 个答案:

答案 0 :(得分:8)

在Java中,泛型是在没有外部上下文的情况下编译的,因此代码必须是有效的,而不知道最终它将如何被调用。

声明某些内容<T>意味着您可以传递任何对象,因此T var表示在编译时var应该只是java.lang.Object。因此,var.base()没有意义,因为java.lang.Object不提供名为base()的方法。

例如,您可以通过声明T告诉Shape至少<T extends Shape>,然后您可以传递从Shape继承的任何内容。但是,您的第二个示例仍然不起作用,因为OtherShape未从Shape继承,即它不满足条件<T extends Shape>

要完全修复它,它应该如下所示:

class Shape{
    int id=1;
    void base(){
        System.out.println("Shape.base()");
    }
}

// unrelated class, but same func name
class OtherShape extends Shape{
    float id=1.1f;
    @Override
    void base(){
        System.out.println("OtherShape.base()");
    }
}

public class Main {

    static <T extends Shape> void testShape(T shape){
        shape.base();
    }
    ...
}

向前迈出的一步是让Shape成为一个界面,而是创建实现该界面的每个形状类(TriangleShapeOtherShape,...)。

请注意,在您的示例中,您并不真正需要泛型,如果您稍后需要引用相同的类型,它们非常有用,例如将其从方法返回:

    static <T extends Shape> T testShape(T shape){
        shape.base();
        return shape;
    }

在上面的示例中,您仍然可以将此方法的结果分配给您在参数中传递的相同类型,因为参数类型和返回类型相同(T)。

答案 1 :(得分:1)

我相信你遇到了这个问题,因为你没有将T转换为任何对象类型。试试这样做。

class Shape{
    int id=1;
    void base(){
        System.out.println("Shape.base()");
    }
}

// unrelated class, but same func name
class OtherShape extends Shape{
    float id=1.1f;
    void base(){
        System.out.println("OtherShape.base()");
    }
}

public class Test {

    static void testShape(Shape shape){
        shape.base();
    }

    public static void main(String[] args) {        
        testShape(new Shape() );
        testShape(new OtherShape());        
    }
}

答案 2 :(得分:1)

您收到的实际错误消息是:

The method base() is undefined for the type T

这正是您的问题:您的方法旨在对T类型进行操作,并且您已经说T可以字面上任何对象类型。由于T可能是String,或Number,或其他人创建的其他随机对象,因此您无法假设它将在对象上使用任何特定方法。因此,类型base()的方法T 未定义,因为T不一定是具有base()方法的类型。这有意义吗?

如果您希望在任何具有base()方法的类型上运行,那就是structural typing,其中 Java很遗憾不支持即可。 (Java的类型系统改为nominative。)

接下来最好的事情是定义一个接口来保存你的base()方法,并在你的两个类中实现该接口:

interface ShapeInterface {
  void base();
}

class Shape implements ShapeInterface {
  ...
}

class OtherShape implements ShapeInterface {
  ...
}

但是你不再需要参数多态(即泛型),因为你可以使用普通的subtype polymorphism代替:{{1} }和Shape都支持与OtherShape is-a 关系,您的ShapeInterface方法可以接受testShape并直接与其进行互动:

ShapeInterface

答案 3 :(得分:0)

只有为类实现相同的接口时才能执行此操作。

interface S {
    void base();
}

static void testShape(S shape){
    shape.base();
}