整理自:老师课件、动力节点Javase基础讲义

Java基础语法

java方法前加感叹号 java方法上有横线_System

前言

在本文中,学习Java的基础语法,包括注释、标识符与关键字、变量、数据类型、运算符以及控制语句

通过本文的学习,您将了解到:

  • 注释是什么?
  • 标识符是什么意思,关键字呢?
  • 数据类型是什么,跟现实的数据有什么对应的关系吗?
  • Java中的运算符都有哪些?
  • 为什么要学习控制语句?

注释

为什么有注释这个语法

  • 对于复杂的程序,注释可以在代码旁边写下思路,便于他人了解代码功能而不必一行一行的阅读代码甚至跟踪;甚至对于本人,下次阅读此代码,也不一定能一下子全然了解其功能,这时候若有思路记录,便很容易回忆理解。即俗话说的“好记性不如烂笔头

注释有哪些

  • 单行注释
  • 在语句行中以“//”开头到本行末的所有字符视为注释
  • 多行注释
  • 以"/*" 和"*/"进行标记,其中"/*"标记着注释的开始,"*/"标记着注释的结束
  • 当注释文字较多,一行写不下或者排版难看要分成多行,若每行都写"//"将很麻烦也不美观,故有多行注释
  • 文档注释
  • 类似多行注释,但注释开始标记为"/**",结束为"*/"
  • 在有了多行注释基础上,还有此文档注释是因为它可通过javadoc.exe命令解析并生成帮助文档,如JDK帮助文档

怎么写

  • 类和接口
  • x写明创建者、创建时间、版本及该类的作用
  • 方法
  • 标明入参、出参以及返回值
  • 常量
  • 使用多行注释,标明用途
  • 关键算法
  • 按顺序依次标明该方法为什么这么做

标识符与关键字

标识符是什么

  • 是用于编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与使用之间的关系
  • 通常由字母和数字以及其他字符构成
  • 总结:标识符即起名字

标识符怎么命名

  • 标识符只能由数字、字母、下划线、美元符号组成
  • 这里的字母是Java字母,可以用中文作为变量、方法名,但是不推荐用中文作为类名,编译时会出现莫名其妙的错误
  • 标识符不能以数字开始
  • Java关键字与保留字不能作为标识符
  • 标识符严格区分大小写
  • 标识符理论上没有长度限制

标识符命名规范:提高代码可读性

  • 见命知意
  • 遵循驼峰命名方式
  • 类名、接口名首字母大写,后面每个单词首字母大写
  • 变量名、方法名首字母小写,后面每个单词首字母大写
  • 常量名全部大写,单词之间用'_'衔接

关键字是什么?

  • 是编程语言里事先定义的,有特殊意义的单词(因此不能作为标识符,避免冲突),Java中所有关键字都是小写的英文单词

关键字有哪些(不必记)

关键字

大致含义

abstract

表明类或成员方法具有抽象属性

assert

断言,用于程序调试

boolean

基本数据类型之一,声明布尔类型的关键字

break

提前跳出一个块

byte

基本数据类型之一,字节类型

case

用在switch语句之中,表示其中的一个分支

catch

用在异常处理中,用来捕捉异常

char

基本数据类型之一,字符类型

class

声明一个类

const

保留关键字,没有具体含义

continue

回到一个块的开始处

default

默认,例如,用在switch语句中,表明一个默认的分支

do

用在do-while循环结构中

double

基本数据类型之一,双精度浮点数类型

else

用在条件语句中,表明当条件不成立时的分支

enum

枚举

extends

表明一个类型是另一个类型的子类型,这里常见的类型

有类和接口

final

表示不可变,最终的

finally

用于处理异常情况,用来声明一个基本肯定会被执行

到的语句块

float

基本数据类型之一,单精度浮点数类型

for

一种循环结构的引导词

goto

保留关键字,没有具体含义

if

条件语句的引导词

implements

表明一个类实现了给定的接口

import

表明要访问指定的类或包

instanceof

用来测试一个对象是否是指定类型的实例对象

int

基本数据类型之一,整数类型

interface

接口

long

基本数据类型之一,长整数类型

native

用来声明一个方法是由与计算机相关的语言(如C/C++

语言)实现的

