【问题标题】:Java generics: multiple generic parameters?Java泛型:多个泛型参数?
【发布时间】:2010-12-18 02:08:28
【问题描述】:

我想知道是否可以编写一个接受多种泛型类型的函数,如下所示:

public int void myfunction(Set<T> a, Set<T> b) {
    return 5;
}

Set<Integer> setA = new HashSet<Integer>();
Set<String> setB = new HashSet<String>();
int result = myfunction(setA, setB);

这行得通吗?每个参数中的泛型是否意味着每个参数必须具有与泛型相同的类型 T?

【问题讨论】:

    标签: java generics parameters


    【解决方案1】:

    是的 - 有可能(尽管不是您的方法签名),是的,您的签名类型必须相同。

    使用您提供的签名,T 必须与呼叫站点的单一类型(例如String Integer)相关联。但是,您可以声明采用多个类型参数的方法签名

    public <S, T> void func(Set<S> s, Set<T> t)
    

    请注意,在上面的签名中,我已经在签名本身中声明了 ST 类型。因此,它们与与包含该函数的类或接口相关联的任何泛型类型不同且独立。

    public class MyClass<S, T> {
       public        void foo(Set<S> s, Set<T> t); //same type params as on class
       public <U, V> void bar(Set<U> s, Set<V> t); //type params independent of class
    }
    

    您可能想看看java.util 包中集合类的一些方法签名。泛型确实是一个相当复杂的主题,尤其是在考虑通配符(? extends? super)时。例如,通常情况下,可能采用Set&lt;Number&gt; 作为参数的方法也应该接受Set&lt;Integer&gt;。在这种情况下,您会看到这样的签名:

    public void baz(Set<? extends T> s);
    

    已经有很多关于 SO 的问题供您查看!

    不确定从函数返回 int 的意义何在,尽管您可以根据需要这样做!

    【讨论】:

    • 我不明白为什么这两个问题都是“是”(具体来说,为什么“是”对“这会起作用吗?”)。上面的函数(我知道,用 int-return 设计的)不会接受这两种不同的类型,因为它期望两个参数具有相同的泛型类型 T,对吧?
    • 抱歉 - 我的意思是“是的,这是可能的”和“是的,在您定义的签名中,类型必须相同”
    【解决方案2】:

    您可以在一个类型或方法上声明多个类型变量。例如在方法上使用类型参数:

    <P, Q> int f(Set<P>, Set<Q>) {
      return 0;
    }
    

    【讨论】:

      【解决方案3】:

      更重要的是,您可以继承泛型 :)

      @SuppressWarnings("unchecked")
      public <T extends Something<E>, E extends Enum<E> & SomethingAware> T getSomething(Class<T> clazz) {
              return (T) somethingHolderMap.get(clazz);
          }
      

      【讨论】:

        【解决方案4】:

        您可以采用以下方法之一:

        1) 基本,单一类型:

        //One type
        public static <T> void fill(List <T> list, T val) {
        
            for(int i=0; i<list.size(); i++){
                list.set(i, val);
            }
        
        }
        

        2) 多种类型:

        // multiple types as parameters
        public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {
        
            return val1+" "+val2;
        
        }
        

        3) 下面将引发编译器错误,因为'T3 不在函数声明部分中使用的泛型类型列表中。

        //Raised compilation error
        public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {
            return 0;
        }
        

        正确:编译良好​​p>

        public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {
            return 0;
        }
        

        示例类代码:

        package generics.basics;
        
        import java.util.ArrayList;
        import java.util.List;
        
        public class GenericMethods {
        
        /*
         Declare the generic type parameter T in this method. 
        
         After the qualifiers public and static, you put <T> and 
         then followed it by return type, method name, and its parameters.
        
         Observe : type of val is 'T' and not '<T>'
        
         * */
        //One type
        public static <T> void fill(List <T> list, T val) {
        
            for(int i=0; i<list.size(); i++){
                list.set(i, val);
            }
        
        }
        
        // multiple types as parameters
        public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {
        
            return val1+" "+val2;
        
        }
        
        /*// Q: To audience -> will this compile ? 
         * 
         * public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {
        
            return 0;
        
        }*/
        
         public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {
        
            return null;
        
        }
        
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(10);
            list.add(20);
            System.out.println(list.toString());
            fill(list, 100);
            System.out.println(list.toString());
        
            List<String> Strlist = new ArrayList<>();
            Strlist.add("Chirag");
            Strlist.add("Nayak");
            System.out.println(Strlist.toString());
            fill(Strlist, "GOOD BOY");
            System.out.println(Strlist.toString());
        
        
            System.out.println(multipleTypeArgument("Chirag", 100));
            System.out.println(multipleTypeArgument(100,"Nayak"));
        
        }
        
        }
        

        //类定义结束

        样本输出:

        [10, 20]
        [100, 100]
        [Chirag, Nayak]
        [GOOD BOY, GOOD BOY]
        Chirag 100
        100 Nayak
        

        【讨论】:

          【解决方案5】:

          a 和 b 必须都是相同类型的集合。但是没有什么能阻止你写作

          myfunction(Set<X> a, Set<Y> b)
          

          【讨论】:

          • 除非你需要像我的回答那样在签名中声明类型参数
          • 你不应该接受错误的答案。 @oxbow_lakes 是第一个做对的人。
          【解决方案6】:

          在您的函数定义中,您将集合 a 和 b 限制为相同的类型。你也可以写

          public <X,Y> void myFunction(Set<X> s1, Set<Y> s2){...}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-10-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多