【问题标题】:Why return a class instance inside of a class instance in Java?为什么在 Java 中的类实例中返回一个类实例?
【发布时间】:2015-11-04 17:28:24
【问题描述】:

我来自 JavaScript 和 Node.js 背景,虽然我掌握了大部分 OOP 基础知识,但仍有许多 Java 基础知识我不太了解。例如,我正在做 a Spring tutorial 并立即遇到一些令我困惑的语法。

第一个演练是一个 hello world 应用程序。首先,我们设置一个 Greeting 类:

public class Greeting {

    private final long id;
    private final String content;

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}

首先,我不明白他们为什么在类本身中定义类的实例。为什么不直接向公共类添加参数?无论如何,这不是我的问题。我更迷失的是当我们制作一个 Greeting 控制器时:

package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    // This ensures that HTTP requests to /greeting are mapped to the greeting() method.
    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(),
            String.format(template, name));
    }
}

在这个文件中,我知道public Greeting greeting 创建了一个新的 Greeting 类实例,但是当构造函数有两个参数时,它只有一个参数,long idString content。接下来,它们返回该类的另一个实例,这一次带有与构造函数结构匹配的参数。

这是为什么?

【问题讨论】:

  • 在类本身中定义一个类的实例 你在哪里看到的?此外,如果这不是您的问题或与之无关,请将其删除。
  • public Greeting greeting 创建 Greeting 类的新实例 不,它没有。这只是一个返回类型为Greeting的方法。
  • "但是当构造函数有两个参数时它只有一个参数" - 另一个参数不是 "String.format(...)" 吗? (看起来那条线上也使用了逗号而不是点?)
  • “向公共类添加参数”是什么意思?一个类没有参数……方法或构造函数调用有。如果您真的是 Java 新手,我强烈建议您放弃 Spring 方面的内容,首先学习该语言的基础知识。
  • 在进入像 Spring MVC 这样的高级框架之前,你应该真正学习 Java。

标签: java spring class oop


【解决方案1】:

何时使用链接

函数序列通常在带有自动完成功能的 IDE 中很常见的语言中很常见。例如,大多数 Visual C# 开发人员使用 Visual Studio。因此,如果您使用 C# 进行开发,向您的方法添加序列可以为该行的用户节省时间,因为 Visual Studio 将帮助您创建字符串。

另一方面,您会看到 PHP 等语言具有非常动态的特性,并且通常在 IDE 中不支持自动完成功能。仅当使用正确的 phpDocs 来公开顺序方法时,该顺序才合适。

什么是链接?

给定一个名为 Foo 的类,以下两个方法都是可链接的。

function what() { return this; }
function when() { return new Foo(this); }

一个是对当前实例的引用,一个是创建一个新实例这一事实并不会改变这些是顺序方法。

顺序方法应该只引用当前对象并没有黄金法则。连续和连续的道路可以跨越两个不同的类别。例如,

class B { function When() { return true; } };
class A { function What() { return new B(); } };

var a = new A();
var x = a.What().When();

在上面的任何例子中都没有提到这一点。代码是a.What()。当()是一个序列的例子。有趣的是,B 类从未分配给变量。

当返回值用作表达式的后面组件时,该方法受到限制。

这里还有一些例子

// 返回值从未赋值。

 myFile.Open("something.txt").Write("stuff").Close();

//表达式中用到的两条链

int x = a.X().Y() * b.X().Y();

// 创建新字符串的链

string name = str.Substring(1,10).Trim().ToUpperCase();

何时使用 this 和 new(this)

大多数语言中的字符串是不可更改的。顺序方法调用总是创建新的字符串。可以修改StringBuilder等对象的地方。

一致性是最佳实践。

如果您有修改对象状态并返回 this 的方法,请不要混淆返回新实例的方法。相反,创建一个名为 Clone () 的特定方法,该方法将显式执行此操作。

 var x  = a.Foo().Boo().Clone().Foo();

这对于内部发生的事情更加明显。 走出去,反击

我将此称为倒退,因为它解决了序列化的许多常见问题。基本上就是你从原来的班级毕业到一个新的临时班,然后回到原来的学期。

没有临时类别,除了为原类别提供特殊功能外,只有在特殊情况下。

系列赛经常需要改变情况,但A级不能代表所有这些潜在情况。因此,在字符串期间,一个包含引用的新类被呈现给 A。这允许程序员进入状态并返回到 A。

这里是理想,让特殊状态知道b。

class A {
    function Foo() { return this; }
    function Boo() { return this; }
    function Change() return new B(this); }
}

class B {
    var _a;
    function (A) { _a = A; }
    function What() { return this; }
    function When() { return this; }
    function End() { return _a; }
}

    var a = new A();
    a.Foo().Change().What().When().End().Boo();

现在这是一个非常简单的例子。如果您想拥有更多控制权,那么 B 可以返回到具有不同方法的 A 的新超类型。

我也向你推荐 hackr 社区以获得最好的 java 教程:https://hackr.io/tutorials/learn-java

【讨论】:

    【解决方案2】:

    首先我建议你学习 Java 编程语言,不要使用 Spring:

    public class Greeting {
    

    您正在定义一个名为 Greeting 的类。那是你的课。

    在这个类中你有:

    public Greeting(long id, String content) {
    

    这是类的构造函数。在 Java 中,没有对象就没有调用它们的构造函数。所以为了创建一个新对象,你必须调用它的构造函数。

    那么你有

    public class GreetingController {
    

    这定义了另一个类,在本例中为 GreetingController。

    这个类有一个方法(函数):

     public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name)
    

    此方法接收一个名为name 的字符串并返回一个Greeting 对象(实例)。为了返回 Greeting 的实例,您必须先创建实例,然后调用它的构造函数:

    return new Greeting(counter.incrementAndGet(),
                String.format(template, name));
    

    这一行调用构造函数并传递了两个参数,与您之前在 Greeting 类的构造函数中定义的相同。

    【讨论】:

      【解决方案3】:

      我不知道我是否理解你的问题,但我试着给你一个答案。

      通常您使用控制器(在您的情况下是 GreetengsController)向世界公开资源。此资源是一个 Greeting 对象/实例。您使用两个参数初始化对象(在您的情况下是 long 和 String)。

      public Greeting greeting(... String name) 
      

      是一个方法(函数)声明,它说:这个函数期望一个字符串“名称”作为参数,并返回一个对象 Greeting 给客户端(调用者),并带有

      return new Greeting(....)
      

      您返回 Greeting 对象。通常你会用对象做更多的事情(不仅仅是返回一个新的实例)

      我不知道我是否回答了你的问题。如果不。请告诉我。

      【讨论】:

        【解决方案4】:

        public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name)只定义了一个返回类型的方法greeting问候

        new Greeting(counter.incrementAndGet(),
                String.format(template, name))
        

        上面的代码实际上创建了一个新的 Greeting 实例并返回它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-27
          • 1970-01-01
          • 2021-03-23
          • 2012-10-08
          • 1970-01-01
          • 2022-01-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多