Java&Kotlin&Dart语法教程

423 阅读13分钟

没事多翻书

Java

基本语法

关于Java程序,请务必牢记以下几点。

  • 区分大小写 - Java区分大小写,因此标识符Hellohello在Java中具有不同的含义。

  • 类名 - 对于所有类名,第一个字母应为大写。 如果使用多个单词来形成类的名称,则每个内部单词的第一个字母应为大写。
    示例:class MyFirstJavaClass

  • 方法名称 - 所有方法名称都应以小写字母开头。如果使用多个单词来形成方法的名称,那么每个内部单词的第一个字母应该是大写字母。
    示例:public void myMethodName()

  • 程序文件名 - 程序文件的名称应与类名完全匹配。保存文件时,应使用类名保存它(记住Java区分大小写)并在名称的末尾使用扩展名称:.java(如果文件名和类名不匹配,则程序将无法编译))。但请注意,如果代码文件中没有public class,则文件名可能与类名不同。在代码文件中也没有强制要求必须有public class
    示例:假设MyFirstJavaProgram是类名,那么该文件应保存为: MyFirstJavaProgram.java

  • public static void main(String args[]) − Java程序处理从main()方法开始,该方法是每个Java程序的必需部分。

Java标识符

所有Java组件都需要名称。 用于类,变量和方法的名称称为 标识符
在Java中,标识符的命名有几点要记住。 它们如下 -

  • 所有标识符都应以字母(AZaz),货币字符($)或下划线(_)开头。
  • 在第一个字符之后,标识符可以是任何字符组合。
  • 关键字不能用作标识符。
  • 标识符区分大小写。
  • 合法标识符的示例:age$salary_value__1_value
  • 非法标识符的示例:123abc-salary

Java修饰符

与其他语言一样,可以通过使用修饰符来修改类,方法等。 修饰符分为两类 -

  • 访问修饰符 - default, public , protected, private
  • 非访问修饰符 - finalabstractstrictfp

在下一节中学习有关修饰符的更多细节。

Java变量

以下是Java中的变量类型 -

  • 局部变量
  • 类变量(静态变量)
  • 实例变量(非静态变量)

Java数组

数组是存储多个相同类型变量的对象。 但是,数组本身是堆上的对象。

Java枚举

枚举是在Java 5.0中引入的。 枚举将变量限制为仅具有少数预定义值之一。此枚举列表中的值称为枚举。
通过使用枚举,可以减少代码中的错误数量。

例如,在新鲜果汁店中,可将玻璃杯大小限制为: 小杯中杯大杯 。 这将确保它不允许购买除了小杯,中杯或大杯之外的玻璃杯。

示例代码:

class FreshJuice {
    // 定义枚举
    enum FreshJuiceSize{ SMALL, MEDIUM, LARGE }
    FreshJuiceSize size;
}

public class FreshJuiceTest {

   public static void main(String args[]) {
      FreshJuice juice = new FreshJuice();
      juice.size = FreshJuice.FreshJuiceSize.MEDIUM ;
      System.out.println("玻璃杯大小: " + juice.size);
   }
}


Java

编译并执行上面示例代码,得到以下结果:

玻璃杯大小: MEDIUM


Shell

注 - 枚举可以单独声明或在类中声明。 方法,变量,构造函数也可以在枚举内定义。

Java关键字

以下列表中列出了Java中的保留字(关键字)。这些保留字不能用作常量或变量或任何其他标识符名称。

abstract assert boolean break
byte case catch char
class const continue default
do double else enum
extends final finally float
for goto if implements
import instanceof int interface
long native new package
private protected public return
short static strictfp super
switch synchronized this throw
throws transient try void
volatile while

注释

Java支持与C和C++非常相似的单行和多行注释。Java编译器会忽略任何注释中可用的所有字符。

示例代码:

public class MyFirstJavaProgram {

   /* This is my first java program.
    * This will print 'Hello World' as the output
    * This is an example of multi-line comments.
    */

