括号内的Javagenerics方法参数类型与外部括号

之间有什么区别:

static void findMax(LinkedList list){...} 

和:

 static  void findMax(LinkedList list){...} 

既然两者都有效,我想知道两者之间是否有任何重大差异,建议采用哪种方法。

主要区别在于,在第二个版本中,您可以访问类型T而在第一个版本中,您不能访问。

例如,您可能希望返回链接到T的内容(例如,返回T而不是void):

 static  T findMax(LinkedList list){...} 

或者您可能需要创建一个新的Ts列表:

 static  void findMax(LinkedList list){ List copyAsArrayList = new ArrayList<> (list); //do something with the copy } 

如果您不需要访问T ,则两个版本在function上都是等效的。

如果您只关心findMax接受符合特定条件的列表(在您的情况下是扩展Number的类型的List),则应使用第一个

 static Number findMax(LinkedList list) { Number max = list.get(0); for (Number number : list) { if (number > max) { max = number; } } return max; } 

此方法返回Number 。 例如,如果您拥有一个扩展Number的类,并且您希望稍后在此方法的结果上使用某些特殊方法,则可能会出现问题。


当您计划在方法体中使用精确类型T ,方法参数或方法的返回类型时,应使用第二个

 static  T findMax(LinkedList list, T currentMax) { T max = currentMax; for (T number : list) { if (number > max) { max = number; } } return max; } 

结论:

在function上,它们几乎相同, 只是具有未知类型( ? )的列表无法修改。

这是区别

 static void findMax(LinkedList list){ list.add(list.get(0)); <-- compile error } 

你不能在列表中添加任何空格。

同时编译时没有错误或警告

 static  void findMax2(LinkedList list){ list.add(list.get(0)); <-- no error } 

就签名的权力而言,两者完全相同。 我的意思是,如果您有任何使用第二个签名的API,您可以将其替换为使用第一个签名的API,并且使用该API的任何代码将完全像以前一样工作,并且任何以前无效的代码也行不通。 所以对于外部代码,两者之间没有区别。

你如何将第二个的实现改为第一个? 其他人用list.add(list.get(0));指出了例子list.add(list.get(0)); 。 具有第一个签名的API是否可以执行该操作? 是。 这很简单。 只需让第一个调用第二个(将第二个调用为内部私有方法)。 这称为捕获助手 。 你可以这样做的事实certificate,两者都可以从外部代码的角度“做”相同的事情(通过任何内部手段“做”,包括调用其他方法)。

 static void findMax(LinkedList list){ findMaxPrivate(list); } static static  void findMaxPrivate(LinkedList list){ list.add(list.get(0)); } 

我认为关于参数T在第二种方法体中的访问已经有了很好的答案。

我想补充一点,如果您有许多需要按类型链接的参数,则需要第二种表示法。 例:

 static  int getPosition(LinkedList list, T element){...} 

如果不使用generics类型参数无法强制执行上述约束。