异常
回顾下Java中的异常类型
|- Throwable
|- Error 系统底层错误,无法处理
|- Exception 应用异常,可以处理
|- RuntimeException 运行时异常
|- 非RuntimeException 检查时异常
scala 中的异常和Java中的一致,调用的都是Java的中异常类
package object scala extends scala.AnyRef {
type Throwable = java.lang.Throwable
type Exception = java.lang.Exception
type Error = java.lang.Error
type RuntimeException = java.lang.RuntimeException
type NullPointerException = java.lang.NullPointerException
type ClassCastException = java.lang.ClassCastException
//..../
}
常见的异常类型
NullPointerException
常见错误,不接受反驳ClassCastException
类型转换异常ArrayIndexOutOfBoundsException
下标越界异常ClassCastException
类型转换异常
Scala中异常处理
消极处理
抛出异常
- java语法:
throw 异常.... throws 声明抛出异常
- scala语法:
throw 异常...
object Exception01 {
def main(args: Array[String]): Unit = {
f1()
}
def f1(): Unit ={
println("start ...")
// 手动抛出异常
throw new java.lang.RuntimeException("程序错误...")
println("end ...")
}
}
积处理
语法:try ... catch .. finally
package exceptions
object Exception02 {
def main(args: Array[String]): Unit = {
try {
// 积极处理
println("start ....")
var m: Int = 1 / 0
println("end ....")
} catch {
// 模式匹配的语法 case 类型
case e0: ArithmeticException => e0.printStackTrace()
case e1: RuntimeException => println("runtime exception")
case e2: Exception => println("exception ...")
case _ => println("other ...")
} finally {
println("finally ...")
}
}
}
异常应用 scala jdbc
package execptions
import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}
import scala.collection.mutable.ArrayBuffer
import scala.util.Properties
/**
* 连接JDBC
* JDBC 五大步骤
*/
object JDBCTest extends App {
var conn: Connection = null
var statement: PreparedStatement = null
var users: ArrayBuffer[User] = null
var set: ResultSet = null
try{
Properties.setProp("scala.time", "true")
Class.forName("com.mysql.jdbc.Driver")
conn = DriverManager.getConnection("jdbc:mysql://localhost/test","root","1234")
statement = conn.prepareStatement("select * from t_user")
users = new ArrayBuffer[User]()
set = statement.executeQuery()
while (set.next()) {
val user: User = new User
val id = set.getInt("id")
val name = set.getString("name")
val sex = set.getBoolean("sex")
user.id = id
user.name = name
user.sex = sex
users += user
}
}
if(set != null) set.close()
if(statement != null) statement.close()
if(conn != null) conn.close()
users.foreach(println)
}
// -------------------------实体类------------------------
package execptions
class User {
var id: Int = _
var name: String =_
var sex: Boolean = _
override def toString = s"User($id, $name, $sex)"
}
隐式转换
隐式转换函数(implicit conversion function)指的是以implicit关键字声明的带有单个参数的函数。这样的函数将被自动应用,将值从一种类型转换为另一种类型。隐式转换函数叫什么名字是无所谓的,因为通常不会由用户手动调用,而是由Scala进行调用。但是如果要使用隐式转换,则需要对隐式转换函数进行导入(import
)。因此通常建议将隐式转换函数的名称命名为“one2one”的形式。
常用使用方式:
- 隐式值
- 隐式参数
- 隐式函数
- 隐式增强
- 隐式类
Scala会考虑如下位置的隐式转换函数:
- 位于源或目标类型的伴生对象中的隐式函数
- 位于当前作用域可以以单个标识符指代的隐式函数
隐式转换在如下三种不同情况下会被考虑:【知道】
- 当表达式类型与预期类型不同时【隐式值的使用】
- 当对象访问一个不存在成员时【隐式增强】
- 当对象调用某个方法,而这个方法的参数声明与传入参数不匹配时【隐式函数】
有三种情况编译器不会尝试使用隐式转换: 【知道】
- 如果代码能够在不使用隐式转换的前提下通过编译,则不会使用隐式转换
- 编译器不会尝试同时执行多个转换
- 存在二义性的转换是错误
隐式值
package implicits
object ImplicitValue01 extends App {
implicit var name: String = "张三"
implicit var age: Int = 18
// 获取类型为String 的隐式值
val zs = implicitly[String]
println(zs)
val zsage = implicitly[Int]
println(zsage)
}
隐式参数
总结: 所谓隐式参数,指scala在编译不通过时,在当前类或者作用域中寻找隐式参数同类型的隐式值,赋予隐式参数,完成函数处理;
package implicits
/**
* 隐式参数
* 柯里化函数,当参数不匹配的时候会去作用域中寻找类型相同的隐式参数
* 参数符合的时候就不会查找隐式参数
*/
object ImplicitValue02 extends App {
implicit val num: Int = 10
println(sum(5)) // 15
println(sum(5)(20)) // 25
def sum(x: Int)(implicit y: Int) = x + y
}
隐式函数
总结:所谓的隐式函数,指scala在编译不通过时,自动尝试将一个中类型转换为另外的一种类型;
package implicits
/**
* 隐式函数
* 编译时函数形参匹配不通过时,自动尝试将类型转为另一种类型
*/
object ImplicitValue03 extends App {
val student = new Student
student.run(1)
// 需要指定返回值类型 返回值类型只有在编译时候才会被推断
// 要指定返回值类型使隐式函数自动根据类型调用
implicit def intToString(num: Int): String={
num + ""
}
// 同类型只能有一个
/*implicit def intToString1(num: Int): String={
num + ""
}*/
}
class Student{
def run(name: String): Unit ={
printf("%s 在跑 \n",name)
}
}
隐式增强
通过隐式转换增强某一个类的功能
package implicits
/**
* 增强man,使man具有fly方法
*/
object ImplicitValue04 extends App {
private val man = new Man
man.fly
// 传递一个man 返回一个supperMan对象
implicit def manToSupperMan(man: Man): SupperMan ={
new SupperMan
}
}
class Man
class SupperMan{
def fly(): Unit ={
println("supperMan fly...")
}
}
隐式类
implicit修饰的特殊类,注意不能独立声明,需要定义在一个类\对象的内部
package implicits
/**
* 隐式类
* 对类进行增强
*/
object ImplicitValue05 {
def main(args: Array[String]): Unit = {
val man = new Man2("lisi")
man.fly
}
implicit class Boss(man: Man2){
var name: String = _
this.name = man.name
def fly() = println(name + " fly ...")
}
class Man2(var name:String)
}
隐式转换的导入
如何使用当前类以外的隐式转换呢?
导入外部类中的隐式值
package implicits
/**
* 获取 外部类中的隐式值
*/
object ImplicitValue06 extends App {
// 类需要new 创建对象
val aa = new A
import aa._
private val i: Int = implicitly[Int]
println(i)
class A{
implicit def num: Int = 5
}
}
导入外部对象中的隐式方法
package implicits
/**
* 获取外部对象的隐式值
*/
object ImplicitValue07 extends App {
import Bb._
run(1)
def run(name :String)={
println(name + " is running...")
}
}
object Bb{
implicit def intToString(num: Int):String={
num + "lisi"
}
// 隐式方法重载
implicit def intToString(num: Double):String={
num + "lisi"
}
}