new

用于创建新实例对象

package


private

一种访问控制方式:私用模式

protected

一种访问控制方式:保护模式

public

一种访问控制方式:共用模式

return

从成员方法中返回数据

short

基本数据类型之一,短整数类型

static

表明具有静态属性

strictfp

用来声明FP_strict(单精度或双精度浮点数)表达式遵循

IEEE 754算术规范

super

表明当前对象的父类型的引用或者父类型的构造方法

switch

分支语句结构的引导词

synchronized

表明一段代码需要同步执行

this

指向当前实例对象的引用

throw

抛出一个异常

throws

声明在当前定义的成员方法中所有需要抛出的异常

transient

声明不用序列化的成员域

try

尝试一个可能抛出异常的程序块

void

声明当前成员方法没有返回值

volatile

表明两个或多个变量必须同步地发生变化

while

用在循环结构中

难点解惑

  • 新建一个123Test.java文件,里面写class T{},编译通过,是不是违反标识符不能以数字开头?
  • 不是的,因为此时123Test只是一个普通的文件名(因为没有把该类声明为共同的,所以文件名不必和类名一致),不是作为类名
  • 如果将其作为类名,编译是会出现:需要

变量

字面量

是什么

  • 表示Java中数与字符的明显值,即常量
  • 字符型字面量须用半角单引号括起来
  • 只能是单个字符
  • 字符串型字面量需用半角双引号括起来

变量概述

是什么

  • 把数据(字面量)放到内存中,给这块内存起一个名字,即是变量

有什么特点

  • 变量中存储的数据可改变
  • 变量的数据类型须和存储的字面值一致

变量定义

  • 格式:数据类型  变量名 = 值…;
  • 在同一个域中不能同时声明多个同名变量
  • 方法体中if/switch等都在同一个域,所以若if外面已声明变量,不可在if里声明同名变量
  • 如果一个是类体域,一个是方法体域,则可声明同名变量,且Java遵循就近原则,会自动访问离它最近的数据
  • 方法中的代码有执行顺序,遵循自上而下的顺序

变量分类

  • 局部变量
  • 在方法体中声明的变量以及方法的每一个参数
  • 成员变量:在方法体外,类体内声明的变量
  • 没有static修饰
  • 有static修饰
  • 静态成员变量/静态变量
  • 实例成员变量/实例变量

变量作用域

  • 出了大括号后就不认识了
  • 注意区分成员变量及局部变量,对应的大括号不一致

数据类型

数据类型概述

是什么

  • 现实中有很多数据(如数字、字母),编程语言对其进行分门别类,产生数据类型
  • 主要作用:决定程序运行阶段给该变量分配多大的内存空间

字符编码

  • 编码和解码都要采用同一种字符编码方式,否则出现乱码
  • 支持简体中文的编码方式:GB2312、GBK、GB18030(容量大小从左到右增大)
  • Java采用Unicode编码

基本数据类型

java方法前加感叹号 java方法上有横线_不兼容_02

  • 可以在各自的包装类查看最大最小值,MAX_VALUE,MIN_VALUE
  • 字符型char
  • 两个字节,可容纳一个汉字(两个字节)
  • 转义字符会在解析代码之前得到处理
  • 整数型
  • 赋值时在字面量后加L
  • 整数型字面量默认是int类型
  • byte
  • short
  • int
  • long
  • 布尔型
  • boolean
  • 浮点型
  • 赋值时在字面量后面加F
  • float类型容量比long大是因为float有一部分空间用于存储有效位数,一部分存储多少次方
  • 浮点型字面量默认是double
  • float
  • double
  • 基本数据类型转换规则
  • 八个基本类型中,除boolean类型不能转换,其他都可以转换
  • 如果整数型字面量没有超过byte,short,char的取值范围,可以直接将其赋值为byte,short,char类型的变量
  • 注意是指字面量,而不是整数型变量,对于变量编译器不知道其大小,不能判断是否超过取值范围
  • 小容量转换成大容量,称为自动类型转换,容量从小到大的排序为:byte
  • int->float、long->float、long->double有可能出现精度损失,因为浮点型只能存储有限位数
  • 大转小,称为强制类型转换,可能会出现精度损失
  • byte,short,char类型混合运算时,先各自转换成int类型再做运算,结果也是int类型,注意了
  • 多种数据类型混合运算,各自先转换成容量最大的那一种再做运算

