【问题标题】:Benefits of Avoiding 'new' Keword When Creating Object in Java在 Java 中创建对象时避免使用“new”关键字的好处
【发布时间】:2014-12-19 11:54:36
【问题描述】:

我发现一些博客建议避免使用 new 关键字,而 创建一个类的对象。不使用 new 关键字创建对象的一些示例是-

SampleObject obj = Class.forName("com.example.SampleObject").newInstance();

或者使用clone()方法——

SampleObject obj1 = new SampleObject();  
SampleObject obj2 = obj.clone();

然后here我找到了一些不用new关键字创建对象的好例子

我可以理解“工厂”模式的优点,同时避免在代码的主要部分使用 new 关键字。如果我没有使用任何设计模式(用于创建对象),那么在没有 new 关键字的情况下创建对象有什么好处吗?或者没有new创建对象的原因是什么?

【问题讨论】:

  • 我认为,这都是关于 static 创建对象的方法。类似于 Paths.get 的标准库。
  • 那你打算如何创建对象?你不打算传递字符串来创建你用来加载你的类的对象吗?

标签: java oop instance instantiation object-create


【解决方案1】:

您在博客中读到的内容一定是关于工厂方法和类似技术的,它们并没有避免 new,而是将其置于更灵活的 API 之后。

new 运算符绝对没有总体缺点。它已经并将继续是任何 Java 代码的主要内容,并且是实际创建对象的最自然方式,而不是满足更通用的关注点,例如“为我提供 API 的入口点”。

在不涉及new 的情况下创建对象的所有其他技术都是专用工具(克隆、反序列化等)。

【讨论】:

  • 其他技术一定效率较低吧?我的意思是在幕后,他们必须都在做 new 在内部所做的事情。我正在浏览newInstance0()的java源代码,里面有很多代码:)。是否有任何其他技术提供比new 更好的性能?
  • 由于new是运行时最激进的优化目标,包括根本不分配对象的逃逸分析,所以基本上不可能比new更高效.与往常一样,使用标准习语并享受 HotSpot 已成为的优化怪物的好处。
  • 实际上,通过池化实例,您可以获得比 new 更高的效率。
  • @Andres 上下文“在创建实例时更有效”。
  • 是的,同意。但是,我认为说“新运营商绝对没有总体缺点”有点误导。我已经看到许多问题只能通过用不同的东西(单例、DI、池等)替换 new 来解决
【解决方案2】:

复杂对象

一般来说,您可以考虑避免new 用于具有非平凡创建的相当复杂的对象。您可以考虑一些增加多功能性的工厂/构建器。

例如,如果您创建一个大型复合对象,最好使用构建器模式。 (Long example here)

简单对象

对于简单对象(最常见的情况),最好坚持使用new

例如,如果你有简单的类

public class Dog{
    private string name;

    //getter + setter
}

那么为此创建工厂有点过头了,你应该通过new Dog()调用它

依赖注入

在企业应用程序中,您通常使用依赖注入,这可以让您避免显式使用new。您不会删除所有对象实例化,但它提供了很好的改进。 (Basic Spring tutorial here)

【讨论】:

  • 简单/复杂的二分法可能没有那么富有成效。许多非常简单的值对象都由记忆工厂支持。
  • 大多数设计规则并不严格。您需要使用一些常识来为它们创建例外。你说的对。这不是“权威指南”,而是一种指导。
  • 我已经在我的评论中暗示了这一点(当我使用术语富有成效的时)。
  • 好。那我们有同样的看法:)
【解决方案3】:

new 没有替代品,甚至 Class.forName("XYZ").newInstance() HAS 可以完全像 new 一样工作,唯一的区别是您正在硬编码整个类(甚至是 package...class ) 因此实际上实现了相反您正在尝试做的事情,new 可以动态解析和/甚至注入实例。

如果你注入一个interface A 的实例,你很可能会得到一个B 类的bean,它实现了A——这实际上更加动态并且很好地补充了工厂模式。如果你的类名是硬编码的,那几乎是不可能的,至少在我看来是这样。

【讨论】:

  • 当您使用 Class.forName 时,您不必对类名进行硬编码。也不包。事实上,这就是使用 Class.forName 的主要原因。
【解决方案4】:

当您使用 Class.forName 时,可以在运行时设置类名。这对司机很有用,例如

当您使用 new 时,您正在创建的实例的类名是硬编码的。一般来说,这会产生高coupling,应该避免(除非您绝对确定您将始终需要这种耦合)。

简而言之,如果您想创建特定类的实例new 没有任何害处。

但是,你应该问问自己:

  • 如果您确实需要一个新实例(否则,您应该将 new 替换为 singleton 或池)。
  • 如果您将始终为该实例使用相同的类(否则,您应该将 new 替换为 Dependency InjectionFactory Pattern)。

【讨论】:

    【解决方案5】:

    如果你喜欢缓慢、缓慢、难以调试、维护和理解的代码,绝对不要使用new关键字,尽可能地混淆!

    【讨论】:

    • 嘘!不要向所有年轻的“程序员”和“黑客”撒谎!他们不喜欢那样!
    • 对于创建需要外部资源的对象,更多的子组件你的“未混淆”代码将在创建对象时在每个地方占用 20 行。最好将这 20 行放在一个地方,不要一直重复。
    • 当然 - 但这不会消除您工厂中对 new 的需求。
    • @MarcinSzymczak,嗯?把 20 行放在你想要的地方……你在说什么?
    猜你喜欢
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 2012-08-24
    • 1970-01-01
    相关资源
    最近更新 更多