Kotlin开发Android
Kotlin开发Android《第一行代码》
- Kotlin简单语法
- 变量
- 1. 关键字var和val
- 2.不必显式声明变量类型
- 3. 变量的类型
- 函数
- 函数的定义
- 语法糖
- 流程控制
- 条件控制
- if
- when
- 循环
- while
- for- in
- Kotlin 面向对象的编程语言
- 类与对象
- 普通类
- 类的继承
- 构造函数
- 主构造函数
- 次级构造函数
- 接口
- 可见性
- 数据类
- 单例类
- Lambda表达式
- JAVA函数式API
- 空指针
- ?
- ?.
- ?:
- !!
- let
- 字符串内嵌表达式
- 函数设置参数默认值
- 延迟初始化
- 密封类
看书总是觉得都懂了,实际操作二百五,试着默写出来才是真的懂,就是写写有点累。
主要是看(郭霖的《第一行代码》第三版)
Kotlin简单语法
变量
1. 关键字var和val
1.var 和val的区别
var:可以改变的变量
val :第一次赋值后,无法进行更改的变量
注意:当变量赋值的时候,首先选择val进行,如果val不满足要求的情况下才选择var,这样能够使得代码更加健壮。
var a=10
a=20 //正确 变量可变所以可以
val b=20
b=20 //错误 不可变的变量 再次进行赋值操作
2.不必显式声明变量类型
kotlin 具备强大的推导能力,所以变量的定义的时候无需显示声明。
但是延迟赋值的时候,就需要显示声明了,声明的方法是 变量名后面:加类型
延迟赋值:通常使用了lateinit ,在对象的属性声明的时候不初始化,在用到的时候再初始化。
val a=10 //kotlin 推导得出a是Int类型
val b:Int =10;//显式声明Int类型,并赋值10,这时候不需要进行推导了,但是这里的显式申明可要可不要
3. 变量的类型
如上面例子所示,和java相比,Int 是大写的,这代表Kotlin放弃了基础数据类型,全部选择的是对象数据类型。Int,Long,Short,Float,Double,Boolean,Byte,Char
函数
函数的定义
函数的定义fun关键字+函数名+(参数:变量类型)+:返回值类型+函数体。无返回值时不需要声明返回值类型。
//无返回值
fun saySomething(msg:String){ print(msg)
}
//多参数
fun saySomething(msg:String,name:String){ print(name+"说"+msg)
}//有返回值
fun saySomething(msg:String):Int{ print(msg)return 1
}
语法糖
当函数只有一条语句的时候,直接写在函数的后面用等号连接
//语法糖版本
fun saySomething(msg:String)= print(msg)
流程控制
条件控制
if
if 语句和大多数的语言里面的if语句相类似,唯一新增了一个就是可以有返回值,返回值是每个条件里面的最后一行。
//传统写法
fun largerNumber(num1:Int,num2:Int):Int{var max=0;if (num1>num2){max= num1 } else{max=num2}return max
}//新特性的改写
fun largerNumber(num1:Int,num2:Int):Int{if (num1>num2){num1 } else{num2}
}//语法糖 因为只有一句语句( if和else是整体,结果就是返回一个值) ,套用上面的语法糖所以可以用等号连接
fun largerNumber(num1:Int,num2:Int):Int= if (num1>num2) num1 else num2//当然既然采用了语法糖用等于号连接,那么也可以省略显式声明,让kotlin自己推导类型
fun largerNumber(num1:Int,num2:Int)= if (num1>num2) num1 else num2
when
类似于switch,但是强于switch,变量不只局限于整形或者是字符串。而且不需要break语句。 【匹配值】->{执行逻辑},当执行逻辑只有一行代码,{}可以省略不写。而且when和if一样也是可以有返回值的,
//传统写法
fun getScore(name:String):Int {var score =0when(name){"Tom"->{ score =66 } //不省略{}写法"ANN"-> score =90 //省略写法else -> score =0}return score
}//语法糖写法 when整体是一个语句
fun getScore(name:String)= when(name){"Tom"->66"ANN"-> 90else -> 0
}//不带参数的when写法
fun getScore(name:String)= when(){name=="Tom"->66 // 前面写匹配的条件 name== "ANN"-> 90else -> 0
}
when 还支持类型的匹配,其中关键字is.
Number 是抽象类,Int之类和数字相关的类都是它的字类
fun checkNumber(num:Number){when(num){is Int -> println(" is Int")is Double -> println(" is Double ")else -> println(" other Type ")}
}
循环
while
这个写法和java中一样的,或者是C啥的,只要有基础的都知道,所以直接来个例子吧
fun main(){var i=1;while(i<10) {print("第"+i+"次")i=i+1}}
do-while 和while的区别。
do-while语句不管条件是否满足,肯定执行一次。而while是只有条件满足才会进入。
fun main(){var i=10;do {print("当前i="+i)}while (i<9)
}
for- in
和java中常用的for-i循环不同,kotlin舍弃了这个循环,增强了for-each循环这个模式,也就是现在的for-in循环,能够满足大多数的场景,如果遇到不满足的场景可以选择while语句进行实现。
fun main(){for ( i in 1..10){//..为关键字,1..10 代表创建了 [1,10]闭区间的,并且默认步长为1,可以省略,也就是i的递增顺序是 i=i+1println("当前"+i)}}//写完整
fun main(){for ( i in 1..10 step 1){ // step 关键字,步长。当然可以设置其他的数字,用来跳过某些值println("当前"+i)}}// 当遇到长度为10的数组,其实下标是[0,10) 也就是左闭右开,用until
fun main(){for ( i in 0 until 10 ){ //同样省略步长 默认为1,用until关键字就是创建了 [0,10)区间println("当前"+i)}}//刚刚的例子是递增,那么有时候要递减 downTo
fun main(){for ( i in 10 downTo 0 ){ //downTo ,创建了两端闭合降序的[10,0]区间println("当前"+i)}}
Kotlin 面向对象的编程语言
类与对象
普通类
class 关键字,和java一样的,唯一的不同的,当实例化的时候,不需要new关键字,调用 val person =Person(); 用val是因为,我们首选应当是val,当val不满足才选用var
class Person {var name="" ;var age =0 ;
}
类的继承
和java不同,java里面的类默认是可以继承的,但是kotlin里面,只有写有关键字open的类能继承,当然抽象类肯定是可以继承。
改写Peson类
open class Person {var name="" ;var age =0 ;
}
然后创建Student 类去继承
class Student :Person(){var sno=""var grade=0}
这时候会发现:是继承的关键字,但是为什么是Person(),咋比java多了个()呢?
这涉及到了主构造函数,和次级构造函数,我们现在记住一个死理
首先一定要知道,当子类去继承父类的时候,子类的构造函数一定要调用父类的构造函数。
构造函数
一个类有两种构造函数,主构造函数,次级构造函数,类会默认带有一个无参的主构造函数。
同时kotlin规定了一个类只能有一个主构造函数,但是能有多个次构造函数。
注意点:只能有一个主构造函数,代表可以有0个或者1个主构造函数。
多个次构造函数,代表可以有0到多个。
(不是说默认带着无参的主构造函数吗?为什么又可以0个,0个就是当你没显式声明主构造函数的参数,但是又定义了次级构造函数。简单而言,相当于默默无闻的主构造函数被高调的次级构造函数,顶替了,只有当高调的主构造函数,才能不被次级构造函数给顶替)。
所以厉害关系排行榜
显式声明的主构造函数>次级构造函数>默认的主构造函数
(默认的主构造函数相较于前两者,更特别一点,它一旦遇到更厉害的角色出现,就被顶替消失了)
主构造函数
每个类默认会带有一个无参数的主构造函数,但是主构造函数也可以显示的声明参数,参数写的位置就在类名的后面。如果显示声明了参数,之后调用的话,就要传入参数了。
主构造函数重要的是,它是没有函数体的。如果想要主构造函数执行某些代码,必须采用init关键字。
open class Person { //其实自带一个Person()的主构造函数var name="" ;var age =0 ;
}// 显示声明主构造函数的参数
open class (val name:String,val age:Int) {//其实自带一个Person()的主构造函数,你会发现我没有在类里面定义name和age字段了//因为写在主构造函数里面的传入参数,如果前面带有val或者var关键字自动会变成类的字段的}//由于主构造函数没有函数体,那我们想用主构造函数构造的时候还要执行某些语句怎么办
//那么有 init结构体,专门为主构造函数设计的open class Person(val name:String,val age:Int) {init {print("初始化")}
}
那么现在再来看原来的代码下图为例,是不是就好理解很多。
1 Person类里面没有次级构造函数,Person类后面没跟()说明没显示声明主构造函数,所以拥有一个自带无参数的主构造函数。
2. Student 类里面的: 表达了 Student继承了Person类
3. Student 和Person类情况一样,只有默认的主构造函数。
(同时要知道,继承的话子类必须实现父类的构造函数,现在子类只有默认的主构造函数,父类也是默认的主构造函数,所以子类的主构造函数必须实现父类的主构造函数)
4.class Student :Person() 里面的() 代表 Student默认的主构造函数去实现了Person里面的默认的主构造函数。
所以方便记忆的话,可以当类的:后面出现()的时候就代表了是子类的主构造函数,在实现父类的某一个构造函数。那到底是实现的是父类哪一个构造函数呢?就看()里面的参数,和哪个对的上就是哪个。
open class Person { //其实自带一个Person()的主构造函数var name="" ;var age =0 ;
}class Student :Person(){ //子类一定要调用父类的构造函数,父类的构造函数只有Person()var sno=""var grade=0}
同理当父类显示声明了主构造函数的参数的话呢?
open class Person(val name:String,val age:Int) {//只有一个主构造函数 Person(name,age)init {print("初始化")}
}//当Person变成上面这样的话,这样固然可以,但是每个人都是一样的名字了
class Student :Person("小小","12"){var sno=""var grade=0
}//较为正确的应该是,构造Student的时候,输入学号,年级,名字和年龄。但是很奇怪的是,为什么name和age这两个字段咋前面没有变量的标识符,val或者var呢?
//因为之前说了如果写在主构造函数里面用val和var,就默认变成这个类的字段,那么Student里面S有name和age字段了,但是Person不是也有age和name吗,会冲突的。
//所以只是让它前面没有标识符,作用域只在主构造函数里面。
class Student(val sno:String,val grade:Double,name:String,age:Int) :Person(name,age){}
次级构造函数
constructor 关键字定义,当既有主构造函数,又有次级构造函数时候。次级构造函数必须直接或者间接的调用主构造函数。
所以在这
次级构造函数 --》 主构造函数 --》父构造函数
(这个调用满足俩要求,次级构造函数必须直接或者间接的调用主构造函数,子构造函数必须实现主的构造函数)
主构造函数 --》父构造函数 (子构造函数必须实现父的构造函数)
class Student(val sno:String,val grade:Double,name:String,age:Int) :Person(name,age){constructor( sno:String,grade:Double,name:String):this(sno,grade,name,0){//构造函数1 ,直接调用主构造函数}constructor( sno:String,name:String):this(sno,2.0,name){//构造函数1 ,间接调用主构造函数}
}
特殊例子,有次级构造函数,但是没显示声明主构造函数,所以只有次级构造函数。没有主自然不调用。
Student 是继承Person 类的,那么子构造函数必须实现父的构造函数,那么自然就是这个次级构造函数,直接去继承父亲的构造函数了。
class Student :Person {var sno="";var grade=0.0;constructor( //次级构造函数里面不能有var和val,那么自然也无法自动生成字段,那么只能在类里面手动定义了。sno:String,grade:Double,name:String,age:Int):super(name,age){}}
接口
kotlin的接口中支持,对函数的默认实现。
interface Study {fun readBooks()fun doHomeWork(){ //函数的默认实现println("做作业")}}
类对接口的实现也是用:关键字,然后可以发现没有对doHomeWork函数进行实现,因为Study 接口中有默认实现,所以不实现是不会报错的。但是如果readBooks函数没进行重写实现,那么就会报错的,因为接口中这个方法是没有实现的。
Kotlin中使用override关键字来重写父类和实现接口中的函数。
class Student(name:String,age:Int) :Person(name,age),Study{var sno="";var grade=0.0;constructor( ):this("小小",1){}override fun readBooks() {println("读书");}
}
可见性
Kotlin的默认可见性是Public。
//没写可见性open class Person(val name:String,val age:Int) {init {print("初始化")}
}//上面等同,但是多此一举了
public open class Person(val name:String,val age:Int) {init {print("初始化")}
}
数据类
数据类,只要前面写上data关键字,其实Kotlin 默认实现了 equals(),hashCode(),toString()方法
//由于这个类里面没有其他代码的时候,就可以省略掉大括号了
//相信你们应该还记得吧 主构造函数里面出现了var 或者val 代表着这个字段就是这个类的字段(属性)
data class Cellphone(var name:String,var price :Double)
单例类
全局只有最多拥有一个实例的单例类,只需要object关键字就行。
object Singleton {fun doText(){ //里面定义的方法print("测试")}
}
调用单例类的方法很简单,有点像是调用静态方法
Singleton .doText();//但是实际上 kotlin给我们在背后创建了实例,而且全局有且只有一个实例。
Lambda表达式
Lambda是一小段可以作为参数传递的代码片段。什么意思呢,通常写函数的时候,我们定义的参数是Int,String 啊之类的,但是现在写函数的时候我们可以选择传入的参数是一个Lambda的表达式,(也就是一小段代码作为参数)。实不相瞒,个人认为这个东东很像回调函数。
Lambda式子的语法结构,函数体中最后一行代码就是lambda的返回值
{参数名1:参数类型,参数名字:参数类型 -> 函数体}
以一个我写的无病呻吟的一个传入参数是Lambda表达式的函数textLambda为例子。
//参数名为test 然后参数的类型是 一个Lambda表达式
//并且这个Lambda 会有一个String类型的传入参数,和Int类型的返回值
//也就是说 这个函数已经规定了这个Lambda 传入参数是什么类型,返回值是什么类型。
fun textLambda(test:(String) -> Int){val str1="aaa"val num= test(str1)if (num>5) print("短字符串")else print("长字符串")
}
那么调用的时候,我就要传入一个符合这个函数要求的lambda表达式
//调用的时候,str1:String-> 8 就是我写的lambda表达式
//lambda表达式中 有textLambda传给我的str1这个参数,但是我没用到
//结果 输出 短字符串
textLambda ({str1:String-> 8})// 用传给我的字符串的长度作为返回值
//判定结果 长字符串
textLambda ({str1:String-> str1.length})//kotlin规定 当lambda参数是函数的最后一个参数,可以将表达式移到()后面
textLambda (){str1:String-> str1.length}
//当 lambda参数是函数的唯一一个参数的时候,可以省略掉()
textLambda {str1:String-> str1.length}//kotlin的推导机制,可以让我们省略掉lambda参数列表的类型声明
textLambda {str1-> str1.length}
//当只有lambda只有一个参数的时候,参数名称可以不写 直接用it指代
textLambda {it.length}
通过以上的例子就会发现,其实Lambda表达式和Int之类的没什么区别,Int代表的是一个值,但是Lambda代表的是一段代码罢了。对于参数是Lambda表达式的函数而言,它会告诉你它要一个Lambda表达式,然后这个表达式中它会告诉你,它将会给你一个什么类型的参数,然后它需要你返回给它一个什么类型的结果。至于中间的过程它一概不管。
JAVA函数式API
当kotlin调用java代码的时候,也可以使用JAVA函数式API。但是要满足以下条件:**调用的java方法接收一个java单抽象方法的接口参数。**以上的句子很难懂但是没关系,例子来解释,Android的java开发中经常要开线程,Thread方法很熟悉吧,就以他为例子。
解释:
java代码中,看下定义:Thread 方法,参数是Runnable 类型的参数public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}
再看下Runnable 的定义,会发现它是一个接口,并且只有一个抽象方法也就是run方法。
public interface Runnable {public abstract void run();
}
那么Thread方法它就是满足上面那段话的,首先Thread 是一个java方法,并且它接收的参数Runnable是一个接口,然后这个接口里面有一个抽象方法。
所以说当kotlin中调用Thread方法中那个接口参数的单抽象方法可以写成Lambda表达式
实战
//java中调用thread的写法(匿名类的写法)new Thread(new Runnable() {@Overridepublic void run() {System.out.println("线程");}});// 原模原样改造成kotlin的话,没有new关键字,方法的关键字是fun(匿名类的写法采用了object关键字)
Thread(object: Runnable {override fun run() {print("线程");}})
// 但是刚才说了,这个 Thread是满足java函数式api的,也就是说可以简写,因为只有Runnable只有一个待实现方法,所以可以不显示重写run方法
Thread( Runnable {print("线程");}) // Thread方法里不沉溺在一个以上的java单抽象方法接口参数,可以省略接口名字
Thread( {print("线程");})// lambada表达式是方法的最后一个参数
Thread() {print("线程")} // lambada表达式只有一个lambada表达式的参数,省略括号Thread{print("线程")}
这里的java函数式API的使用,都是限定于从kotlin中调用java方法,并且单抽象方法也必须用java语言定义的。
空指针
kotlin默认的是变量不为空。
?
fun doStudy(study:Study){ //这里的study参数传空就会报错
}
如果想要空,后面加上一个?,表示可以为空,但是这时候需要自己把空异常都处理掉。
fun doStudy(study:Study?){ //这里的study参数传空就会报错
}
?.
代表当对象为空不做任何事情,当对象不为空调用方法
例如
if(a!=null){
a.doSomething()
}//可以变成a?.doSomething()
?:
val c=a?:b //意思是当a不为空 返回a,但是当a为空返回b
!!
非空断言,当可为空的全局变量的时候,在不为空的时候才调用某个方法,但是kotlin没办法知道
var content:String?="hello"
fun main(){if(content!=null){doUpperCase()}}
fun doUpperCase(){content.toUpperCase(); //代码会异常
}
采用!!,告诉kotlin 这个我自己确定不为空,有异常的话我来解决。
var content:String?="hello"
fun main(){if(content!=null){doUpperCase()}}
fun doUpperCase(){content!!.toUpperCase();
}
let
一个函数,提供了函数式api接口,并将原始调用对象作为参数传递到lambda表达式里面。它配合?.可以发挥很大作用。而且let可以处理全局变量的判空问题。
a?.doSomething()
a?.doStudy()//上面其实a是否为空每一句都判断了,代码复杂了。但是用let函数,在外面先判断一次,然后就做操作a?.let{
a1-> a.doSomething()
a.doStudy()
}//再次简化,当lambda表达式里面只有一个传入参数的时候,可以声明直接用it来指代
a?.let{
it.doSomething()
it.doStudy()
}
字符串内嵌表达式
在字符串中允许${}的方式来内嵌,可以把一堆+给省略掉了。
val name="小明"val age="20"println("你好,"+name+",原来你已经"+age+"岁了呀!")println("你好,${name},原来你已经${age}岁了呀!")
-----------------结果--------------------
你好,小明,原来你已经20岁了呀!
你好,小明,原来你已经20岁了呀!
函数设置参数默认值
fun main(){doPrint()doPrint(name = "小花") //键值对的传参方式,可以无视顺序doPrint(age = 10)}
fun doPrint(name:String="小明",age:Int=20){ //设置默认值 println("你好,${name},原来你已经${age}岁了呀!")
}
----------------结果----------------
你好,小明,原来你已经20岁了呀!
你好,小花,原来你已经20岁了呀!
你好,小明,原来你已经10岁了呀!
延迟初始化
使用lateinit关键字,使用了这个关键字之后,我们可以不需要定义的时候就设置默认值,可以后面用到的时候初始化。
这个的作用是可以让我们用到全局变量少很多非空校验,当然这个的前提是你确保用到这个变量的时候已经完成初始化才行。
lateinit var a:String //没有初始值
var b="" //必须设置初始值
判断是否进行过初始化。 ::a.isInitialized 代表a是否进行过初始化,没有的话进行初始化。
if(!::a.isInitialized){a=""}
密封类
普通写法,创建一个Result.kt文件,也就是kotlin文件。
interface Result
class Success(val msg:String):Result()
class Failure(val error:Exception):Result()
为了过编译一定要写个else,但是实际结果肯定不会有else。
还有就是当Result又多了一个Unknown类继承它,但是方法里面没有去判断,走到else导致系统抛出异常,程序崩溃。
fun getResultMsg(result:Result)=when(result){
is Success ->result.msg
is Failure->result.error.message
else throw IllegalArgumentException()
}
但是密封类的写法,创建一个Result.kt文件。
sealed class Result
class Success(val msg:String):Result()
class Failure(val error:Exception):Result()
不需要写else,而且如果后续增加了Unknown继承它,kotlin会强制你每个都进行判断,否则编译通不过。密封类是一个可继承的类,所以当其他类继承它的时候要实现它的主构造函数,所以是:Result()
fun getResultMsg(result:Result)=when(result){
is Success ->result.msg
is Failure->result.error.message
}
密封类和子类只能定义在同一个文件的顶层位置,不能嵌套在其他类里面。
Kotlin开发Android相关推荐
- 用Kotlin开发android平台语音识别语义理解应用
用Kotlin开发android平台语音识别,语义理解应用(olamisdk) 转载请注明CSDN博文地址:http://blog.csdn.net/ls0609/article/details/75 ...
- 用Kotlin开发android平台语音识别,语义理解应用(olamisdk)
本文使用Kotlin开发Android平台的一个语音识别方面的应用,用的是欧拉密开放平台olamisdk. 1.Kotlin简介 Kotlin是由JetBrains创建的基于JVM的编程语言,Inte ...
- 使用Kotlin开发Android应用 - 环境搭建 (1)
一. 在Android Studio上安装Kotlin插件 按快捷键Command+, -> 在Preferences界面找到Plugins -> 点击Browse repositorie ...
- 使用Kotlin开发Android应用初体验
使用Kotlin开发Android应用初体验 昨晚,最近一届的谷歌IO大会正式将Kotlin确定为了官方开发语言,作为一名Android开发鸟,怎么能不及时尝尝鲜呢? Kotlin的简要介绍 在开发之 ...
- kotlin开发Android入门篇八Kotlin开发Android的基本使用
基础篇:Kotlin开发Android的基本使用 使用AndroidStudio3.0及以上开发Kotlin在新建项目中勾选这个选项则会默认开发语言为Koltin,然后再gradle(Project的 ...
- 用 Kotlin 开发 Android 项目是一种什么样的感受?(二)
前言 前面我已经写了一篇名为<用 Kotlin 开发 Android 项目是一种什么样的感受?>的文章.文中多数提到的还是 Kotlin 语言本身的特点,而 Kotlin 对于 Andro ...
- 使用Kotlin开发Android应用
作者:snowdream Email:yanghui1986527#gmail.com QQ 群: 529327615 原文地址:https://snowdream.github.io/blog/20 ...
- [Android]使用Kotlin开发Android(二)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4829007.html [TOC] 使用Kotlin+OkHtt ...
- IDEA基于kotlin开发android程序配置小结
IDEA功能极其强大,和微软的宇宙第一IDE不相上下.用了很长时间,对它配置的完善性产生了近乎迷信的感情.似乎只要走正常渠道,用它来配置,没有不成功的. IDEA是开发android原生程序的利器,a ...
最新文章
- wk一sm5时间温度控制器_新能源汽车电机控制器温度计算及其模型—DC电容篇
- 010_jQuery获取和设置内容属性
- java 学生成绩排序
- 蓝桥杯 - 完美的代价(贪心+模拟)
- mockjs中的方法(三)
- 爬楼梯(递归——奇数步,偶数步扩展)
- Android中的数据库
- ci phpexcel mysql_PHPExcel导入数据到mysql数据库
- 程序员每天少吃 能活120岁
- 程序员为什么要少写代码?
- 服务器一直运行python_【已采纳】supervisor在服务器端(linux),如何一直运行你的python代码...
- vim 批量替换字符串_Vim 有什么奇技淫巧?
- Xamarin.Forms Layout Challenges – Great Places(已全文翻译)
- mongodb集群linux日志分割,Linux下Mongodb数据库日志切割及定时删除
- 验证GridControl Gridview 单元格。
- 在C / C ++中使用INT_MAX和INT_MIN
- 七款修复工具介绍:不仅能修复U盘,SD卡、TF卡也能修复!
- AdventureWorks2008 数据库安装
- python迭代器是什么_python中什么是迭代器
- 「BIND9」- DLZ(Dynamically Loadable Zones) @20210212
热门文章
- 恒生o32系统介绍_恒生指数日内空间预测模型和实盘对照20201104日
- 实在智能RPA亮相2023全球人工智能技术博览会,“能对话的数字员工”引领智能自动化新篇章
- ANSYS经典界面中的刚性目标面及其控制节点_51CAE_新浪博客
- 【博客134】linux显示磁盘信息—df命令
- 2013买房靠不靠谱?---“秒杀”三件最蛋疼的房事儿是关键
- 高级软件工程团队第一次作业
- selenium3 + python - gird分布式(转载)
- 国外问卷调查该怎么做?
- ftpd服务器配置文件,中文解释PureFTPd配置文件网络服务器 -电脑资料
- 主题单元评价量规用计算机画画,巧用评价量规引领课堂教学