рдЕрднрд┐рд╡рд╛рджрди, рд╣рдмреНрд░! рдореИрдВ рдЖрдкрдХреЗ рдзреНрдпрд╛рди рдореЗрдВ рдЬрд╛рд╡рд╛, рд╕реНрдХрд╛рд▓рд╛, рдкрд╛рдЧрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдФрд░ рдЯреВрдЯреЗ рд╡рд╛рджреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓рдШреБ рд╢реБрдХреНрд░рд╡рд╛рд░ рдХрд╛ рд▓реЗрдЦ рд▓рд╛рддрд╛ рд╣реВрдВред
рд╕рд░рд▓ рдЕрд╡рд▓реЛрдХрди рдХрднреА-рдХрднреА рдмрд╣реБрдд рд╕рд░рд▓ рдкреНрд░рд╢реНрди рдирд╣реАрдВ рдмрдирддреЗ рд╣реИрдВред
рдпрд╣рд╛рдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рд░рд▓ рдФрд░ рдмрд╛рд╣реНрдп рд░реВрдк рд╕реЗ, рд╢рд╛рдпрдж рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рддреБрдЪреНрдЫ рддрдереНрдп рд╣реИ рдЬреЛ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдЬрд╛рд╡рд╛ рдореЗрдВ рдЖрдк рдХрд┐рд╕реА рднреА рдЧреИрд░-рдЕрдВрддрд┐рдо рд╡рд░реНрдЧ рдФрд░ рдХрд┐рд╕реА рднреА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рджрд╛рдпрд░реЗ рдореЗрдВ рдмрдврд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ рджреВрд╕рд░рд╛, рдпрд╣ рднреА рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ, рдпрд╣ рдХрд╣рддреЗ рд╣реБрдП рдХрд┐ рдЬрд╛рд╡рд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП JVM рдХреЗ рд▓рд┐рдП рд╕рдВрдХрд▓рд┐рдд рд╕реНрдХрд╛рд▓рд╛ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЗрди рджреЛрдиреЛрдВ рддрдереНрдпреЛрдВ рдХреЗ рд╕рдВрдпреЛрдЬрди рдиреЗ, рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд░ рджрд┐рдпрд╛: рдЬрд╛рд╡рд╛ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдХреЛрдИ рднреА рд╡рд░реНрдЧ рдХреИрд╕рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░реЗрдЧрд╛, рдЬреЛ рдХрд┐ рд╕реНрдХрд╛рд▓рд╛ рдореЗрдВ рд╕реАрд▓ рд╣реИ, рдЕрд░реНрдерд╛рддреНред рдЕрдкрдиреА рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдмрд╛рд╣рд░реА рдХреЛрдб рдХреЗ рд╕рд╛рде рд╡рд┐рд╕реНрддрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?
рдХрд▓рд╛рдХрд╛рд░ рдХреА рджреГрд╖реНрдЯрд┐ рдореЗрдВ рд╡рд┐рдШрдЯрд┐рдд рд╕реНрдХрд╛рд▓рд╛-рд╡рд░реНрдЧред рд╕реНрд░реЛрдд: https://specmahina.ru/wp-content/uploads/2018/08/razobrannaya-benzopila.jpg
рдПрдХ рдкреНрд░рдпреЛрдЧрд╛рддреНрдордХ рдЦрд░рдЧреЛрд╢ рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ рдорд╛рдирдХ рд╡рд░реНрдЧ рд▓рд┐рдпрд╛ Option
ред рдЗрд╕реЗ рдЗрдВрдЯреЗрд▓реАрдЬ рдЖрдЗрдбрд┐рдпрд╛ рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдбрд┐рдХрдореНрдкреЙрдЗрд▓рд░ рдХреЛ рдЦрд┐рд▓рд╛рдХрд░, рд╣рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдорд┐рд▓рддрд╛ рд╣реИ:
public abstract class Option
implements IterableOnce, Product, Serializable {
public abstract Object get();
}
Decompiled рдХреЛрдб, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдорд╛рдиреНрдп Java рдХреЛрдб рдирд╣реАрдВ рд╣реЛрдЧрд╛ - рдпрд╣рд╛рдБ рд╡рд░реНрдгрд┐рдд рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдорд╛рди , рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рд╕рд╛рде:
public List toList() {
return (List)(
this.isEmpty()
? scala.collection.immutable.Nil..MODULE$
: new colon(this.get(), scala.collection.immutable.Nil..MODULE$)
);
}
MODULE$ , package object. , , Java , ?
, , ...
Java ( Maven), Scala provided- тАФ , , , :
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.13.1</version>
<scope>provided</scope>
</dependency>
, scala.Option
. Idea, , Scala , sealed-, , , :
package hack;
public class Hacking<T> extends scala.Option<T> {
@Override
public T get() {
return null;
}
public int productArity() {
return 0;
}
public Object productElement(int n) {
return null;
}
public boolean canEqual(Object that) {
return false;
}
}
- , Option Product.
, тАФ . mvn package
тАФ , , jar-, , Java, , , .
, Scala.
тАж scala-
Scala (, SBT) тАФ lib , , , ; build.sbt , Idea. ( ) :
import hack.Hacking
object Main {
def main(args: Array[String]): Unit = {
implicit val opt: Option[String] = new Hacking()
}
private def tryDo[T](action: => T): Unit = {
try {
println(action)
} catch {
case e: Throwable => println(e.toString)
}
}
}
implicit var
.
tryDo
тАФ , : , , . call-by-name tryDo
, , .
, match
тАФ , sealed class- ( , sealed-, ?)
object Main {
def main(args: Array[String]): Unit = {
tryMatch
}
private def tryDo[T](action: => T): Unit = {
}
private def tryMatch(implicit opt: Option[String]): Unit = tryDo {
opt match {
case Some(inner) => inner
case None => "None"
}
}
}
:
scala.MatchError: hack.Hacking
, : Option тАФ sealed class, ( case Some case None), :
[warn] $PATH/Main.scala:22:5: match may not be exhaustive.
[warn] It would fail on the following input: None
[warn] opt match {
[warn] ^
, .
, - Option:
object Main {
def main(args: Array[String]): Unit = {
tryMap
}
private def tryDo[T](action: => T): Unit = {
}
private def tryMap(implicit opt: Option[String]): Unit =
tryDo(opt.map(_.length))
}
:
java.lang.NullPointerException
, map:
sealed abstract class Option[+A] /* extends ... */ {
final def isEmpty: Boolean = this eq None
def get: A
@inline final def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
}
, :
- тАФ None. , isEmpty false.
- , this.get, null.
- null , тАФ length.
- length null NPE.
, NPE , Java ? (, , , ...)
:
object Main {
def main(args: Array[String]): Unit = {
tryContainsNull
}
private def tryDo[T](action: => T): Unit = {
}
private def tryContainsNull(implicit opt: Option[String]): Unit =
tryDo(opt.contains(null))
}
(, , null) , contains -Nullable . , , , Option false тАФ null. ?
:
true
, , , contains map: !isEmpty && this.get == elem
.
, . , null , Option ( , , ) else match.
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдПрдХ рдЬреЗрд╡реАрдПрдо рдкрд░ рд╡рд┐рднрд┐рдиреНрди рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд рдХреА рдПрдХ рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рдХрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдкреНрд░рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд▓реЗрдЦ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде, рдереЛрдбрд╝рд╛ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд╕рд╛рде, рд╕реНрдкрд╖реНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди - рдореЗрд░реЗ рд╕реНрд╡рд╛рдж рдХреЗ рд▓рд┐рдП, рдЕрднреА рднреА рджрд┐рд▓рдЪрд╕реНрдк рд╣реИред