2011-01-24 52 views
5

我想编写一个单一的方法add()在Java中,这可能会添加整数,字符串等。泛型将帮助我。为什么在Java中泛型?它与超载有何不同?

我无法理解泛型的最终目的。我感到很困惑。

泛型vs重载?

public Integer add(Integer i, Integer j){return i+j;} 
public String add(String i, String j){return i+j;} 
public <T> T add(T i, T j){return i+j;} //this gives me error. 

请让我出去吧。

谢谢。

+1

当您执行Integer i + Integer j时,实际上并没有添加Integers。 “整数”不支持“+”运算符。他们将unboxed放入`ints`,而不是直接添加为`Integer`对象。您不能添加通用对象,因为对象不支持`+`运算符。 “字符串”是一种特殊情况,支持`+`。 – 2011-01-24 13:30:41

+4

你会调用你的两个例子`add`的唯一原因是因为它们使用`+`运算符,这实际上是一种无意义的相似性,因为它对Strings和Integers完全不同。名称方法基于它们从调用者的角度实际做了什么 - 在这种情况下`sum`和`concatenate`将是好名字。 – 2011-01-24 13:35:16

回答

4

我想在Java中编写一个方法add(),它可以添加整数,字符串等。泛型将帮助我。

NO

泛型用于类型安全大多是在编译时。

只能指定一个类型的集合添加

List<String> lst;

将接受字符串而已,没有子类[例如,如果存在]没有字符串的超

+1

`只接受字符串,没有字符串的超类没有子类` - 这是不正确的。像`void add42(List list){list.add(42);}`是完全有效的。 – maaartinus 2011-01-24 14:31:11

5

泛型可能帮助,这里的问题是+操作只是针对java基元和String而定义的,但不适用于一般类型。而在Java中,我们不能重载操作符(就像我们可以在C++中做的那样)。

没有泛型一个实际的解决办法是:

public Integer add(Integer a, Integer b) { return a + b; } // sum of a and b 
public String add(String a, String b) { return a + b; }  // concatenate operation! 
public MyType add(MyType a, MyType b) { return a.add(b); } // requires add operation 
+2

你的第二段不正确。返回类型不是Java中方法签名的一部分,只是名称和参数类型。只要参数不同,您可以有不同的返回类型。或者我误解了你写的内容? – 2011-01-24 13:35:56

+0

重载不确定返回类型。重载的返回类型不一定相同。 – Manoj 2011-01-24 13:39:28

2

泛型是好的,因为如果处理得当它可以让你推广了一些你写的代码。就编写软件而言,您希望尽量减少不必要的代码,并尽可能多地重用代码。

通过使用超载的方法,你必须写出每一个重载,而与泛型,你只需要做一次。泛型在您操作集合的情况下工作良好,因为您在一组集合上执行某些常见操作。在某些情况下,如果您希望采用更加自定义的方法来处理某些情况,那么您可能必须重载方法,但如果可以在多个位置使用它,我会将其写成泛型编写的目标。

1

这正是泛型的一点。 你不想实现一个可以接受一切的方法。坦白地说,你可以随时实现方法

add(Object obj)

,并传递给它的整数,字符串,布尔......但在大多数情况下,你不想要这个。该方法必须处理参数,因此它应该知道参数的类型。这是,如果你想使接收字符串和整数实现2种方法方法添加的原因:

add(String s); 
add(int i); 

现在你不能送布尔加()方法:这样的方法并不存在。

还可以实现通用的方法

<T> void add(T arg);

,并称之为:this.<String>add("hello");this.<Integer>add(123);

在这种情况下this.<String>add(123);导致编译错误。

3
public Integer add(Integer i, Integer j){return i+j;} 
public String add(String i, String j){return i+j;} 
public <T> T add(T i, T j){return i+j;} //this gives me error. 

虽然这些方法看起来几乎相同,但在这种情况下,泛型无法提供帮助。考虑到这一点:

public <T> T add(T i, T j){return i+j;} 
... 
add(new Object(), new Object()); 

这是什么意思添加到只是经常Object一起?不,+不支持Object,并且不支持许多其他可替代T的类型。

在创建一个通用的方法<T> T add(T i, T j),泛型方法仅限于被允许在泛型类型参数T,这实际上意味着唯一的东西,你可以用Object做方法和操作。您正尝试使用方法/操作+,即而不是您可以使用Object进行的操作。

我们可以尝试通过找到一个通用的基类StringInteger来解决这个问题,该基类支持我们在泛型方法体中使用的所有方法和操作。 如果有这样一个共同的基类XXXXX那支+运营商,我们可以这样做:

public <T extends XXXXX> T add(T i, T j) { return i+j; } 

但是,没有公共基类XXXXX支持我们想要做的一切泛型方法(+),所以泛型不能用来解决这个问题。

1

如何通过通用接口的方法:

interface Adder<T> { 
    T add(T first, T second); 
} 

而一个管理器类:

public class AdderManager{ 

    public <T> AdderManager putAdder(final Class<T> clazz, 
     final Adder<? extends T> adder){ 
     adders.put(clazz, adder); 
     return this; 
    } 

    @SuppressWarnings("unchecked") 
    public <T> Adder<T> getAdder(final Class<T> clazz){ 
     return (Adder<T>) adders.get(clazz); 
    } 

    private final Map<Class<?>, Adder<?>> adders = 
     new HashMap<Class<?>, Adder<?>>(); 

} 

现在,您可以注册和使用自定义的加法器不同类别:

final AdderManager manager = new AdderManager(); 
manager 
.putAdder(String.class, new Adder<String>(){ 

    @Override 
    public String add(final String first, final String second){ 
     return first.concat(second); 
    } 
}) 
.putAdder(Integer.class, new Adder<Integer>(){ 

    @Override 
    public Integer add(final Integer first, final Integer second){ 
     return first + second; 
    } 
}) 
.putAdder(List.class, new Adder<List<?>>(){ 

    @Override 
    public List<?> add(final List<?> first, final List<?> second){ 
     final List<Object> newList = new ArrayList<Object>(); 

     return newList; 
     } 
}); 

现在你可以使用像这样的加法器:

String addedString = manager.getAdder(String.class).add("abc", "def"); 

@SuppressWarnings("unchecked") // this is necessary because of 
           // the generic <Integer> type 
List<Integer> addedList = manager 
          .getAdder(List.class) 
          .add(
           Arrays.asList(1,2,3), 
           Arrays.asList(4,5,6) 
          ); 
1

java中的泛型只添加转换为字节码。

该代码将是相同的,除了铸造。

所以两种结构:

List list1 = new ArrayList(); 
List<String list2 = new ArrayList<String>(); 
.... 
String string1 = (String) list1.get(0); 
String string2 = list2.get(0); 

也在做同样的。

5

其他人指出为什么这不起作用。让我补充一下,我认为你误解了Java泛型的用途。也许你对C++模板或C宏扩展很熟悉,这两种模式都类似于泛型,但却是非常不同的东西。泛型实际上是关于类型安全性和避免混乱的演员表。你告诉编译器某个集合包含了Strings,然后它知道你放入或取出的所有东西都必须是一个String。你可以通过编译时检查你放入的东西,并且可以将一些东西保存在你取出的东西上。

它不会导致编译器根据类型生成不同的代码。泛型不是避免编写相同函数的“int”版本和“浮点”版本的简短方式,就像宏或C++模板将为您所做的那样。你可以通过让两个类实现相同的功能,但一个使用int而另一个使用浮点数来获得所需的独特行为。但是,您可以使用没有泛型的面向对象技术来实现这一点。如果使用“非泛型”面向对象技术无法获得所需的独特行为,那么您也无法使用泛型来实现。

相关问题