Scala入门之高级类型:this.type

本文介绍Scala中使用this.type实现方法链调用的技术细节。通过实例展示如何在类中定义方法返回当前对象,从而方便地进行连续方法调用。

this.type

在写Spark程序的代码中一开始就能看到这代码:
    val conf = new SparkConf
    conf.setAppName("OnlineBlackListFilter").setMaster("local")
上面  setAppName、setMaster返回的就是SparkConf,所以才能继续使用SparkConf的方法点出方法来。
而要做到这一点的关键就是使方法的返回值是对象本身。
在SparkConf源码中是这样做的:
def setAppName(name: String): SparkConf = {
set("spark.app.name", name)
  }
其中set方法
def set(key: String, value: String): **SparkConf** = {
if (key == null) {
  throw new NullPointerException("null key")
}
if (value == null) {
  throw new NullPointerException("null value for " + key)
}
logDeprecationWarning(key)
settings.put(key, value)
**this**
 }  
从中可以看出它返回的是SparkConf。而这情况其实也可以另外的方式写出来,这就是this.type
通过例子来讲,如下
/**
  定义食物这个类,里面有食物的名字还有年龄
 */
class Food{
  var name: String = _
  var age: Int = _
  def setName(getName: String) = {
    this.name = getName
    *this*
  }
  def setAge(getAge: Int)= {
    this.age = getAge
    *this*
  }
}
object ThisType extends App{
  //
  val food = new Food
  food.setName("rice").setAge(2)
}

上面代码在方法的最后一行都是用的this,意味着返回自身对象。不过这方式如果有继承结构的话,子类这方式调用会有问题。完整代码如下:

package com.dt.scala.moguyun

/**
  * Created by hlf on 2016/8/9 for learn this.type.
  */
object ThisType extends App{
  //食物点出来
  val food = new Food
  food.setName("rice").setAge(2)
  println("Food : " + food)
  //大米点出来
  val rice = new Rice
  //这是没问题的因为返回的是Food
  rice.setName("guangxidami").setAge(3)
  //这样也没问题,setgrow()返回大米这个对象,可以调用父类的setName,setAge方法
  rice.setgrow().setName("beijingdami").setAge(1)
  //这样在没修改返回类型为this.type之前是有问题的,因为setName,setAge返回的是食物这个类,
  //食物没有setgrow()这个方法
  rice.setName("zhejiangdami").setAge(4).setgrow()
  println("Rice : " + rice)
}
/**
  定义食物这个类,里面有食物的名字还有年龄
 */
class Food{
  private var name: String = _
  private var age: Int = _
  def setName(getName: String): this.type = {
    this.name = getName
    this
  }
  def setAge(getAge: Int): this.type = {
    this.age = getAge
    this
  }
  /*
  def setName(getName: String) = {
    this.name = getName
    this
  }
  def setAge(getAge: Int)= {
    this.age = getAge
    this
  }
   */

  override def toString: String = "name = " + name + "||=|| age = " + age
}

/**
  * 定义一个大米类继承食物,里面方法返回的this是大米这个对象
  */
class Rice extends Food{

