在Java中使用泛型或对象类型作为静态助手类更好吗?

时间:2015-06-19 04:56:56

标签: java list object generics

前几天我正在编写一个程序,要求我:在ArrayList<String>内获取特定对象的频率,删除所有出现的给定项目等,而不是{{{ 1}}接口。我决定编写自己的帮助类,并希望尽可能地使它成为可重用的。我决定将List指定为集合的参数类型,因此我可以将它用于实现List接口的任何类。但是这些类通常使用泛型来定义,我不知道要删除的项的类类型。因此,我必须一般性地定义静态辅助方法,因为静态类不能显式包含泛型类型,或者将要删除的对象的类类型定义为List。我以两种方式实现它,见下文,但我想知道使用一个是否有任何好处。

关于该主题的一些进一步的问题:

  1. 为什么我能够通过在方法头而不是类头中定义泛型类的参数来解决静态上下文中的泛型类型的引用?
  2. 使用此静态方法时,为什么必须在其用法中声明类Type?即Object仍然有效。
  3. 使用Object类类型

    实现
    ListTools_V2.getFrequencyOf(ArrayList<String> items, String s)

    使用泛型实现

    import java.util.List;
    
    /** General utility class for performing frequently needed operations
        on any class implementing the List interface **/ 
    public class ListTools {
    
        public static void removeAllOccurrences(List items, Object o) {
            while(items.contains(o)) {
                items.remove(o);
            }
        }
    
        public static int getFrequencyOf(List items, Object o) {
            int frequency = 0;
            for(Object item : items) {
                if(item.equals(o)) {
                    frequency++;
                }
            }
            return frequency;
        }
    
    }
    

4 个答案:

答案 0 :(得分:1)

两个操作都在给定对象引用和列表中的元素之间进行相等(o)操作,并且相等不限于相同类型的对象,因此不应限制List与列表的类型参数的类型相同。

但是,原始类型不好,因此不应使用原始类型public static void removeAllOccurrences(List<?> items, Object o) public static int getFrequencyOf(List<?> items, Object o) 。当不需要针对任何事物约束类型变量时,您应该使用通配符对其进行参数化:

var text = "1\n2\n3\n4\n5";

答案 1 :(得分:0)

Generic更好,因为它在编译时检测到类型相关的问题。
在运行期间&#34;擦除&#34;发生了,没有&#34;意思&#34;对仿制药。

例如:

List apples = new ArrayList();
apples.add(new Apple());
apples.add(new Mango()); //compiles, but this is wrong
apples.add(new Chair()); //compiles, but this is wrong



你当然必须意识到各种各样的陷阱&#34;通用机制。 我可以轻易想到的例子是:
List<Mango>未展开List<Fruit>,因此您应使用List<? super Fruit>List<? extends Fruit>

你做不了类似的事情:

T.getClassName()

答案 2 :(得分:0)

泛型是实现此类的推荐方法。它们可用于向您的用户(使用此类的任何人)提供一些隐含信息。 例如:

List<Cat> cats = ...;
ListTools.removeAllOccurrences(cats, new Dog());

它没有意义,因为在猫列表中不能有任何狗。但是用户可以执行此代码并想象他已从cat的列表中删除了一些狗。另一方面,通用版本通知用户这个不适当的呼叫。

List<Cat> cats = ...;
ListTools_V2.removeAllOccurrences(cats, new Dog()); // Compile time error because it is pointless

此外,还有性能提升。如果猫的名单包含数以千计的猫,你真的想在大量的猫咪名单中搜索那只狗吗? (包含方法实际上搜索整个List)或者你只是想在编译时避免它? ;)

答案 3 :(得分:0)

你的getFrequencyOf()方法体在两种情况下基本相同,除了在一种情况下你传递原始List而在另一种情况下你将它参数化为接受任何类型。

1 -

public static int getFrequencyOf(List items, Object o) {
        int frequency = 0;
        for(Object item : items) {
            if(item.equals(o)) {
                frequency++;
            }
        }
        return frequency;
    }

此处列表是原始类型。对泛型类型List的引用应该参数化,而不是。但它适用于任何类型的List(整数,长整数,字符串等)

2 -

public static <E> int getFrequencyOf(List<E> items,E o) {
        int frequency = 0;
        for(E item : items) {
            if(item.equals(o)) {
                frequency++;
            }
        }
        return frequency;
    }

此处列表不是原始类型。对泛型类型List的引用应该参数化,它是。这也适用于任何类型的List(整数,长整数,字符串等)