我有以下示例:

class bounds
{
  private StringBuilder str = new StringBuilder();

  public <Type> void add (Type value)
  {
    add_specific (value);
    str.append (String.format("%n"));
  }

  private <Type extends Number> void add_specific (Type value)
  {
    str.append (value);
  }

  public String toString () { return str.toString(); }

  public static void main (String[] args)
  {
    bounds test = new bounds();
    test.add (new Integer (42));
    System.out.print (test.toString());
  }
}


当我尝试编译它时,出现以下错误:

bounds.java:7: error: method add_specific in class bounds cannot be applied to given types;
    add_specific (value);
    ^
  required: Type#1
  found: Type#2
  reason: inferred type does not conform to declared bound(s)
    inferred: Type#2
    bound(s): Number
  where Type#1,Type#2 are type-variables:
    Type#1 extends Number declared in method add_specific(Type#1)
    Type#2 extends Object declared in method add(Type#2)
1 error

This looks to me as if the original type of the argument passed to the add method gets lost in the body of add. How can I preserve the type so that the correct add_specific method can be chosen?

Update

I have simplified my example, because I thought it would be easier to understand. But it seems to me that most people do not understand the reason why it contains a generic and a specific function. So I paste a more advanced example. Maybe this makes the reasons more obvious:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

class bounds
{
  private StringBuilder str = new StringBuilder();

  public <Type> void add (Type value)
  {
    add_specific (value);
    str.append (String.format("%n"));
  }

  private <Type extends Number> void add_specific (Type value)
  {
    str.append (value);
  }

  private void add_specific (String value)
  {
    str.append ('"');
    for (int i = 0; i < value.length(); i++) {
      char ch = value.charAt(i);
      switch (ch) {
      case '\\': str.append ("\\\\"); break;
      case '"': str.append ("\\\""); break;
      default: str.append (ch);
      }
    }
    str.append ('"');
  }

  private static DateFormat iso8601
    = new SimpleDateFormat("'\"'yyyy-MM-dd'T'HH:mm:ssZ'\"'");

  private void add_specific (Date date)
  {
    str.append (iso8601.format(date));
  }

  public String toString ()
  {
    return str.toString();
  }

  public static void main (String[] args)
  {
    bounds test = new bounds();

    test.add (new Integer (42));
    test.add ("42");
    test.add (new Date());

    System.out.print (test.toString());
  }
}


我有一个称为add的通用函数。该通用函数执行通用操作,并调用特定函数执行特定操作。问题在于,用于选择特定功能的类型在通用功能中丢失了。问题是如何解决这个问题?如何编写通用函数,以便仍然可以在通用函数的主体中选择正确的特定函数?

最佳答案

在我看来,好像传递给add方法的参数的原始类型在add的正文中丢失了。


好吧,类型擦除意味着Type在执行时不会被知道,但这不是您遇到编译时错误的直接原因。您可以使用任何类型调用add-而只能使用与add_specific兼容的类型调用Number。因此,例如,请考虑:

// TODO: Fix your naming to meet Java naming conventions
bounds b = new bounds();
b.<String>add("foo");


您希望如何呼叫add_specificString不扩展Number

(顺便说一句,命名类型参数Type也是一个很糟糕的主意-将它与java.lang.reflect.Type混淆太容易了。)

选项:


extends Number中添加绑定到Typeadd
删除Typeadd_specific的边界


编辑:好的,听起来您只给了我们一半的图片-您希望基于Type在执行时执行重载解析。这是行不通的,有两个原因:


Java总是在编译时执行重载解析
类型擦除意味着在执行时不存在任何信息,因此无论如何都不能做出过载决策。如果需要这些信息,则需要另一个Class<Type>类型的参数。

关于java - 如何在Java中保留类型变量的原始类型?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19251576/

10-11 22:54
查看更多