引用类型(之后展开)

  • 字符串类型
  • 数组

运算符

为什么有运算符

  • 因为数据有运算

有哪些运算符

java方法前加感叹号 java方法上有横线_System_03



算术运算符

  • 注意++、--运算符,该运算符只能用于变量且只能用于除boolean类型的基本数据类型,不能用字面值

关系运算符

  • 关系运算符的结果是布尔类型

逻辑运算符

  • 操作数都是布尔类型
  • 根据是否期望右边的表达式一定执行选择短路与&&或逻辑与&,前者若左边为空,右边不执行;后者左右两边都执行

赋值运算符

  • 对于+=等拓展类运算符,在运算过程中不会改变运算的结果类型,相当于b=(byte)()b+1)等价于b += 1;如果超过当前类型的最大容量,则会截断,跟强转一样

控制语句

为什么要学习控制语句

  • 因为单单依靠“标识符、关键字、变量、运算符”等知识无法进行流程控制,而现实中的业务常常需要进行条件判断或循环执行等流程,如“小孩身高1.2m以下乘车免费,否则收费”
  • 概述
  • 控制语句即用来实现对程序流程的选择、循环、转向和返回等进行控制

控制语句有哪些

选择语句

  • if
  • 语法:if(布尔表达式){}
  • if语句的任何一种形式在执行时只要有一个分支执行,则所对应的整个if语句就全部结束
  • else/else if会与最近的if/else if匹配
  • switch
  • 语法:switch(int/String/enum){case int/String/enum: …}
  • case可以合并
  • 如果当前分支没有“break;”语句,则会发生case穿透现象,即下一个分支不再进行匹配,直接进入下一个分支执行,直到遇到break;语句或到末尾
  • 用于几个常量数据的条件判断,一般要进行逻辑判断的找if
  • default可以写在switch方括号里的任何位置,但它的执行时机永远不变,永远都是在所有分支都没有匹配成功的时候才会执行

循环语句

  • 为什么要学习循环语句?
  • 为了提高代码的复用性,对于一些重复代码,如果每次都写,那样既不美观也不现实
  • for
  • 语法:for(初始化表达式;布尔表达式;迭代表达式){循环体;}
  • 初始化表达式最先执行,并且在整个循环当中只执行一次;布尔表达式的结果是true或false,true表示循环可以继续执行,false则循环终止;迭代表达式用于迭代某个变量,更新后可能布尔表达式的结果不再为true,换言之,一般是为了达到终止条件
  • 执行顺序:先执行初始化表达式(若有的话),然后判断布尔表达式是否为true,若是,执行循环体;否则退出循环。执行完循环体后,执行迭代表达式(如果有的话),之后再判断布尔表达式是否为true……直到满足退出条件
  • 初始化表达式;布尔表达式;迭代表达式都不是必须的,但是两个分号不能省略
  • 注意初始化变量的作用域,如果是在for循环内创建,那么循环结束后该变量不复存在
  • while
  • 语法:while(布尔表达式){循环体;}
  • 先判断再执行
  • do…while
  • 语法:do{}while(布尔表达式); 别忘while后面的分号
  • 先执行后判断

转向语句

  • 转向语句有什么用?
  • 用于实现循环执行过程中程序流程的跳转
  • 标号:紧跟着":"的标识符
  • 标号必须放置语句块前面才有作用
  • break
  • 不带标号:即break;跳出当前循环
  • 带标号:即break 标号;跳出标号所指的代码块,执行块后的下一条语句
  • continue
  • 不带标号:即continue;终止当前一轮循环,继续下一轮判断
  • 带标号:即continue 标号;跳转到标号指明的外层循环,继续外层循环的下一轮判断

返回语句

  • return
  • 返回方法指定类型的值,也可以是对象
  • 方法的结束

对于上述的各种结论,可以验证一下,说服自己接受

易错点

1、局部变量调用前需要初始化,全局变量若没有赋值,会按照缺省默认值初始化

public class Test{
    public static void main(String[] args){
        //变量使用前需初始化
        int age;
        System.out.println(age);
    }
}

