11

我有这样的情况:

我有一个看起来像这样的类:

public class TestClass<T> {
   // class body here...
}

我有一个看起来像这样的方法:

public class AnotherTestClass<K> {
     private TestClass<K> testClass;

     public AnotherTestClass(TestClass<K> testClass) {
         this.testClass = testClass;
     }

     public K testMethod() {
         //call methods on param object and pass a value of the same type as testClass.
         K returnVal = this.testClass.doSomething();
         return returnVal;
     }
}

现在我有一个工厂方法,它返回一个类型的对象TestClass<?>

public TestClass<?> sampleFactory(int i) {
       if( i==1 ) 
           return new TestClass<Integer>();
       if( i==2 ) 
           return new TestClass<Double>();
       if( i==3 ) 
           return new TestClass<String>();
}

但我不能使用该方法将参数传递给我的testMethod. 这有什么解决办法?

目前我正在编写if else链块以获得正确的实例。if else我知道这是不正确的,因为当有多个参数(如上面的参数)时编写块是不切实际的。

请为此提出一种优雅的方式。

编辑:示例用法:

package my;

import java.util.ArrayList;
import java.util.List;

public class GenericsSpike {
    public static void main( String[] args ) {
        TestClass1< ? > tc1 = new TestClass1<Integer>( 123 );
        TestClass2< ? > tc2 = new TestClass2<Integer>( 123 );
        AnotherTestClass< ? > atc = new AnotherTestClass<Integer>( tc1, tc2 );
        atc.testMethod();
    }
}

class TestClass1<T> {
    private T value;

    TestClass1( T val ) {
        value = val;
    }

    // class body here...

    public T getValue() {
        return value;
    }
}

class TestClass2<T> {
    private T value;

    TestClass2( T val ) {
        value = val;
    }

    // class body here...

    public T getValue() {
        return value;
    }
}

class AnotherTestClass<K> {
    public TestClass1<K> testClass1, testClass2;

    public AnotherTestClass( TestClass1<K> testClass, TestClass2<K> testClass2 ) {
        this.testClass1 = testClass;
    }

    public K testMethod() {
        //Any logic can come here.
        System.out.println( testClass1.getValue() );
        System.out.println( testClass2.getValue() );
        return testClass1.getValue();
    }
}

在这种情况下,如果tc1并且tc2来自创建这些对象的工厂,我想知道创建实例的体面方法是什么AnotherClass

4

4 回答 4

5

您的问题在于这种方法:

public TestClass<?> sampleFactory(int i) {

通配符类型的?意思是“某种类型,但我不知道是什么”。因此,您可以获得 type 的值TestClass<?>,但这对您没有用,因为您无法与类型进行有意义的交互?——您无法创建 type 的值?(null 除外)并且您无法调用 type 上的方法?(的方法除外java.lang.Object)。

你真正想要的是这样的:

public <T> TestClass<T> sampleFactory(TypeToken<T> typeToken) {

也就是说,如果你希望你的工厂返回由不同类型参数化的值,你需要给它一些东西来告诉它你想要什么类型。不幸的是,int这还不够——可能知道这i==1意味着类型将为Integer,但编译器并不知道这一点。

您对问题的描述有点含糊,我无法理解您真正想要实现的目标,但我猜您真正需要的是超级类型令牌之类的东西,或者可能是 Guava 之类的东西ClassToInstanceMap

于 2013-08-10T22:31:36.540 回答
2

一种可能的解决方案是使用原始AnotherTestClass类型

public class A {
    public static void main(String[] args) {
        TestClass<?> tc = new TestClass<Integer>();
        AnotherTestClass atc = new AnotherTestClass();
        atc.testMethod(tc);
    }
}

class TestClass<T> {

// class body here...

}

class AnotherTestClass<K> {

    public void testMethod(TestClass<K> param) {
    }
}

编译得很好。但在一般情况下使用原始类型并不是一个好主意

于 2013-08-10T14:26:09.360 回答
0

Java 文档说:

从其超类或超接口继承的原始类型 C 的构造函数、实例方法或非静态字段 M 的类型是在对应于 C 的泛型声明中擦除其类型。原始类型 C 与其在对应于 C 的泛型声明中的类型相同。

即使方法的类型签名不使用类本身的任何类型参数,类型擦除也会出现,

这就是你的方法,

public method testMethod(TestClass param) {
}

您的返回类型对象的工厂方法TestClass<?>不能用于上述方法。

于 2013-08-10T14:35:13.090 回答
0

使用这个,您将能够将参数传递给您的testMethod

package stackoverflow;

public class Func {

    static class TestClass<T> {
    }

    static class AnotherTestClass {

        public <K> TestClass<K> testMethod(TestClass<K> param) {
            return param;
        }
    }

    static class Factory {

        public static <E> TestClass<E> sampleFactory(int i) {
            if (i == 1)
                return (TestClass<E>) new TestClass<Integer>();
            if (i == 2)
                return (TestClass<E>) new TestClass<Double>();
            if (i == 3)
                return (TestClass<E>) new TestClass<String>();
            throw new IllegalArgumentException();
        }
    }

    public static void main(String[] args) {
        new AnotherTestClass().testMethod(Factory.sampleFactory(1));
    }

}
于 2013-08-10T14:57:04.170 回答