scala面试问题
Before reading this post, please go through my previous post at “Scala Basic Interview Questions and Answers” to get some basic knowledge about Scala Language.
在阅读本文之前,请仔细阅读我以前的文章《 Scala基本面试问答 》,以获取有关Scala语言的一些基本知识。
In this post, we are going to discuss about some more Scala Interview Questions which are useful for some experienced Scala Developers.
在这篇文章中,我们将讨论更多的Scala面试问题,这些问题对一些有经验的Scala开发人员很有用。
Note:- As this list has already become very large, I’m going to deliver another post with remaining Questions and Answers. Please refer that post at: “Scala Intermediate and Advanced Interview Questions and Answers”
注意:-由于此列表已经很大,因此我将提供另一篇文章,其中包含剩余的“问题与解答”。 请在以下位置参阅该帖子:“ Scala中级和高级面试问答 ”
In this section, we are going to list out all Scala Intermediate Interview Questions and in next section we will discuss them in detail.
在本节中,我们将列出所有Scala中级面试问题,在下一节中,我们将详细讨论它们。
In this section, we will pickup each and every question from above list and discuss in-detail with suitable examples(if required). If you want to understand these concepts in-depth with examples, please go through my previous posts in Scala Tutorials section.
在本节中,我们将从上面的列表中提取每个问题,并详细讨论适当的示例(如果需要)。 如果您想通过示例深入了解这些概念,请阅读我之前在Scala教程部分中的文章。
Scala has two kinds of constructors:
Scala有两种构造函数:
Primary Constructor
In Scala, Primary Constructor is a constructor which is defined with class definition itself. Each class must have one Primary Constructor: Either Parameter constructor or Parameterless constructor.
主要建设者
在Scala中,主要构造函数是使用类定义本身定义的构造函数。 每个类必须具有一个主构造函数:参数构造函数或无参数构造函数。
Example:-
例:-
class Person
Above Person class has one Zero-parameter or No-Parameter or Parameterless Primary constructor to create instances of this class.
上述Person类具有一个零参数或无参数或无参数的Primary构造函数来创建此类的实例。
class Person (firstName: String, lastName: String)
Above Person class has a two Parameters Primary constructor to create instances of this class.
在Person类之上,有两个Parameters Primary构造函数来创建此类的实例。
Auxiliary Constructor
Auxiliary Constructor is also known as Secondary Constructor. We can declare a Secondary Constructor using ‘def’ and ‘this’ keywords as shown below:
辅助构造器
辅助构造函数也称为辅助构造函数。 我们可以使用'def'和'this'关键字声明一个二级构造函数,如下所示:
class Person (firstName: String, middleName:String, lastName: String){
def this(firstName: String, lastName: String){
this(firstName, "", lastName)
}
}
In Scala, The main purpose of Auxiliary Constructors is to overload constructors. Like Java, We can provide various kinds of constructors so that use can choose the right one based on his requirement.
在Scala中,辅助构造函数的主要目的是重载构造函数。 像Java一样,我们可以提供各种构造函数,以便用户可以根据自己的需求选择合适的构造函数。
Auxiliary Constructor Rules:
辅助构造函数规则:
NOTE:- If you want to learn about Scala’s Constructors, please refer my Scala posts at: Primary Constructor and Auxiliary Constructor.
注意:-如果您想了解Scala的构造函数,请参阅我的Scala帖子: 主要构造函数和辅助构造函数 。
Differences between Array and ArrayBuffer in Scala:
Scala中Array和ArrayBuffer之间的区别:
Case class is a class which is defined with “case class” keywords. Case object is an object which is defined with “case object” keywords. Because of this “case” keyword, we will get some benefits to avoid boilerplate code.
案例类是使用“案例类”关键字定义的类。 案例对象是使用“案例对象”关键字定义的对象。 由于使用了“ case”关键字,我们将获得一些避免样板代码的好处。
We can create case class objects without using “new” keyword. By default, Scala compiler prefixes “val” for all constructor parameters. That’s why without using val or var, Case class’s constructor parameters will become class members, it is not possible for normal classes.
我们可以创建案例类对象,而无需使用“ new”关键字。 默认情况下,Scala编译器为所有构造函数参数添加“ val”前缀。 这就是为什么不使用val或var的情况下,Case类的构造函数参数将成为类成员,而普通类则不可能。
Advantages of case class:
案例类的优点:
object MyNormalObject
case object MyCaseObject
The following are the major advantages or benefits of a Case class over Normal Classes:
以下是案例类相对于普通类的主要优点或好处:
Both isInstanceOf and asInstanceOf methods are defined in Any class. So no need import to get these methods into any class or object.
isInstanceOf和asInstanceOf方法都在Any类中定义。 因此,无需导入即可将这些方法导入任何类或对象。
“isInstanceOf” method is used to test whether the object is of a given type or not. If so, it returns true. Otherwise returns false.
“ isInstanceOf”方法用于测试对象是否为给定类型。 如果是这样,则返回true。 否则返回false。
scala> val str = "Hello"
scala>str.isInstanceOf[String]
res0: Boolean = false
“asInstanceOf” method is used to cast the object to the given a type. If the given object and type are of same type, then it cast to given type. Otherwise, it throws java.lang.ClassCastException.
“ asInstanceOf”方法用于将对象转换为给定的类型。 如果给定的对象和类型属于同一类型,则将其转换为给定的类型。 否则,它将引发java.lang.ClassCastException。
scala> val str = "Hello".asInstanceOf[String]
str: String = Hello
In Java, ‘instanceof’ keyword is similar to Scala’s ‘isInstanceOf’ method. In Java, the following kind of manual type casting is similar to Scala’s ‘asInstanceOf’ method.
在Java中,“ instanceof”关键字类似于Scala的“ isInstanceOf”方法。 在Java中,以下类型的手动类型转换类似于Scala的'asInstanceOf'方法。
AccountService service = (AccountService)
context.getBean("accountService");
Yes, By Default, Case Object is Serializable. But normal object is not. We can prove this by using isInstanaceOf method as shown below:
是的,默认情况下,Case对象是可序列化的。 但是普通对象不是。 我们可以使用isInstanaceOf方法证明这一点,如下所示:
scala> object MyNormalObject
defined object MyNormalObject
scala> MyNormalObject.isInstanceOf[Serializable]
res0: Boolean = false
scala> case object MyCaseObject
defined object MyCaseObject
scala> MyCaseObject.isInstanceOf[Serializable]
res1: Boolean = true
NOTE:- If you are not sure about Invariant and Covariant, please read my next post on Scala Interview Questions.
注意:-如果您不确定不变式和协变式,请阅读我关于Scala面试问题的下一篇文章。
As we discussed in my Basic Scala Interview Questions, “val” means value or constant which is used to define Immutable variables.
正如我们在我的基本Scala面试问题中所讨论的那样,“ val”表示用于定义不可变变量的值或常数。
There are two kinds of program evaluations:
有两种程序评估:
Eager Evaluation means evaluating program at compile-time or program deployment-time irrespective of clients are using that program or not.
急切评估是指在编译时或程序部署时评估程序,而不管客户端是否正在使用该程序。
Lazy Evaluation means evaluating program at run-time on-demand that means when clients access the program then only its evaluated.
惰性评估是指在运行时按需评估程序,这意味着客户端访问该程序时仅评估它。
The difference between “val” and “lazy val” is that “val” is used to define variables which are evaluated eagerly and “lazy val” is also used to define variables but they are evaluated lazily.
“ val”和“ lazy val”之间的区别在于,“ val”用于定义热切评估的变量,“ lazy val”也用于定义变量,但它们是延迟计算的。
In Scala, we do NOT need to call equals() method to compare two instances or objects. When we compare two instances with ==, Scala calls that object’s equals() method automatically.
在Scala中,我们不需要调用equals()方法来比较两个实例或对象。 当我们用==比较两个实例时,Scala会自动调用该对象的equals()方法。
Java’s == operator is used to check References Equality that is whether two references are pointing to the same object or not. Scala’s == is used to check Instances Equality that is whether two instances are equal or not.
Java的==运算符用于检查“引用相等”,即两个引用是否指向同一对象。 Scala的==用于检查实例是否相等,即两个实例是否相等。
In Java, Inner class is associated with Outer class that is Inner class a member of the Outer class.
Unlike Java, Scala treats the relationship between Outer class and Inner class differently. Scala’s Inner class is associated with Outer class object.
在Java中,内部类与外部类相关联,外部类是内部类的外部类的成员。
与Java不同,Scala对待外部类和内部类之间的关系有所不同。 Scala的内部类与外部类对象相关联。
A Diamond Problem is a Multiple Inheritance problem. Some people calls this problem as Deadly Diamond Problem.
钻石问题是多重继承问题。 有人将此问题称为致命钻石问题。
In Scala, it occurs when a Class extends more than one Traits which have same method definition as shown below.
在Scala中,当一个类扩展了多个具有以下相同方法定义的特性时,就会发生这种情况。
Unlike Java 8, Scala solves this diamond problem automatically by following some rules defined in Language. Those rules are called “Class Linearization”.
与Java 8不同,Scala通过遵循Language中定义的一些规则自动解决了这一钻石问题。 这些规则称为“类线性化”。
Example:-
例:-
trait A{
def display(){ println("From A.display") }
}
trait B extends A{
override def display() { println("From B.display") }
}
trait C extends A{
override def display() { println("From C.display") }
}
class D extends B with C{ }
object ScalaDiamonProblemTest extends App {
val d = new D
d display
}
Here output is “From C.display” form trait C. Scala Compiler reads “extends B with C” from right to left and takes “display” method definition from lest most trait that is C.
这里的输出是“ From C.display”形式的特征C。Scala编译器从右到左读取“用C扩展B”,并从最主要的特征C中获取“ display”方法定义。
NOTE:- See my post on “Scala Traits in Depth” to know this with clear explanation.
注意:-请参阅我在“深度上的斯卡拉特征”中的帖子,以清楚的说明了解这一点。
As we know, Scala does NOT have “static” keyword at all. This is the design decision done by Scala Team.
众所周知,Scala根本没有“ static”关键字。 这是Scala团队做出的设计决定。
The main reason to take this decision is to make Scala as a Pure Object-Oriented Language. “static” keyword means that we can access that class members without creating an object or without using an object. This is completely against with OOP principles.
做出此决定的主要原因是使Scala成为纯面向对象的语言。 “静态”关键字表示无需创建对象或使用对象就可以访问该类成员。 这完全违反OOP原则。
If a Language supports “static” keyword, then that Language is not a Pure Object-Oriented Language. For instance, as Java supports “static” keyword, it is NOT a Pure Object-Oriented Language. But Scala is a Pure Object-Oriented Language.
如果一种语言支持“静态”关键字,则该语言不是纯面向对象的语言。 例如,由于Java支持“静态”关键字,因此它不是纯面向对象的语言。 但是Scala是一种纯面向对象的语言。
In Scala, object keyword is used the following purposes:
在Scala中,使用object关键字的目的如下:
object MySingletonObject
Here, MySingletonObject becomes singleton object automatically.
在这里,MySingletonObject自动成为单例对象。
object MyScalaExecutableProgram{
def main(args: Array[String]){
println("Hello World")
}
}
When we define main method in object as shown above (its same as main() method in Java), it becomes automatically as a executable Scala program.
当我们如上所述在对象中定义main方法时(与Java中的main()方法相同),它将自动成为可执行的Scala程序。
object MyScalaStaticMembers{
val PI: Double = 3.1414
def add(a: Int, b: Int) = a + b
}
By def PI variable and add methods will become as static members. That means we can call them without creating a separate object like MyScalaStaticMembers.add(10,20).
通过def PI变量和add方法将成为静态成员。 这意味着我们可以调用它们而无需创建像MyScalaStaticMembers.add(10,20)这样的单独对象。
In Scala, we use ‘object’ keyword to define Factory methods. The main purpose of these Factory methods in Scala is to avoid using ‘new’ keyword. Without using ‘new’ keyword we can create objects.
在Scala中,我们使用'object'关键字定义Factory方法。 Scala中这些Factory方法的主要目的是避免使用'new'关键字。 不使用“ new”关键字,我们可以创建对象。
To define Factory methods:
We can use apply method to define Factory methods in Scala. If we have Primary Constructor and Multiple Auxiliary constructors, then we need to define multiple apply methods as shown below.
定义工厂方法:
我们可以使用apply方法在Scala中定义Factory方法。 如果我们有主构造函数和多个辅助构造函数,则需要定义多个apply方法,如下所示。
class Person(val firstName: String, val middleName: String, val lastName: String){
def this(firstName: String, lastName: String){
this(firstName,"",lastName)
}
}
object Person{
def apply(val firstName: String, val middleName: String, val lastName: String)
= new Person(firstName,middleName,lastName)
def apply(val firstName: String, val lastName: String)
= new Person(firstName, lastName)
}
Now we can create Person objects without using new keyword or with new keyword upto your wish.
现在,我们可以创建Person对象,而无需使用new关键字或根据您的意愿使用new关键字。
val p1 = new Person("Scala","Java")
or
val p1 = Person("Scala","Java")
In Scala, apply and unapply methods play very important role. They are also very useful in Play Framework in mapping and unmapping data between Form data and Model data.
在Scala中,套用和套用的方法起着非常重要的作用。 它们在Play框架中在Form数据和Model数据之间映射和取消映射数据时也非常有用。
In simple words,
简单来说
Scala’s apply method:
It is used to compose an object by using its components. Suppose if we want to create a Person object, then use firstName and laststName two components and compose Person object as shown below.
Scala的apply方法:
它用于通过使用其组件来构成对象。 假设我们要创建一个Person对象,则使用firstName和laststName两个组件并组成Person对象,如下所示。
class Person(val firstName: String, val lastName: String)
object Person{
def apply(firstName: String, lastName: String)
= new Person(firstName, lastName)
}
Scala’s unapply method:
It is used to decompose an object into its components. It follows reverse process of apply method. Suppose if we have a Person object, then we can decompose this object into it’s two components: firstName and laststName as shown below.
Scala的未应用方法:
它用于将对象分解为其组件。 它遵循申请方法的相反过程。 假设我们有一个Person对象,则可以将该对象分解为两个组件:firstName和laststName,如下所示。
class Person(val firstName: String, val lastName: String)
object Person{
def apply(firstName: String, lastName: String)
= new Person(firstName, lastName)
def unapply(p: Person): (String,String)
= (p.firstName, p.lastName)
}
In Scala, when we create an instance of a Class without using ‘new’ keyword, internally it make a call to appropriate apply method available in Companion object. Here appropriate apply method means that matched with parameters.
在Scala中,当我们在不使用'new'关键字的情况下创建Class的实例时,在内部它会调用Companion对象中可用的适当apply方法。 这里合适的应用方法意味着与参数匹配。
When do we choose this option: When we need to provide private private constructor and we need to avoid using ‘new’ keyword, we can implement only apply method with same set of parameters and allow our class users to create it without new keyword.
什么时候选择此选项:当我们需要提供私有的私有构造函数并且需要避免使用'new'关键字时,我们只能实现具有相同参数集的apply方法,并允许我们的类用户创建不带有new关键字的方法。
In Scala, we can declare a private Primary Constructor very easily. Just define a Primary Constructor as it is and add ‘private’ just after class name and before parameter list as shown below:
在Scala中,我们可以非常轻松地声明私有的Primary Constructor。 只需按原样定义一个主构造函数,并在类名之后和参数列表之前添加“ private”,如下所示:
class Person private (name: String)
object Person{
def apply(name: String) = new Person(name)
}
As it’s a private constructor, we cannot call it from outside. We should provide a factory method (that is apply method) as shown above and use that constructor indirectly.
由于它是私有构造函数,因此我们不能从外部调用它。 我们应该提供如上所述的工厂方法(即apply方法),并间接使用该构造函数。
Generally, private members means accessible only within that class. However Scala’s Companion class and Companion Object has provided another feature.
通常,私有成员意味着只能在该类中访问。 但是,Scala的Companion类和Companion对象提供了另一个功能。
In Scala, a Companion object can access private members of it’s Companion class and Companion class can access it’s Companion object’s private members.
在Scala中,Companion对象可以访问其Companion类的私有成员,而Companion类可以访问其Companion对象的私有成员。
In Scala, we use class keyword to define instance members and object keyword to define static members. Scala does not have static keyword, but still we can define them by using object keyword.
在Scala中,我们使用class关键字定义实例成员,使用object关键字定义静态成员。 Scala没有static关键字,但是我们仍然可以使用object关键字定义它们。
The main design decision about this is that the clear separation between instance and static members. Loosely coupling between them. And other major reason is to avoid static keyword so that Scala will become a Pure-OOP Language.
关于此的主要设计决策是实例和静态成员之间的明确分隔。 它们之间的耦合松散。 另外一个主要原因是避免使用静态关键字,以便Scala成为Pure-OOP语言。
Unlike Java, Scala has two meanings about ‘object’. Don’t get confuse about this, I will explain it clearly. In Java, we have only one meaning for object that is “An instance of a class”.
与Java不同,Scala关于“对象”有两种含义。 不要对此感到困惑,我会清楚地解释它。 在Java中,对象的唯一含义是“类的实例”。
val p1 = new Person("Scala","Java")
or
val p1 = Person("Scala","Java")
In simple words, if a Scala class and object shares the same name and defined in the same source file, then that class is known as “Companion Class” and that object is known as “Companion Object”.
简而言之,如果Scala类和对象共享相同的名称并在同一源文件中定义,则该类称为“同伴类”,而该对象称为“同伴对象”。
When we create a Class by using Scala “class” keyword and Object by using Scala “object” keyword with same name and within the same source file, then that class is known as “Companion Class” and that object is known as “Companion Object”.
当我们在同一个源文件中使用具有相同名称的Scala“类”关键字和使用Scala“对象”关键字来创建对象时,该类称为“伴侣类”,而该对象称为“伴侣对象” ”。
Example:-
Employee.scala
例:-
员工规模
class Employee{ }
object Employee{ }
In Scala, The main purpose of Companion Object is to define apply methods and avoid using new keyword in creating an instance of that Companion class object.
在Scala中,Companion对象的主要目的是定义应用方法,并避免在创建该Companion类对象的实例时使用new关键字。
As we know from Java background, we use interface to define contact.
从Java背景知道,我们使用接口定义联系人。
However, there is no interface concept in Scala. Even, Scala doesn’t have interface keyword. Scala has a more powerful and flexible concept i.e. trait for this purpose.
但是,Scala中没有接口概念。 甚至,Scala没有interface关键字。 Scala具有更强大和灵活的概念,即为此目的的特征。
Range is a Lazy Collection in Scala. Range is a class available in ‘scala’ package like ‘scala.Range’. It is used to represent a sequence of integer values. It is an ordered sequence of integers.
Example:-
Range是Scala中的一个惰性集合。 Range是“ scala”包中可用的类,例如“ scala.Range”。 它用于表示整数值序列。 它是整数的有序序列。
例:-
scala> 1 to 10
res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1 until 10
res1: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
In Scala, Nothing type have no values that is zero. It does not have any values. It is a subtype of all Value classes and Reference classes.
在Scala中,Nothing类型没有零值。 它没有任何值。 它是所有Value类和Reference类的子类型。
In Scala, Unit is something similar to Java’s void keyword. It is used to represent “No value exists”. It has one and only one value that is ().
在Scala中,Unit类似于Java的void关键字。 它用来表示“不存在任何值”。 它只有一个值() 。
A pure function is a function without any observable side-effects. That means it returns always same results irrespective how many times we call it with same inputs.
纯函数是没有任何可观察到的副作用的函数。 这意味着无论我们用相同的输入调用多少次,它始终返回相同的结果。
A pure function always gives same output for the same inputs.
纯函数始终为相同的输入提供相同的输出。
For Example:-
例如:-
scala> 10 + 20
res0: Int = 30
scala>
scala> 10 + 20
res0: Int = 30
Here “+” a pure function available in Int class. It gives same result 30 for same inputs 10 and 30, irrespective how many times we call it.
在这里,“ +”是Int类中可用的纯函数。 对于相同的输入10和30,无论我们调用多少次,它都会给出相同的结果30。
Both are used to perform computation, however they have one major difference in Functional Programming world.
两者都用于执行计算,但是它们在函数式编程世界中有一个主要区别。
A function is a computation unit without side-effect where as a Procedure is also a computation unit with side-effects.
函数是没有副作用的计算单元,而过程(Procedure)也是具有副作用的计算单元。
Scala’s Auxiliary constructor is almost similar to Java’s constructor with few differences.
Scala的辅助构造函数几乎与Java的构造函数相似,几乎没有区别。
Compared to Java’s constructors, Auxiliary constructors have the following few differences:
与Java的构造函数相比,辅助构造函数具有以下一些区别:
We can use ‘yield’ keyword in Scala’s for-comprehension construct. ‘for/yield’ is used to iterate a collection of elements and generates new collection of same type. It does not change the original collection. It generates new collection of same type as original collection type.
我们可以在Scala的for-comprehension构造中使用'yield'关键字。 “ for / yield”用于迭代元素集合并生成相同类型的新集合。 它不会更改原始集合。 它生成与原始集合类型相同类型的新集合。
For example, if we use ‘for/yield’ construct to iterate a List then it generates a new List only.
例如,如果我们使用“ for / yield”构造来迭代列表,则仅生成一个新的列表。
scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> for(l <- list) yield l*2
res0: List[Int] = List(2, 4, 6, 8, 10)
In Scala, for-comprehension construct has an if clause which is used to write a condition to filter some elements and generate new collection. This if clause is also known as “Guard”.
在Scala中,for-comprehension构造包含一个if子句,该子句用于编写条件以过滤某些元素并生成新的集合。 此if子句也称为“ Guard”。
If that guard is true, then add that element to new collection. Otherwise, it does not add that element to original collection.
如果该防护为真,则将该元素添加到新集合中。 否则,它不会将该元素添加到原始集合中。
Example:- For-comprehension Guard to generate only Even numbers into new collection.
示例:-对于综合警卫只能将偶数生成到新集合中。
scala> val list = List(1,2,3,4,5,6,7,8,9,10)
list: List[Int] = List(1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 , 10)
scala> for(l <- list if l % 2 =0 ) yield l
res0: List[Int] = List(2, 4, 6, 8, 10)
If we use Java 8’s Interface with Default methods, we will get Inheritance Diamond Problem. Developer has to solve it manually in Java 8. It does not provide default or automatic resolution for this problem.
如果我们将Java 8的Interface与Default方法一起使用,我们将得到Inheritance Diamond Problem。 开发人员必须在Java 8中手动解决它。它没有为该问题提供默认或自动解决方案。
In Scala, we will get same problem with Traits but Scala is very clever and solves Inheritance Diamond Problem automatically using Class Linearization concept.
在Scala中,我们会遇到与Traits相同的问题,但是Scala非常聪明,并使用类线性化概念自动解决了继承钻石问题。
In Scala, Pattern Matching follows Visitor Design Pattern. In the same way, Java’s ‘isinstanceof’ operator also follows Visitor Design Pattern.
在Scala中,模式匹配遵循游客设计模式。 同样,Java的“ isinstanceof”运算符也遵循“访客设计模式”。
That’s it all about “Scala Intermediate Interview Questions and Answers”. We will discuss some Advanced Scala Interview Questions and Answers in my coming posts.
关于“ Scala中级面试问答”的全部内容。 我们将在我的后续文章中讨论一些高级Scala面试问答。
Please drop me a comment if you like my post or have any issues/suggestions.
如果您喜欢我的帖子或有任何问题/建议,请给我评论。
翻译自: https://www.journaldev.com/9663/scala-interview-questions
scala面试问题