   public static void main(String []args) {
      // 这是单行注释
      /* 这也是一个单行注释 */
      /* 这是一个
       多行的
       注释 
       */
      System.out.println("Hello World");
   }
}


Java

继承

在Java中,类可以从类派生(继承)。 如果需要创建一个新类,并且已经有一个包含需要的代码的类,那么可以直接从这个现有代码派生一个新类。

此概念可重用现有类的字段和方法,而无需在新类中重写代码。 在这种情况下,现有类称为超类,派生类称为子类。

接口

在Java语言中,接口可以定义为对象之间如何相互通信的契约。 在涉及继承的概念时,接口起着至关重要的作用。

接口定义一些方法,在派生类(子类)应该使用这些方法。 但是这些方法的实现完全取决于子类。

Kotlin

Kotlin 文件以 .kt 为后缀。

包声明

代码文件的开头一般为包的声明:

package com.runoob.main

import java.util.*

fun test() {}
class Runoob {}

kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。

以上例中 test() 的全名是 com.runoob.main.test、Runoob 的全名是 com.runoob.main.Runoob。

如果没有指定包,默认为 default 包。

默认导入

有多个包会默认导入到每个 Kotlin 文件中:

  • kotlin.*
  • kotlin.annotation.*
  • kotlin.collections.*
  • kotlin.comparisons.*
  • kotlin.io.*
  • kotlin.ranges.*
  • kotlin.sequences.*
  • kotlin.text.*

函数定义

函数定义使用关键字 fun,参数格式为:参数 : 类型

fun sum(a: Int, b: Int): Int {   // Int 参数,返回值 Int
    return a + b
}

表达式作为函数体,返回类型自动推断:

fun sum(a: Int, b: Int) = a + b

public fun sum(a: Int, b: Int): Int = a + b   // public 方法则必须明确写出返回类型

无返回值的函数(类似Java中的void):

fun printSum(a: Int, b: Int): Unit { 
    print(a + b)
}


// 如果是返回 Unit类型,则可以省略(对于public方法也是这样):
public fun printSum(a: Int, b: Int) { 
    print(a + b)
}

可变长参数函数

函数的变长参数可以用 vararg 关键字进行标识:

fun vars(vararg v:Int){
    for(vt in v){
        print(vt)
    }
}

// 测试
fun main(args: Array<String>) {
    vars(1,2,3,4,5)  // 输出12345
}

lambda(匿名函数)

lambda表达式使用实例:

// 测试
fun main(args: Array<String>) {
    val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
    println(sumLambda(1,2))  // 输出 3
}

定义常量与变量

可变变量定义:var 关键字

var <标识符> : <类型> = <初始化值>

不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)

val <标识符> : <类型> = <初始化值>

常量与变量都可以没有初始化值,但是在引用前必须初始化

编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。

val a: Int = 1
val b = 1       // 系统自动推断变量类型为Int
val c: Int      // 如果不在声明时初始化则必须提供变量类型
c = 1           // 明确赋值


var x = 5        // 系统自动推断变量类型为Int
x += 1           // 变量可修改

注释

Kotlin 支持单行和多行注释,实例如下:

// 这是一个单行注释

/* 这是一个多行的
   块注释。 */

与 Java 不同, Kotlin 中的块注释允许嵌套。


字符串模板

$ 表示一个变量名或者变量值

$varName 表示变量值

${varName.fun()} 表示变量的方法返回值:

var a = 1
// 模板中的简单名称:
val s1 = "a is $a" 

a = 2
// 模板中的任意表达式:
val s2 = "${s1.replace("is", "was")}, but now is $a"

NULL检查机制

Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理

//类型后面加?表示可为空
var age: String? = "23" 
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1

当一个引用可能为 null 值时, 对应的类型声明必须明确地标记为可为 null。

当 str 中的字符串内容不是一个整数时, 返回 null:

fun parseInt(str: String): Int? {
  // ...
}

以下实例演示如何使用一个返回值可为 null 的函数:

