与Java类似,Kotlin的类也有类型参数(泛型):
class Box(t: T) {
var value = t
}
一般情况,使用泛型实例,需要类型参数:
val box: Box = Box(1)
如果类型参数可推断出来,可省略类型参数:
val box = Box(1) // 1是Int,编译器可推断出Box
Java泛型的一个例子:
interface Source {
//只有生产者方法,没有消费者方法
T nextT();
}
void demo(Source strs) {
//Source没有消费者方法,型变是安全的,但是Java并不知道,所以仍然禁止!
//需要声明类型为Source extends Object>,这是毫无意义的,更复杂类型并没有带来价值!
Source objects = strs; //错误:在Java中不允许型变
}
1.out修饰符
在Kotlin中,可用out修饰类型参数T,确保T只能输出(生产),不被消费!
out修饰符称为型变注解(variance annotation),使类型参数协变(covariant)!
abstract class Source {
abstract fun nextT(): T
}
fun demo(strs: Source) {
val objects: Source = strs //可以型变,因为T是out
}
2.in修饰符
用in修饰类型参数T,确保T只能被消费,不能输出(生产),使类型参数逆变(contravariance)!
abstract class Comparable {
abstract fun compareTo(other: T): Int
}
fun demo(x: Comparable) {
//1.0拥有Double类,是Number的子类
x.compareTo(1.0)
//Double是Number的子类,父类Number可以被Double消费
val y: Comparable = x
}
助记符:消费者-输入in, 生产者-输出out
由于in/out在类型参数声明处,所以称为声明处型变(Declaration-site variance)
4.使用处型变(Use-site variance)/类型投影(Type projections)
类型参数T既不是协变,也不是逆变(T既生产out,又消费in):
class Array(val size: Int) {
fun get(index: Int): T {...} //生产out
fun set(index: Int, value: T) {...} //消费in
}
fun copy(from: Array, to: Array) {
assert(from.size == to.size)
for (i in from.indices)
to[i] = from[i]
}
val ints: Array = arrayOf(1, 2, 3)
val anys = Array(3) { "" }
copy(ints, anys) //错误:期望(Array, Array)
1.out,确保from中的Any只生产输出,不被消费,对应于Java的Array extends Object>:
fun copy(from: Array, to: Array) {
...
}
2.in,确保dest中的String只能被消费,不生产输出,对应于Java的Array super String>
fun fill(dest: Array, value: String) {
...
}
5.星投影<*>(Star-projections)
如果对类型参数一无所知,可用星投影:
1.对于Foo,T是一个具有上界TUpper的协变类型参数,Foo<*>等价于Foo,
当T未知时,可以安全地从Foo<*>读取TUpper的值
2.对于Foo,T是一个逆变类型参数,Foo<*>等价于Foo,
当T未知时,没有什么方式可以安全写入Foo<*>
3.对于Foo,T是一个具有上界TUpper的不型变类型参数,
Foo<*>在读取值时等价于Foo,在写入值时等价于Foo
如果有多个类型参数,则每个类型参数都可单独投影:
interface Function
Function<*, String> 表示Function
Function 表示Function
Function<*, *> 表示Function
注意:星投影非常像Java的原始类型,但是安全!
6.泛型函数
和java类似, kotling不仅类有泛型,函数也有泛型:
//普通函数
fun singletonList(item: T): List {
// ……
}
//扩展函数
fun T.basicToString() : String {
// ……
}
//调用泛型函数,在函数名后指定类型参数
val l = singletonList(1)
7.泛型约束
最常见的约束类型是,与Java的 extends T>对应的上界:
//>冒号之后指定类型上界,只有Comparable子类型可以替代T
fun > sort(list: List) {
}
sort(listOf(1, 2, 3)) //Int是Comparable子类型
sort(listOf(HashMap())) //错误: HashMap不是Comparable>子类型
默认上界是Any?,<:上界>中只能指定一个上界,如果同一类型参数需要多个上界,需要一个单独的where子句:
fun cloneWhenGreater(list: List, threshold: T): List
where T : Comparable, T : Cloneable {
return list.filter { it > threshold }.map { it.clone() }
}
视图控制层代码demo如下:
@Controller
@RequestMapping("/")
public class MessageController {
private final MessageRepository messageRepository;
@Autowired
public MessageController(Mes
作为一名
Linux SA,日常运维中很多地方都会用到脚本,而服务器的ip一般采用静态ip或者MAC绑定,当然后者比较操作起来相对繁琐,而前者我们可以设置主机名、ip信息、网关等配置。修改成特定的主机名在维护和管理方面也比较方便。如下脚本用途为:修改ip和主机名等相关信息,可以根据实际需求修改,举一反三!
#!/bin/sh
#auto Change ip netmask ga