  def setgrow() ={
    println(" I am growing!! Don't eat me :(")
    this
  }
}
从此可以看出在方法返回类型上使用this.type就可以写出像链条一样的代码,不断地点出来:)
java.lang.ArrayIndexOutOfBoundsException: 1 (JTeachers.java:24) (JavaRDDLike.scala:143) (JavaRDDLike.scala:143) (Iterator.scala:434) (Iterator.scala:440) (ExternalSorter.scala:191) (SortShuffleWriter.scala:63) (ShuffleMapTask.scala:96) (ShuffleMapTask.scala:53) (Task.scala:108) (Executor.scala:335) (ThreadPoolExecutor.java:1142) (ThreadPoolExecutor.java:617) (Thread.java:745) (TID 0, localhost, executor driver): java.lang.ArrayIndexOutOfBoundsException: 1 (JTeachers.java:24) (JavaRDDLike.scala:143) (JavaRDDLike.scala:143) (Iterator.scala:434) (Iterator.scala:440) (ExternalSorter.scala:191) (SortShuffleWriter.scala:63) (ShuffleMapTask.scala:96) (ShuffleMapTask.scala:53) (Task.scala:108) (Executor.scala:335) (ThreadPoolExecutor.java:1142) (ThreadPoolExecutor.java:617) (Thread.java:745) Driver stacktrace: (DAGScheduler.scala:1499) (DAGScheduler.scala:1487) (DAGScheduler.scala:1486) (ResizableArray.scala:59) (ArrayBuffer.scala:48) (DAGScheduler.scala:1486) (DAGScheduler.scala:814) (DAGScheduler.scala:814) (Option.scala:257) (DAGScheduler.scala:814) (DAGScheduler.scala:1714) (DAGScheduler.scala:1669) (DAGScheduler.scala:1658) (EventLoop.scala:48) (DAGScheduler.scala:630) (SparkContext.scala:2022) (SparkContext.scala:2043) (SparkContext.scala:2062) (SparkContext.scala:2087) (RDD.scala:936) (RDDOperationScope.scala:151) (RDDOperationScope.scala:112) (RDD.scala:362) (RDD.scala:935) (JavaRDDLike.scala:361) (JavaRDDLike.scala:45) (JTeachers.java:31) (Native Method) (NativeMethodAccessorImpl.java:62) (DelegatingMethodAccessorImpl.java:43) (Method.java:498) (SparkSubmit.scala:784) (SparkSubmit.scala:188) (SparkSubmit.scala:213) (SparkSubmit.scala:127) (SparkSubmit.scala) Caused by: java.lang.ArrayIndexOutOfBoundsException: 1 (JTeachers.java:24) (JavaRDDLike.scala:143) (JavaRDDLike.scala:143) (Iterator.scala:434) (Iterator.scala:440) (ExternalSorter.scala:191) (SortShuffleWriter.scala:63) (ShuffleMapTask.scala:96) (ShuffleMapTask.scala:53) (Task.scala:108) (Executor.scala:335) (ThreadPoolExecutor.java:1142) (ThreadPoolExecutor.java:617) (Thread.java:745)
最新发布
11-27
`java.lang.ArrayIndexOutOfBoundsException: 1` 异常表明程序试图访问数组中索引为 1 的元素,但该数组的长度可能小于 2,即数组越界访问,通常发生在试图访问的索引值小于 0 或大于或等于数组的实际长度时[^2]。在提供的代码中,问题可能出现在 `line.split(" ")` 之后,若某一行数据没有分隔符或者分隔后数组长度不足 2,就会引发此异常。 以下是修改后的代码,添加了对数组长度的检查: ```java package step2; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import scala.Tuple2; import java.util.Arrays; import java.util.List; public class JTeachers { public static void main(String[] args) { SparkConf conf = new SparkConf().setMaster("local").setAppName("JTeachers"); JavaSparkContext sc = new JavaSparkContext(conf); String dataFile = "file:///root/step2_files"; // 第一步:以外部文件方式创建RDD JavaRDD<String> lines = sc.textFile(dataFile); // 第二步:将文件中每行的数据切分,得到自己想要的返回值 JavaPairRDD<String, Integer> pairs = lines.flatMapToPair(line -> { String[] parts = line.split(" "); if (parts.length >= 2) { try { return Arrays.asList(new Tuple2<>(parts[0], Integer.parseInt(parts[1]))).iterator(); } catch (NumberFormatException e) { // 处理无法转换为整数的情况 return Arrays.asList().iterator(); } } return Arrays.asList().iterator(); }); // 第三步:将相同的key进行聚合 JavaPairRDD<String, Integer> result = pairs.reduceByKey((x, y) -> x + y); // 第四步:将结果收集起来 List<Tuple2<String, Integer>> output = result.collect(); // 第五步:输出 for (Tuple2<String, Integer> tuple : output) { System.out.println("(" + tuple._1() + "," + tuple._2() + ")"); } sc.stop(); } } ``` 在上述代码中,添加了对 `parts` 数组长度的检查,确保其长度至少为 2 才进行后续操作。同时,使用 `try-catch` 块捕获 `NumberFormatException` 异常,处理无法将字符串转换为整数的情况。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值