fun main(args: Array<String>) {
  if (args.size < 2) {
    print("Two integers expected")
    return
  }
  val x = parseInt(args[0])
  val y = parseInt(args[1])
  // 直接使用 `x * y` 会导致错误, 因为它们可能为 null.
  if (x != null && y != null) {
    // 在进行过 null 值检查之后, x 和 y 的类型会被自动转换为非 null 变量
    print(x * y)
  }
}

类型检测及自动类型转换

我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字)。

fun getStringLength(obj: Any): Int? {
  if (obj is String) {
    // 做过类型判断以后,obj会被系统自动转换为String类型
    return obj.length 
  }

  //在这里还有一种方法,与Java中instanceof不同,使用!is
  // if (obj !is String){
  //   // XXX
  // }

  // 这里的obj仍然是Any类型的引用
  return null
}

或者

fun getStringLength(obj: Any): Int? {
  if (obj !is String)
    return null
  // 在这个分支中, `obj` 的类型会被自动转换为 `String`
  return obj.length
}

甚至还可以

fun getStringLength(obj: Any): Int? {
  // 在 `&&` 运算符的右侧, `obj` 的类型会被自动转换为 `String`
  if (obj is String && obj.length > 0)
    return obj.length
  return null
}

区间

区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。

区间是为任何可比较类型定义的,但对于整型原生类型,它有一个优化的实现。以下是使用区间的一些示例:

for (i in 1..4) print(i) // 输出“1234”

for (i in 4..1) print(i) // 什么都不输出

if (i in 1..10) { // 等同于 1 <= i && i <= 10
    println(i)
}

// 使用 step 指定步长
for (i in 1..4 step 2) print(i) // 输出“13”

for (i in 4 downTo 1 step 2) print(i) // 输出“42”


// 使用 until 函数排除结束元素
for (i in 1 until 10) {   // i in [1, 10) 排除了 10
     println(i)
}

实例测试

fun main(args: Array<String>) {
    print("循环输出:")
    for (i in 1..4) print(i) // 输出“1234”
    println("\n----------------")
    print("设置步长:")
    for (i in 1..4 step 2) print(i) // 输出“13”
    println("\n----------------")
    print("使用 downTo:")
    for (i in 4 downTo 1 step 2) print(i) // 输出“42”
    println("\n----------------")
    print("使用 until:")
    // 使用 until 函数排除结束元素
    for (i in 1 until 4) {   // i in [1, 4) 排除了 4
        print(i)
    }
    println("\n----------------")
}

输出结果:

循环输出:1234
----------------
设置步长:13
----------------
使用 downTo:42
----------------
使用 until:123
----------------

Dart

语法定义了一组用于编写程序的规则。每种语言规范都定义了自己的语法。Dart程序代码由以下组成 -

  • 变量和运算符
  • 函数
  • 表达式和编程构造
  • 决策和循环结构
  • 注解
  • 库和包
  • 类型定义
  • 数据结构 - 集合/泛型

第一个Dart语序

main() { 
   print("Hello World!"); 
}


Dart

main()函数是Dart中的预定义方法。此方法充当应用程序的入口点。Dart脚本需要main()方法来执行。print()是一个预定义的函数,它将指定的字符串或值打印到标准输出(即终端)。

上述代码的输出将是 -

Hello World!


Shell

执行Dart程序

可以使用以下两种方式执行Dart程序 -

  • 通过终端/控制台
  • 通过WebStorm IDE

通过终端/控制台

通过终端执行Dart程序 -

  • 进入到当前项目的路径

  • 在“终端/控制台”窗口中键入以下命令 -

    C:/> dart helloword.dart

    Shell

通过WebStorm IDE

要通过WebStorm IDE执行Dart程序 -

  • 右键单击IDE上的Dart脚本文件。(该文件应包含main()函数以启用执行)
  • 单击“运行<file_name>”选项。

如下截图所示 -

WebStorm

Dart命令行选项

Dart命令行选项用于修改Dart脚本执行。Dart的常见命令行选项包括以下内容 -

