首页 \ 问答 \ Java最佳实践 - 返回对象与通用(Java Best Practices - Returning an Object vs. a Generic)

Java最佳实践 - 返回对象与通用(Java Best Practices - Returning an Object vs. a Generic)

我第一次在学校项目中使用泛型,我遇到了一个关于是否在我的方法中返回对象或我声明的泛型元素的哲学困境。

我的OCD告诉我,我需要始终返回已知类型,但我发现当我将原始数据类型提供给我的类时,这样做会产生一些下游烦恼(当然,对于这个项目,我只会提供原语进入这个班)。

这是我的意思的一个例子:

public class DansPriorityQueue<E extends Comparable> 
{
    private ArrayList<E> tree;

//Here's a method that returns an object
public Object peek() {
    return tree.get(0);
}

//Here's a method that returns the generic type
public E peek() {
    return tree.get(0);
}

(作为一个FYI ..我需要自己实现这个JDK类,但幸运的是我不需要实现真正的PriorityQueue所做的相同接口,所以我可以选择是否要使用Object或者泛型)

我的问题

它让我觉得有点脏,但我很想在这些方法上返回一个Object而不是我的E泛型元素,因为当我返回E时,JUnit强制我强制转换整数值:

DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());

另一方面,当我返回一个对象时,自动装箱不会强迫我施放原始值。

以下是我所面临的问题的更有说服力的描述:

http://www.aschroder.com/2009/10/php-1-java-0-the-method-assertequalsobject-object-is-ambiguous-for-the-type/

- - - - - - 编辑 - - - - - - - -

这是我返回泛型类型并使用自动装箱的Integer对象填充我的列表而没有上面的强制转换时收到的实际错误:方法assertEquals(String,Object,Object)对于DansPriorityQueueTest类型是不明确的

---------结束编辑--------------

问题

  1. 任何人都可以告诉我为什么我应该或不应该返回一个对象而不是我正在使用的通用元素? 两者似乎都有好处和缺点......什么是最佳做法?

  2. 我隐约知道返回一个Object会导致一些转换问题,但我还没有碰到它们......有没有人有一个具体的例子说明这可能是危险的?

  3. 在JDK中,我注意到许多Collections方法默认返回Object。 这是因为Generics是在Java的更高版本中引入的还是Sun Systems的有意识的决定?


I'm using Generics for the first time for a school project and I have come across a philosophical dilemma regarding whether to return objects or my declared generic element in my methods.

My OCD is telling me that I need to always return the known type but I'm finding that doing so creates some downstream annoyances when I feed primitive datatypes into my class (and, of course, for this project I'm only ever feeding primitives into this class).

Here's an example of what I mean:

public class DansPriorityQueue<E extends Comparable> 
{
    private ArrayList<E> tree;

//Here's a method that returns an object
public Object peek() {
    return tree.get(0);
}

//Here's a method that returns the generic type
public E peek() {
    return tree.get(0);
}

(As an FYI.. I'm required to implement this JDK class myself but I am fortunately not required to implement the same interfaces that the real PriorityQueue does so I do have a choice as to whether I want to use the Object or the generic)

My Issue

It makes me feel a little dirty but I'm tempted just to return an Object rather than my E generic element on these methods because when I return E, JUnit forces me to cast my integer values:

DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());

When I return an object on the other hand, the auto-boxing doesn't force me cast my primitive value.

Here's a more eloquent description of the issue I've been facing:

http://www.aschroder.com/2009/10/php-1-java-0-the-method-assertequalsobject-object-is-ambiguous-for-the-type/

------------EDIT----------------

Here's the actual error I receive when I return the generic type and fill my list with the autoboxed Integer object without the cast above: The method assertEquals(String, Object, Object) is ambiguous for the type DansPriorityQueueTest

--------- END EDIT--------------

Questions

  1. Can anyone tell me why I should or should not return an object as opposed to the generic element I'm working with? Both seem to have upsides and downsides... what's the best practice?

  2. I know vaguely that returning an Object can cause some casting issues later on but I've not yet run into them... does anyone have a specific example of how this can be dangerous?

  3. In the JDK, I've noticed that many of the Collections methods return Object by default. Is this because Generics was introduced in a later version of Java or was this a conscious decision by Sun Systems?


原文:https://stackoverflow.com/questions/19863006
更新时间:2022-11-20 18:11

最满意答案

这里有两个方面:

