这里先看一个例子:下面这段代码,没有任何语法错误,但是在运行时会抛出异常:Error: cannot find class tag for element type T, 这是由于 Scala 和 Java 一样,都存在类型擦除,即泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉。对于下面的代码,在运行阶段创建 Array 时,你必须明确指明其类型,但是此时泛型信息已经被擦除,导致出现找不到类型的异常。
// 使用 <: 符号,限定 T 必须是 Comparable[T]的子类型
class Pair[T <: Comparable[T]](val first: T, val second: T) {
// 返回较小的值
def smaller: T = if (first.compareTo(second) < 0) first else second
}
// 测试代码
val pair = new Pair("abc", "abcd")
println(pair.smaller) // 输出 abc
public class Pair<T extends Comparable<T>> {
private T first;
private T second;
Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T smaller() {
return first.compareTo(second) < 0 ? first : second;
}
}
val pair1 = new Pair(10, 12)
val pair2 = new Pair(10.0, 12.0)
// Predef.scala
@inline implicit def intWrapper(x: Int) = new runtime.RichInt(x)
// 视图界定符号 <%
class Pair[T <% Comparable[T]](val first: T, val second: T) {
// 返回较小的值
def smaller: T = if (first.compareTo(second) < 0) first else second
}
// 隐式转换为 Ordered[T]
class Pair[T <% Ordered[T]](val first: T, val second: T) {
def smaller: T = if (first.compareTo(second) < 0) first else second
}
// 1.使用隐式参数隐式转换为 Comparable[T]
class Pair[T](val first: T, val second: T)(implicit ev: T => Comparable[T])
def smaller: T = if (first.compareTo(second) < 0) first else second
}
// 2.由于直接继承 Java 中 Comparable 接口的是特质 Ordered,所以也可以隐式转换为 Ordered[T]
class Pair[T](val first: T, val second: T)(implicit ev: T => Ordered[T]) {
def smaller: T = if (first.compareTo(second) < 0) first else second
}
object PairUtils{
def smaller[T](a: T, b: T)(implicit order: T => Ordered[T]) = if (a < b) a else b
}
class Pair[T](val first: T, val second: T) {
// 请注意 这个地方用的是 Ordering[T],而上面视图界定和类型约束,用的是 Ordered[T],两者的区别会在后文给出解释
def smaller(implicit ord: Ordering[T]): T = if (ord.compare(first, second) < 0) first else second
}
// 测试
val pair= new Pair(88, 66)
println(pair.smaller) //输出:66
// 1.定义一个人员类
class Person(val name: String, val age: Int) {
override def toString: String = name + ":" + age
}
// 2.继承 Ordering[T],实现自定义比较器,按照自己的规则重写比较方法
class PersonOrdering extends Ordering[Person] {
override def compare(x: Person, y: Person): Int = if (x.age > y.age) 1 else -1
}
class Pair[T](val first: T, val second: T) {
def smaller(implicit ord: Ordering[T]): T = if (ord.compare(first, second) < 0) first else second
}
object ScalaApp extends App {
val pair = new Pair(new Person("hei", 88), new Person("bai", 66))
// 3.定义隐式默认值,如果不定义,则下一行代码无法通过编译
implicit val ImpPersonOrdering = new PersonOrdering
println(pair.smaller) //输出: bai:66
}
object ScalaApp extends App {
def makePair[T](first: T, second: T) = {
// 创建以一个数组 并赋值
val r = new Array[T](2); r(0) = first; r(1) = second; r
}
}
import scala.reflect._
object ScalaApp extends App {
def makePair[T : ClassTag](first: T, second: T) = {
val r = new Array[T](2); r(0) = first; r(1) = second; r
}
}
// 首席执行官
class CEO
// 部门经理
class Manager extends CEO
// 本公司普通员工
class Employee extends Manager
// 其他公司人员
class OtherCompany
object ScalaApp extends App {
// 限定:只有本公司部门经理以上人员才能获取权限
def Check[T >: Manager](t: T): T = {
println("获得审核权限")
t
}
// 错误写法: 省略泛型参数后,以下所有人都能获得权限,显然这是不正确的
Check(new CEO)
Check(new Manager)
Check(new Employee)
Check(new OtherCompany)
// 正确写法,传入泛型参数
Check[CEO](new CEO)
Check[Manager](new Manager)
/*
* 以下两条语句无法通过编译,异常信息为:
* do not conform to method Check's type parameter bounds(不符合方法 Check 的类型参数边界)
* 这种情况就完成了下界限制,即只有本公司经理及以上的人员才能获得审核权限
*/
Check[Employee](new Employee)
Check[OtherCompany](new OtherCompany)
}
import java.util.Arrays;
// 实现 Comparable 接口
public class Person implements Comparable<Person> {
private String name;
private int age;
Person(String name,int age) {this.name=name;this.age=age;}
@Override
public String toString() { return name+":"+age; }
// 核心的方法是重写比较规则,按照年龄进行排序
@Override
public int compareTo(Person person) {
return this.age - person.age;
}
public static void main(String[] args) {
Person[] peoples= {new Person("hei", 66), new Person("bai", 55), new Person("ying", 77)};
Arrays.sort(peoples);
Arrays.stream(peoples).forEach(System.out::println);
}
}
输出:
bai:55
hei:66
ying:77
import java.util.Arrays;
import java.util.Comparator;
public class Person {
private String name;
private int age;
Person(String name,int age) {this.name=name;this.age=age;}
@Override
public String toString() { return name+":"+age; }
public static void main(String[] args) {
Person[] peoples= {new Person("hei", 66), new Person("bai", 55), new Person("ying", 77)};
// 这里为了直观直接使用匿名内部类,实现 Comparator 接口
//如果是 Java8 你也可以写成 Arrays.sort(peoples, Comparator.comparingInt(o -> o.age));
Arrays.sort(peoples, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
});
Arrays.stream(peoples).forEach(System.out::println);
}
}