2、java语言默认整数型为int类型,long类型精度比int高,所以可以转换,但是当超过int类型范围却没有加L的就会出现错误

public class Test{
    public static void main(String[] args) {
        //当数值超过int(4个字节)类型最大值后,若想定义为long类型,
        //需在后面加L,因为整数型默认字面值为int类型
        /*Integer number too large*/
        long num = 123456666666666666;
        System.out.println(num);
    }
}

3、Java中浮点类型的值默认为double类型

public class Test{
    public static void main(String[] args) {
        //不兼容的类型: 从double转换到float可能会有损失
        float num = 10.5;
        System.out.println(num);
    }
}

4、boolean类型只有true或false

public class Test{
    public static void main(String[] args) {
        //不兼容的类型: int无法转换为boolean
        boolean a = 1;
        boolean b = 0;
        System.out.println(a);
        System.out.println(b);
    }
}

5、类型转换测试

public class Test{
    public static void main(String[] args) {
        //默认转换:容量小的会直接转换为容量大的类型

        //只要不超过范围可以把整数型赋值给char、short、byte
        //错误: 不兼容的类型: 从int转换到byte可能会有损失
        //byte是一个字节,1000已超过范围
        byte a = 1000;

        //从byte赋值给short可以,但是反之不行
        short b = a;

        //错误: 不兼容的类型: 从short转换到byte可能会有损失
        a = b;

        //错误: 已在方法 main(String[])中定义了变量 a
        //变量重复命名
        short a = 1000;

        //可以用b赋值给c,因为有默认转换
        long c = b;

        //错误: 不兼容的类型: 从long转换到int可能会有损失
        int d = c;


        //强转后若数值太大,会截断,出现一个很奇怪的数
        c = 1234567890123456L;
        d = (int)c;
        System.out.println(d);//1015724736

        //先按照int类型相除然后再转化为double类型
        double e = 10 / 3;
        System.out.println(e);//3.0
        //先转换为double类型然后相除
        e = 10 / 3.0;
        System.out.println(e);//3.3333333333333335

        //错误: 不兼容的类型: 从long转换到int可能会有损失
        //多个值运算时会先转换为容量最大的类型
        long g = 10;
        int h = g / 3;
        System.out.println(h);

        //错误: 不兼容的类型: 从int转换到byte可能会有损失
        //会先把g转换为int类型,然后转换为byte类型,接着再除以3,
        //因为3是int类型,所以会转换为int类型运算
        byte i = (byte)(int)g / 3;


        byte a = 1;
        short b = 2;
        char c = 'a';
        //错误: 不兼容的类型: 从int转换到short可能会有损失
        /*三个都错误,因为byte、short、char之间没有自动转换,
         即使short取值范围大,但都是转换为int后才处理*/
        b = a + b;
        b = b + c;
        b = a + c;

        boolean c = 10 > 5;     
        System.out.println(c);
    }
}

6、switch测试

6.1、switch后面的括号表达式可以取的数据类型

  • switch后面只能跟byte、short、int、char、String、enum及前四者的包装类
  • switch(表达式){case 值1……},case后面的值要和表达式的值一致