  • 测量Java性能很难 ,请参见此处 。 最有可能的是,你的数字根本就不合理
  • 正如评论所说: 最终的方法只会影响它们是否可以被覆盖。 从理论上讲,这影响运行时性能。 当JIT编译器知道无法覆盖方法时,它可以决定直接内联方法体,而无需任何其他检查。 当该方法不是最终的时,执行基本方法的内联体可能是错误的,因此在执行之前需要进行某种检查。

归结为:如果有的话,使用该关键字有助于在调用方法时避免在运行时进行单个检查。 从这个意义上讲,我们可能正在谈论纳秒的收益。

所以,是的,有一个运行时性能的理论方面,但final的真正用法是向人类读者传达意图


There are two aspects here:

  • Measuring Java performance is hard, see here. Most likely, your numbers are simply not sound
  • As the comments say: final on methods only affects whether they can be overridden. Theoretically, that can affect runtime performance. When the JIT compiler knows that a method can't be overridden, it can decide to directly inline the method body, without any kind of additional checking. When the method isn't final, it could be wrong to execute the inlined body of the base method, therefore some sort of check is necessary before said execution.

Boiling down to: if at all, using that keyword helps avoiding a single check at runtime when the method is invoked. In that sense, we are probably talking nanoseconds of gains.

So, yes, there is a theoretical aspect of runtime performance, but the real usage of final is to communicate intent to human readers.

相关问答

更多
  • 我要说坏习惯,原因如下: 你没有具体说明课堂是否需要最终决定。 你违反了开放/封闭的原则 。 类应该被打开以进行扩展,但是被修改。 最终化的类可能很难用嘲讽框架来测试。 例如: public static void main(String[] args) { final Fruit mockFruit = Mockito.mock(Fruit.class); } private static final class Fruit { } ...会屈服... Exception in thread ...
  • 我认为这一切都与良好的编码风格有关。 当然,你可以编写好的,强大的程序,而不用在任何地方使用很多final修改器,但是当你想到它时... 为所有不应该改变的事情添加final ,简化了您(或下一个程序员,在您的代码上工作)的可能性会误解或误用导致您的代码的思维过程。 至少它应该响起一些钟声,当他们现在想改变你以前不可变的事情。 起初,在你的代码中看到很多final关键字看起来很尴尬,但很快你会停止注意这个单词本身,只会想到, 这个东西永远不会从这一点改变- (你可以从我那里拿走) 我认为这是很好的做法。 我 ...
  • 依次回答您的每一点: 原始变量:只能设一次。 (内存和性能增益) 是的,但没有记忆增益,没有性能增益。 (你假设的表现增益来自于设置只有一次...而不是final ) 对象变量:可以修改,最终适用于对象引用。 是。 (但是,这个描述错过了这一点,这完全符合其他Java语言处理对象/引用对偶性的方式,例如,当对象作为参数传递并作为结果返回时) 字段:只能设一次。 真正的答案是:与变量相同。 方法:不能被覆盖,隐藏。 是。 而且还要注意,这里发生的是final关键字被用在一个不同的句法上下文中来表示一个不同于一 ...
  • 静态方法不能被覆盖,但可以隐藏。 B的ts()方法不会覆盖(不受多态) ts() ,但它会隐藏它的ts() 。 如果您在B(NOT A.ts()或B.ts() ...只是ts() )中调用ts() ),则将调用B中的一个,而不是A.因为这不受多态,在A中调用ts()将不会被重定向到B中的一个。 关键字final将禁用该方法被隐藏。 所以它们不能被隐藏,并且这样做的尝试将导致编译器错误。 希望这可以帮助。 Static methods cannot be overridden but they can be ...
  • 一个你可能想要离开一个非终结者的原因是让子类进行他们自己的更严格的参数检查: public class Subclass extends Superclass { public void setX(int x) { if(x >= 0) throw new IllegalArgumentException("X must be negative"); super.setX(x); } } 当然,这会打破Liskov替代原则 ,因为子类增强了子类型的先决条 ...
  • 救援的接口: public interface IUdpManagerA { void A(); } public interface IUdpManagerB { void B(); } public class UdpManager : IUdpManagerA, IUdpManagerB { public void A() { } public void B() { } } public class UdpManagerFactory { ...
  • 这里有两个方面: 测量Java性能很难 ,请参见此处 。 最有可能的是,你的数字根本就不合理 正如评论所说: 最终的方法只会影响它们是否可以被覆盖。 从理论上讲,这会影响运行时性能。 当JIT编译器知道无法覆盖方法时,它可以决定直接内联方法体,而无需任何其他检查。 当该方法不是最终的时,执行基本方法的内联体可能是错误的,因此在执行之前需要进行某种检查。 归结为:如果有的话,使用该关键字有助于在调用方法时避免在运行时进行单个检查。 从这个意义上讲,我们可能正在谈论纳秒的收益。 所以,是的,有一个运行时性能的理 ...
  • IntelliJ建议变量尽可能为final ,因为它可以防止您意外修改变量。 有时,如果使用static final修饰符,Java编译器也会优化代码。 IntelliJ suggests the variable to be final as far as possible because it will prevent you from accidental modification of the variable. Also sometimes Java compiler optimizes the ...
  • 摘要可以放在类声明中,如 public abstract class Test{ //class implementation } ...和方法声明中,如 public abstract void test(); 关于参数: http : //java.sun.com/docs/books/tutorial/java/IandI/abstract.html Abstract can be put in a class declaration, as in public abstract clas ...
  • 如果使用final,字节码的效率可能没那么高效或低效,因为Java字节码编译器通常在优化方式上做的很少。 效率奖励(如果有的话)将在JIT编译器生成的本机代码中。 从理论上讲,使用final可以为JIT编译器提供一个有助于优化的提示。 在实践中,最近的HotSpot JIT编译器可以通过忽略您的提示来做得更好。 例如,现代JIT编译器通常执行全局分析以查明给定方法调用是否是在应用程序当前加载的类的上下文中调用leaf方法。 此分析比最终提示更准确,运行时甚至可以检测何时加载新类使分析无效...并重新生成受影 ...

相关文章

更多

最新问答

更多
  • 如何在Laravel 5.2中使用paginate与关系?(How to use paginate with relationships in Laravel 5.2?)
  • linux的常用命令干什么用的
  • 由于有四个新控制器,Auth刀片是否有任何变化?(Are there any changes in Auth blades due to four new controllers?)
  • 如何交换返回集中的行?(How to swap rows in a return set?)
  • 在ios 7中的UITableView部分周围绘制边界线(draw borderline around UITableView section in ios 7)
  • 使用Boost.Spirit Qi和Lex时的空白队长(Whitespace skipper when using Boost.Spirit Qi and Lex)
  • Java中的不可变类(Immutable class in Java)
  • WordPress发布查询(WordPress post query)
  • 如何在关系数据库中存储与IPv6兼容的地址(How to store IPv6-compatible address in a relational database)
  • 是否可以检查对象值的条件并返回密钥?(Is it possible to check the condition of a value of an object and JUST return the key?)
  • GEP分段错误LLVM C ++ API(GEP segmentation fault LLVM C++ API)
  • 绑定属性设置器未被调用(Bound Property Setter not getting Called)
  • linux ubuntu14.04版没有那个文件或目录
  • 如何使用JSF EL表达式在param中迭代变量(How to iterate over variable in param using JSF EL expression)
  • 是否有可能在WPF中的一个单独的进程中隔离一些控件?(Is it possible to isolate some controls in a separate process in WPF?)
  • 使用Python 2.7的MSI安装的默认安装目录是什么?(What is the default installation directory with an MSI install of Python 2.7?)
  • 寻求多次出现的表达式(Seeking for more than one occurrence of an expression)
  • ckeditor config.protectedSource不适用于editor.insertHtml上的html元素属性(ckeditor config.protectedSource dont work for html element attributes on editor.insertHtml)
  • linux只知道文件名,不知道在哪个目录,怎么找到文件所在目录
  • Actionscript:检查字符串是否包含域或子域(Actionscript: check if string contains domain or subdomain)
  • 将CouchDB与AJAX一起使用是否安全?(Is it safe to use CouchDB with AJAX?)
  • 懒惰地初始化AutoMapper(Lazily initializing AutoMapper)
  • 使用hasclass为多个div与一个按钮问题(using hasclass for multiple divs with one button Problems)
  • Windows Phone 7:检查资源是否存在(Windows Phone 7: Check If Resource Exists)
  • 无法在新线程中从FREContext调用getActivity()?(Can't call getActivity() from FREContext in a new thread?)
  • 在Alpine上升级到postgres96(/ usr / bin / pg_dump:没有这样的文件或目录)(Upgrade to postgres96 on Alpine (/usr/bin/pg_dump: No such file or directory))
  • 如何按部门显示报告(How to display a report by Department wise)
  • Facebook墙贴在需要访问令牌密钥后无法正常工作(Facebook wall post not working after access token key required)
  • Javascript - 如何在不擦除输入的情况下更改标签的innerText(Javascript - how to change innerText of label while not wiping out the input)
  • WooCommerce / WordPress - 不显示具有特定标题的产品(WooCommerce/WordPress - Products with specific titles are not displayed)