Scala中Nil列表的定义

时间:2018-02-05 19:58:36

标签: scala

我不太了解Scala教科书中Nil List的定义。列表定义如下:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: com/sun/mail/util/PropUtil
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:160)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:127)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
at com.mycompany.spring4base.web.controller.security.UserControllerTest.testFindUserFromActiveDirectory_Exists(UserControllerTest.java:441)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NoClassDefFoundError: com/sun/mail/util/PropUtil
    at javax.mail.internet.InternetAddress.<clinit>(InternetAddress.java:85)
    at com.mycompany.spring4base.model.security.User.getEmailAsInternetAddress(User.java:262)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:664)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:689)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
    at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1429)
    at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:951)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:286)
    at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:106)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:231)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    ... 42 more
Caused by: java.lang.ClassNotFoundException: com.sun.mail.util.PropUtil
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 64 more
  1. 为什么Nil不是班级?

  2. 为什么Nil不扩展List [A]?

  3. 我可以将Nil案例定义为:

    案例类Nil扩展了List [A]?

3 个答案:

答案 0 :(得分:4)

  1. 由于Nil不接受任何参数,因此它可以是单个对象,因此每次创建新List时都不会产生任何开销。
  2. Nothing是所有其他类型的子类型。从List[Nothing]延伸可以将Nil与任何List[A]一起使用。
  3. 不,因为object无法参数化。

答案 1 :(得分:1)

  1. Nil不是一个类,因为它不带任何参数。当一个类不带任何参数且没有可变状态时,它也可以是一个对象。

  2. 因为A会是什么?如果你确实使Nil成为一个类,你可以将A作为类型参数,但是在不能推断它的各种情况下你必须提供该类型参数。 / p>

  3. 不,这在语法上没有用。

答案 2 :(得分:1)

只是加上我的两分钱,让我们说你想要定义自己的列表实现,如下所示:

trait List[A]
case class Nil[A]() extends List[A]
case class Cons[A](head: A, tail: List[A]) extends List[A]

这完全有效Scala

但是您可能会意识到,为什么我需要Nil()成为案例类?我希望它是所有类型列表的底层元素,因此Nil[Int]()应与Nil[String]()一样为空列表。

scala> Nil[Int]()
res3: Nil[Int] = Nil()

scala> Cons(1,Nil[Int]())
res4: Cons[Int] = Cons(1,Nil())

scala> Cons("a",Nil[Int]())
<console>:13: error: type mismatch;
 found   : Nil[Int]
 required: List[Any]
Note: Int <: Any, but trait List is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
              Cons("a",Nil[Int]())
                           ^

因此,对于所有类型的列表,只存在一个空列表,我们可能希望将其视为单独的实例(单个对象)。

由于Nothing是所有其他类型的子类型,我们可能会认为Nil属于List[Nothing]类型。因此,我们最终得到了这个实现:

trait List[A]
case object Nil extends List[Nothing]
case class Cons[A](head: A, tail: List[A]) extends List[A]

到目前为止,这么好。但是等等......

scala> Cons(1, Nil)
<console>:12: error: type mismatch;
 found   : Nil.type
 required: List[Int]
Note: Nothing <: Int (and Nil.type <: List[Nothing]), but trait List is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
              Cons(1, Nil)
                      ^

特质列表在A型中是不变的 ......到底是什么?这是协方差进入游戏的地方。协方差指出的是,对于我们的特征List,如果AB的子类型,那么List[A]List[B]的子类型。

让我们回到我们的示例,我们已经知道Nothing是任何A的子类型,因此我们应该要求List[Nothing]也是任何List[A]的子类型,因此我们需要创建类型A协变,如下所示:

trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A] (head: A, tail: List[A]) extends List[A]

scala> Cons(1, Nil)
res0: Cons[Int] = Cons(1,Nil)