public class Test{
    public static void main(String[] args) {
        //L与数值之间不要分开
        //long a = 2 L;
        //错误: 不兼容的类型: 从long转换到int可能会有损失,
        long a = 2L;
        switch(a){}

        //错误: 不兼容的类型: boolean无法转换为int,表达式不可以为Boolean类型
        switch(5 > 10){}

        //表达式可以为String类型
        switch("ll"){
            //错误: 不兼容的类型: int无法转换为String
            case 1:
                System.out.println("优秀");
                break;
            //错误: 不兼容的类型: int无法转换为String
            case 2:
                System.out.println("厉害啊");
                break;
            //错误: 不兼容的类型: int无法转换为String
            case 3:
                System.out.println("牛");
                break;
            default:
                System.out.println("强");
        }

        //char类型与String类型不存在强转
        switch("ll"){
            //错误: 不兼容的类型: char无法转换为String
            case '1':
                System.out.println("优秀");
                break;
            //错误: 不兼容的类型: char无法转换为String
            case '2':
                System.out.println("厉害啊");
                break;
            //错误: 不兼容的类型: char无法转换为String
            case '3':
                System.out.println("牛");
                break;
            default:
                System.out.println("强");
        }

        switch(1){
            //错误: 不兼容的类型: 从double转换到int可能会有损失
            //case后面的值都要为int类型
            case 1.5:
                System.out.println("优秀");
                break;
            case 2:
                System.out.println("厉害啊");
                break;
            case 3:
                System.out.println("牛");
                break;
            default:
                System.out.println("强");
        }

        switch('a'){
            //错误: case 标签重复
            //97跟'a'在这里是一样的
            case 97:
                System.out.println("优秀");
                break;  
            case 'a':
                System.out.println("厉害啊");
                break;
            case 3:
                System.out.println("牛");
                break;
            default:
                System.out.println("强");
        }

        switch(1){
            case 97:
                System.out.println("优秀");
                break;
            //这里是short类型也可以输出,
            //总结起来就是表达式可以为int、short、byte、char、String
            case (short)1:
                System.out.println("厉害啊");
                break;
            case 3:
                System.out.println("牛");
                break;
            default:
                System.out.println("强");
        }

        //可
        switch(""){
            case "ldh":
                System.out.println("优秀");
                break;
            case "":
                System.out.println("厉害啊");
                break;
            case "12":
                System.out.println("牛");
                break;
            default:
                System.out.println("强");
        }
    }
}
  • 表达式也可以是一个枚举常量
public class Test {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        String size = s.next().toUpperCase();
        switch (Enum.valueOf(Size.class,size)){
            case MEDIUM:
                System.out.println('m');
                break;
            case LARGE:
                System.out.println('l');
                break;
            case SMALL:
                System.out.println('s');
                break;
        }
    }
}

6.2、case穿透

  • default可以在switch里的任何位置,且执行时机不变,但其若在前面又不带break;语句,则也有可能出现穿透现象
  • 以下代码输出
white
blue
yellow
public class Test {
    public static void main(String[] args) {
        String color = "blind";
        switch(color){
            default:
                System.out.println("white");
            case "blue":
                System.out.println("blue");
            case "yellow":
                System.out.println("yellow");
                break;
            case "red":
                System.out.println("red");
                break;
        }
    }
}

7、短路与与逻辑与

public class Test {
    public static void main(String[] args) {
        int x = 5;
        if((--x) >= 5 && (x--) >= 4)
            System.out.println(x);
        System.out.println(x);//4
        if((--x) >= 4 & (x--) >= 3)
            System.out.println(x);
        System.out.println(x);//2
    }
}

8、else if/else的最近匹配原则

  • 注意,不是说如果有多个else if就只有第一条是和最近的else if/if匹配,视情况而定,有时候可能会所有else if语句都和最近的if/else if匹配
public class Test {
    public static void main(String[] args) {
        /*没有输出*/
        int x = 0;
        if(x > 0)
            if(x > 5) System.out.println(5);
        else System.out.println(6);
    }
}
  • 所有else if语句都和最近的if匹配
//输出2

public class Test {
    public static void main(String[] args) {
        int x = 9;
        if(x 10)
            if(x 6) System.out.println(1);
            else if(x 10) System.out.println(2);
            else if(x 15) System.out.println(3);
    }
}
  • 不是所有else if语句都和最近的if/else if匹配
//输出4

public class Test {
    public static void main(String[] args) {
        int x = 11;
        if(x 10)
            if(x 6) System.out.println(1);
            else if(x 10) System.out.println(2);
            else System.out.println(3);
        else if(x 15) System.out.println(4);
    }
}

9、for循环的循环条件部分不可使用逗号语句

public class Test {
    public static void main(String[] args) {
        //循环条件部分不能使用逗号语句,否则出现找不到j,缺少分号等错误
        for(int i = 1,j = 2;i <= 10,j <= 100;i ++,j ++){}
    }
}

10、标号必须在代码块前,但不一定要在循环前

public class Test {
    public static void main(String[] args) {
        int x = 5;
        first:if((--x) >= 5 && (x--) >= 4){}

        second:switch (x){}

        /*Not a statement*/
        //third:int y = 5;
        third:{int y = 5;}
    }
}