编号 命令行选项 描述
1 -c--c 启用断言和类型检查(选中模式)。
2 --version 显示VM版本信息
3 --packages <path> 指定程序包解析配置文件的路径。
4 -p <path> 指定在何处查找导入的库。此选项不能与--packages一起使用。
5 -h--help 显示帮助信息。

启用检查模式

Dart程序以两种模式运行,即 -

  • 检查模式
  • 生产模式(默认)

建议在开发和测试期间以检查模式运行Dart VM,因为它会添加警告和错误以帮助开发和调试过程。选中的模式会强制执行各种检查,例如类型检查等。要打开选中的模式,请在运行脚本时在脚本文件名之前添加- c或—checked选项。

但是,为了在运行脚本时确保性能优势,建议在生产模式下运行脚本。

假设 test.dart 脚本文件代码如下 -

void main() { 
   String s = "welcome to yiibai.com"; 
   print(s); 
}


Dart

输入以下命令运行脚本 -

C:/> dart test.dart


Shell

上面脚本将产生以下输出 -

welcome to yiibai.com


Shell

Dart标识符

标识符是程序中元素的名称,如变量,函数等。标识符的规则是 -

  • 标识符可以包括字符和数字。但是,标识符不能以数字开头。
  • 除下划线(_)或美元符号($)外,标识符不能包含特殊符号。
  • 标识符不能是关键字。
  • 它们必须是唯一的。
  • 标识符区分大小写。
  • 标识符不能包含空格。

下表列出了有效和无效标识符的几个示例 -

有效标识符 无效标识符
firstName Var
first_name first name
num1 first-name
$result 1result

Dart关键字

关键字在语言的上下文中具有特殊含义。下表中列出了Dart语言中的一些关键字。

abstract continue false new this
as default final null throw
assert deferred finally operator true
async do for part try
async* dynamic get rethrow typedef
await else if return var
break enum implements set void
case export import static while
catch external in super with
class extends is switch yield
const factory library

空白和换行

Dart忽略程序中出现的空格,制表符和换行符。可以在程序中自由使用空格,制表符和换行符,并且可以自由地以简洁一致的方式格式化和缩进程序,使代码易于阅读和理解。

Dart区分大小写
Dart区分大小写。Dart中大写和小写字符表示不同地含义。

声明以分号结尾

每行指令都称为语句。每个dart语句必须以分号(;)结尾。一行可以包含多个语句。但是,这些语句必须用分号分隔。

Dart注释

注释是提高程序可读性的一种方法。注释可用于包含有关程序的其他信息,如代码的作者,有关函数/构造的提示等。编译器会忽略注释。

Dart支持以下类型的注释 -

  • 单行注释(//) - // 和行尾之间的任何文本都视为注释

  • 多行注释(/* */) - 这个注释可能跨越多行。

    // 这是单行注释

    /* 这是... 一个 多行的 注释 */

    Dart

Dart面向对象编程

Dart是一种面向对象的语言。面向对象是一种遵循真实世界建模的软件开发范例。面向对象将程序视为通过称为方法的机制相互通信的对象集合。

  • 对象 - 对象是任何实体的实时表示。根据Grady Brooch,每个对象必须具有三个功能 -
    • 状态 - 由对象的属性描述。
    • 行为 - 描述对象的行为方式。
    • 标识 - 将对象与一组类似此类对象区分开的唯一值。
  • 类 - 类是创建对象的蓝图/模板,类封装了对象的数据。
  • 方法 - 方法促进对象之间的通信。

示例:Dart和面向对象

class TestClass {   
   void display() {     
      print("Dart and Object Orientation"); 
   } 
}  
void main() {   
   TestClass c = new TestClass();   
   c.display();  
}


Dart

上面的示例代码中定义了一个类TestClass。该类有一个display()方法。该方法在终端上打印字符串 - "Dart and Object Orientation"new关键字创建类的对象。该对象调用display()方法。

执行上面代码将产生以下输出 -

Dart and Object Orientation


Shell