Java 返回嵌套类中内部类的实例

Java 返回嵌套类中内部类的实例,java,scala,Java,Scala,代码如下: import scala.collection.mutable /** * Created by IDEA on 25/10/15. */ class HttpRequest(builder: Builder) { val headers: Map[String, String] var body: String var path: String class Builder {innerBuilder => private val headers

代码如下:

import scala.collection.mutable

/**
 * Created by IDEA on 25/10/15.
 */
class HttpRequest(builder: Builder) {
  val headers: Map[String, String]
  var body: String
  var path: String

  class Builder {innerBuilder =>
    private val headers = new mutable.HashMap[String, String]()
    private var body: String = _
    private var path: String = _

    def addHeader(name: String, value: String): Unit = {
      headers.put(name, value)
      innerBuilder
    }

    def body(b: String): Builder = {
      body = b
      innerBuilder
    }

    def path(p: String) = {
      path = p
      innerBuilder
    }

    def build: HttpRequest = {
      new HttpRequest(innerBuilder)
    }
  }
}
我有两个错误:

Error:(27, 7) overloaded method path needs result type
      path = p
      ^
Error:(32, 23) type mismatch;
 found   : HttpRequest.this.Builder
 required: Builder
      new HttpRequest(innerBuilder)
                      ^
我做错了什么

顺便说一句,我试图将这个java文件翻译成scala:

/***
 * Excerpted from "Functional Programming Patterns",
 * published by The Pragmatic Bookshelf.
 * Copyrights apply to this code. It may not be used to create training material, 
 * courses, books, articles, and the like. Contact us if you are in doubt.
 * We make no guarantees that this code is fit for any purpose. 
 * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information.
***/
package com.mblinn.oo.tinyweb;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest {
    private Map<String, String> headers;
    private String body;
    private String path;

    public Map<String, String> getHeaders() {
        return headers;
    }

    public String getBody() {
        return body;
    }

    public String getPath() {
        return path;
    }

    private HttpRequest(Builder builder) {
        this.headers = Collections.unmodifiableMap(builder.headers);
        this.body = builder.body;
        this.path = builder.path;
    }

    public static class Builder {
        private Map<String, String> headers;
        private String body;
        private String path;

        private Builder() {
            headers = new HashMap<String, String>();
        }

        public Builder addHeader(String name, String value) {
            headers.put(name, value);
            return this;
        }

        public Builder body(String body) {
            this.body = body;
            return this;
        }

        public Builder path(String path) {
            this.path = path;
            return this;
        }

        public HttpRequest build() {
            return new HttpRequest(this);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public static Builder builderFrom(HttpRequest request) {
            Builder builder = new Builder();
            builder.path(request.getPath());
            builder.body(request.getBody());

            Map<String, String> headers = request.getHeaders();
            for (String headerName : headers.keySet())
                builder.addHeader(headerName, 
                        headers.get(headerName));

            return builder;
        }
    }
}
还有两个问题:

  • 似乎不允许在外部类的构造中引用内部类(intellij无法解析)

  • newhttprequest(此)
    报告类型不匹配


  • 您提到的其余两点的问题是,
    Builder
    HttpRequest
    的一个内部类(事实上,正如所写的,它是为
    HttpRequest
    的每个特定实例单独定义的内部类),因此需要以这种方式进行处理,如类型
    HttpRequest.Builder
    。但是为了正确地实现这一点,您需要将Builder的定义移动到
    HttpRequest
    的伴生对象中。比如:

    case class HttpRequest(headers: Map[String, String], body: String, path: String)
    
    object HttpRequest {
    
      def apply(builder: HttpRequest.Builder): HttpRequest = 
          HttpRequest(Map(builder.headers.toSeq: _*),
                      builder.body,
                      builder.path)
    
      class Builder {
        private[HttpRequest] val headers = new mutable.HashMap[String, String]()
        private[HttpRequest] var body: String = _
        private[HttpRequest] var path: String = _
    
        def addHeader(name: String, value: String): Builder = {
          headers.put(name, value)
          this
        }
    
        def body(b: String): Builder = {
          body = b
          this
        }
    
        def path(p: String): Builder = {
          this.path = p
          this
        }
    
        def build: HttpRequest = {
          HttpRequest(this)
        }
      }
    
      def builderFrom(request: HttpRequest): Builder = {
        val builder = new Builder().path(request.path).body(request.body)
    
        request.headers.foldLeft(builder){ (b,h) => b.addHeader(h._1, h._2) }
      }
    }
    
    以下是一些注意事项:

    • 我使HttpRequest成为一个case类,因为它更适合Scala数据类
    • Builder
      类现在位于伴生对象中(可以粗略地认为它是Java中标记为“static”的所有对象的持有者,尽管它做的不止这些,特别是对于case类)
    • 伴随对象也是放置
      buildFrom
      方法的地方,该方法通过链式方法调用和折叠请求头来构造
      Builder
      。由于折叠生成一个
      Builder
      作为其结果,因此这将是
      buildFrom
      方法的返回值
    • Builder
      字段上的
      private[HttpRequest]
      访问修饰符确保这些字段仅在
      HttpRequest
      类中可见,该类包括内部
      Builder
      类(需要这些字段才能在
      apply
      方法中访问)
    • 我只检查了上面的代码是否在控制台中编译——实际上我还没有对代码进行测试

    您提到的其余两点的问题是,
    Builder
    HttpRequest
    的一个内部类(事实上,如本文所述,它是为
    HttpRequest
    的每个特定实例单独定义的内部类),因此需要以这种方式进行处理,如类型
    HttpRequest.Builder
    。但是为了正确地实现这一点,您需要将Builder的定义移动到
    HttpRequest
    的伴生对象中。比如:

    case class HttpRequest(headers: Map[String, String], body: String, path: String)
    
    object HttpRequest {
    
      def apply(builder: HttpRequest.Builder): HttpRequest = 
          HttpRequest(Map(builder.headers.toSeq: _*),
                      builder.body,
                      builder.path)
    
      class Builder {
        private[HttpRequest] val headers = new mutable.HashMap[String, String]()
        private[HttpRequest] var body: String = _
        private[HttpRequest] var path: String = _
    
        def addHeader(name: String, value: String): Builder = {
          headers.put(name, value)
          this
        }
    
        def body(b: String): Builder = {
          body = b
          this
        }
    
        def path(p: String): Builder = {
          this.path = p
          this
        }
    
        def build: HttpRequest = {
          HttpRequest(this)
        }
      }
    
      def builderFrom(request: HttpRequest): Builder = {
        val builder = new Builder().path(request.path).body(request.body)
    
        request.headers.foldLeft(builder){ (b,h) => b.addHeader(h._1, h._2) }
      }
    }
    
    以下是一些注意事项:

    • 我使HttpRequest成为一个case类,因为它更适合Scala数据类
    • Builder
      类现在位于伴生对象中(可以粗略地认为它是Java中标记为“static”的所有对象的持有者,尽管它做的不止这些,特别是对于case类)
    • 伴随对象也是放置
      buildFrom
      方法的地方,该方法通过链式方法调用和折叠请求头来构造
      Builder
      。由于折叠生成一个
      Builder
      作为其结果,因此这将是
      buildFrom
      方法的返回值
    • Builder
      字段上的
      private[HttpRequest]
      访问修饰符确保这些字段仅在
      HttpRequest
      类中可见,该类包括内部
      Builder
      类(需要这些字段才能在
      apply
      方法中访问)
    • 我只检查了上面的代码是否在控制台中编译——实际上我还没有对代码进行测试