Java标识符规则

组成规则

  • 英文大小写字母
  • 数字字符
  • 美元符号$或下划线_

注意事项

  1. 不能以数字开头;
  2. 不能是java的关键字;
  3. 区分大小写
  4. 不能有空格
  5. 不能是字面值 ture false null
  6. 字母可以看成所有国家书面上使用的,中文也可以看成字母。(不推荐)

命名规范

  • 下划线式命名:my_name
  • 驼峰式命名:myName
  • 类,接口命名:必须是大写字母开头,比如PersonActivity
  • 方法,变量【字符串】命名:getData(),otherName
  • 常量命名:一般全是大写,比如MAX_VALUE

关键字

  • 保留字:没有特殊含义(goto ,const)

  • 定义的关键字如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    用于定义数据类型的关键字
    class interface byte short int long float double char boolean void
    用于定义数据类型值的关键字
    true false null
    用于定义流程控制的关键字
    if else switch case default while do for break continue return
    用于定义访问权限修饰符的关键字
    private protected public
    用于定义类,函数,变量修饰符的关键字
    abstract final static synchronized
    用于定义类与类之间关系的关键字
    extends implements
    用于定义建立实例及引用实例,判断实例的关键字
    new this super instanceof
    用于异常处理的关键字
    try catch finally throw throws
    用于包的关键字
    package import
    其他修饰符关键字
    native strictfp transient volatile assert

instanceof

  • 它的作用是什么?

    • instanceof是Java的一个二元操作符,和==,>,<是同一类东西。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。
  • 使用过程中注意事项有哪些?

    • 类的实例包含本身的实例,以及所有直接或间接子类的实例

    • instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误

      1
      2
      3
      4
      //比如下面就会编译错误
      String s = null;
      s instanceof null
      s instanceof Integer

this和super

  • 面向对象之this关键字
    • 为什么要有this
      • 当我们的局部变量和成员变量相同的时候,如果我们不使用this关键字,那么会导致一个问题:就是局部变量隐藏了成员变量的问题
    • this关键字特点
      • 是当前类的对象引用
      • 简单的记,它就代表当前类的一个对象。谁调用这个方法,那么该方法的内部的this就代表谁
    • this的应用场景
      • 解决局部变量隐藏成员变量
  • this和super的区别
    • A:通过问题引出super
      • 子类局部范围访问父类成员变量
    • B:说说this和super的区别
      • this 代表的是本类对象的引用
      • super 代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员)
    • C:this和super的使用
      • a:调用成员变量
        • this.成员变量 调用本类的成员变量
        • super.成员变量 调用父类的成员变量
      • b:调用构造方法
        • this(…) 调用本类的构造方法
        • super(…) 调用父类的构造方法
      • c:调用成员方法
        • this.成员方法 调用本类的成员方法
        • super.成员方法 调用父类的成员方法

常量

什么是常量和变量

  • 其值不可以改变的称之为常量
  • 其值会发生变化的称之为变量

常量有哪些

  • 字符串常量 用双引号包括的 “hello world”
  • 整型常量 所有的整数 199
  • 小数常量 所有的小数 4.50
  • 字符常量 用单引号包括的 ‘a’
  • 布尔常量 true和false
  • 空常量 null

变量

  • 用来描述值可以变化的量,比如室外温度,App活跃用户量等

    1
    2
    3
    4
    5
    6
    // 声明变量: 数据类型 变量名(,变量名,变量名);
    int age;
    // 初始化:变量名 = 值; (开辟空间,赋初值)
    age=22;
    // 边声明,变赋值
    int age = 22;

java 数据数据类型

基本数据类型

  • 基本数据类型也称为简单类型,这些类型可以分为四组:
    • 整型。包括byte,short,int,long。用于表示有符号整数。
    • 浮点型。包括float,double。用于表示带小数位的数字。
    • 字符型。包括char。用于表示字符集中的符号。
    • 布尔型。包括boolean。用于表示true/false值。
  • Java在其他方面是完全面向对象的,但基本数据类型并不是面向对象的,这样设计的原因是为了效率。将基本数据类型设计为对象会极大地降低性能。
  • Java语言的特色之一就是具备可移植性,即不管在哪个平台下运行,一份代码无需修改就可以直接运行。为了确保这一点,基本数据类型被定义为具有明确的范围和数学行为,与C和C++这类语言“允许整数的大小随着执行环境的要求而变化”不同。
  • Java语言的数据类型都具有严格定义的范围。无论在那种平台下,int总是32位的。虽然严格指定基本数据类型的范围在某些环境下会造成性能损失,但这是为了实现可移植性而必须付出的。
类型 内存(字节)大小 默认值 取值范围
byte 1 0 -128 - 127 (-2^7-1)
short 2 0 -32 768 ~ 32767(-2^15 - 1)
int 4 0 -2 147 483 648 ~ 2 147 483 647(-2^31-1)
long 8 0 -9,223,372,036,854,775,808~ 9 223 372 036 854 775 807 (2^63 -1)
float 4 0.0f 1.4e-045 ~ 3.4e+038
double 8 0.0d 4.9e-324 ~ 1.8e+308
char 2 单一的16位Unicode字符 \u000065535)
boolean 1 false true/false

整数

  • int类型经常用于控制循环变量和索引数组。

  • 对于那些不需要更大范围的int类型数值的情况,你可能会认为使用范围更小的byte和short类型效率会更高,然而事实并非如此。

    • 因为在表达式中使用byte和short值时,当对表达式求值时它们会被提升为int类型。
    • 所以,当需要使用整数时,int通常是最好的选择。
  • 如果整数字面值太长,可读性会受到影响。从Java 7开始,可用在整数字面值中使用下划线将数字分隔开。

1
2
3
4
5
6
int a =20;
// 数据可以用下划线分隔 增强可读性
int x=1_000_000; //十进制
int n5=0b1011_1111_0000; //2进制 :0b开头
int z=0_17; //8进制:0开头
int y=0x2_0;f; //16进制:0x开头

小数

  • float类型表示使用32位存储的单精度数值。在某些处理器上,单精度运行速度更快,并且占用的空间是双精度的一半,但是当数值非常大或者非常小时会变得不精确。如果需要小数部分,且精确度要求不高时,就可以考虑使用float类型。
  • double类型表示使用64位存储的双精度数值。在sin()、cos()和sqrt()这类数学函数中,返回值都是double类型。如果需要在很多次迭代运算中保持精度,或是操作非常大的数值时,double类型是最佳选择。
  • 浮点数包含以下四个部分
    • 一个整数部分
    • 一个小数点
    • 一个小数部分
    • 一个可选的指数
    • 在1.7e8中,1是整数部分,7是小数部分,8是指数
  • 在float和double类型中,0的整数部分是可选的:0.5可以写成**.5**
  • 浮点数字面值加上的后缀字母F或f表明其为float类型,如果没有标明,该浮点数字面值将是double类型
1
2
3
4
5
6
7
8
//小数 默认当做 double 来处理
double n1=11.1d;
float n2 = 22.2f;
double n3 = 2e2//200.0

//十六进制 :p以2为底  (e表示14)
double n1 = 0x1ap2; //0x1a * 2^2 = 0x1a * 4 = 26 * 4 = 104
ni = 6.0e20 + 1;    //6.0E20

小数的精确运算

  • 导包:import java.math.BigDecimal;

    1
    2
    3
    4
    5
    BigDecimal n2 = new BigDecimal("0.1");
    BigDecimal n3 = new BigDecimal("0.2");
    BigDecimal addresult = n2.add(n3);
    double result = addresult.doubleValue();
    System.out.println(result); //0.3

字符(char)

  • char是用于存储字符的数据类型。Java的设计初衷是允许程序员编写在世界范围内均可使用的语言,因此采用了Unicode标准来表示字符。Unicode定义了一个完全国际化的字符集,能够表示全部人类语言中的所有字符,为此需要使用十六位宽度来存储。char的范围是0 ~ 65536,没有负的char值。
  • 尽管char被设计为容纳Unicod字符,但也可以用作整数类型,可以对char类型的变量执行算术运算。
  • 字符字面值是一个Unicode字符,或者是单引号括起来的一个转义序列
    • ‘a’ ,’b’
    • ‘\b’ 回退字符
    • ‘\n’ 换行
    • ‘\r’ 回车
  • 计算机将字符是整数形式存储,常见的编码表
    • ASCII
    • ISO-8859-1
    • Windows-1252
    • GBK2312(97%左右)
    • GBK(所有的,包含繁体)
    • GBk18030(所有的,包含繁体,少数民族)
    • Big(台湾香港繁体字)
    • Unicode编码(全世界统一,范围:0-65535)【占2个字节】
    • UTF32(4字节,浪费空间)
    • UTF-16(双字节)
    • UTF-8(变长的,1,2,3字节)
1
2
3
4
5
6
String s = "Hello你好";
byte[] b = s.getBytes("GBK"); // 以GBK编码存储
String s1 = new String (b,"GBK");// 以GBK编码解码
String s2 = new String (b,"utf-8");// 以Utf-8解码
System.out.println(s1); //Hello你好
System.out.println(s2); // Hello???

boolean 类型

  • 布尔类型有两个值,分别为true和false。
  • 声明一个布尔变量bool: boolean bool=true;

基本数据类型存储位置

  • Java中的基本数据类型一定存储在栈中吗?

  • 答案:

    • 首先说明,”java中的基本数据类型一定存储在栈中的吗?”这句话肯定是错误的。

    • 基本数据类型是放在栈中还是放在堆中,这取决于基本类型在何处声明,下面对数据类型在内存中的存储问题来解释一下。

    • 随便举出一个反例,例如:

      1
      2
      int[] array=new int[]{1,2};
      // 由于new了一个对象,所以new int[]{1,2}这个对象时存储在堆中的,也就是说1,2这两个基本数据类型是存储在堆中,这也就很有效的反驳了基本数据类型一定是存储在栈中~~

局部变量存储位置

  • 在方法中声明的变量,即该变量是局部变量
    • 每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因。
    • 在方法中声明的变量可以是基本类型的变量,也可以是引用类型的变量。
    • 当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在JAVA虚拟机栈
    • 当声明的是引用变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在JAVA虚拟机的栈中,该变量所指向的对象是放在堆类存中的

成员变量存储位置

  • 在类中声明的变量是成员变量,也叫全局变量
    • 放在中的(因为全局变量不会随着某个方法执行结束而销毁)。
    • 同样在类中声明的变量即可是基本类型的变量,也可是引用类型的变量。
    • 当声明的是基本类型的变量其变量名及其值放在堆内存中
    • 引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象。引用变量名和对应的对象仍然存储在相应的堆

静态变量存储位置

  • 静态变量其实就是常量
    • 注意是:存储在JVM的方法区
    • static变量在类加载时被初始化,存储在JVM的方法区中,整个内存中只有一个static变量的拷贝,可以使用类名直接访问,也可以通过类的实例化对象访问,一般不推荐通过实例化对象访问,通俗的讲static变量属于类,不属于对象,任何实例化的对象访问的都是同一个static变量,任何地放都可以通过类名来访问static变量。

引用类型

    • 枚举:严格来说其实就是类类型
  • 接口
    • 注解:继承了Annotation的特殊接口
  • 数组

字符串

  • 字符串的连接:用“+”号连接

  • “+”号二边有字符串,结果为字符串。

    1
    2
    String name="张三";
    System.out.println("姓名是:"+name); //姓名是:张三

类型转换

  • 基本数据运算的时候,赋值的类型和声明的类型不一样会出现类型转换

自动类型转换

  • 由 低 (范围小的) 赋值给 高 (范围大的)

  • 整形默认 int ,小数默认 double

  • 转换的目的类型占得空间范围一定要大于转化的源类型

  • byte –> short –> int –> long –> float –> double

  • char –> int –> long –> float –> double

1
2
3
4
5
6
7
8
9
10
11
byte a = 2;
short b = a;
System.out.println(b); //2

// b=ch+1; //char - short 不能转换

//char类型参与运算
char ch = 'a';
int d = ch + 1;
System.out.println(d);//a:97 结果98

强制类型转换

  • 由 高 (范围大的)赋值给 低 (范围小的),自动类型转换的逆向过程
  • 格式: (强转数据类型)(转换数据)
  • 有的数据经过转型运算后,精度会丢失,而有的会更加精确
  • JAVA强制类型转换的时候,在编译期间,只会校验是否有继承的关系而已
    • object对象,可以在编译期强转成任何对象(因为它本身是所有对象的父类)、以及任何接口却不会报错。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args){
int x;
double y;
x = (int)34.56 + (int)11.2; // 丢失精度
y = (double)x + (double)10 + 1; // 提高精度
System.out.println("x=" + x);
System.out.println("y=" + y);
}

运行结果:
x=45
y=56.0

// 由于在 34.56 前有一个 int 的强制类型转化,所以 34.56 就变成了 34。同样 11.2 就变成了 11 了,所以 x 的结果就是 45。在 x 前有一个 double 类型的强制转换,所以 x 的值变为 45.0,而 10 的前面也被强制成 double 类型,所以也变成 10.0,所以最后 y 的值变为 56。

类型提升

  • 只有参与运算的时候才有类型提升,类型低的提成到类型高的进行运算。运算结果采取类型级别最高的类型作为结果类型。
  • Java定义了若干使用于表达式的类型提升规则:
  1. 对于一元操作符来说,如果操作数的类型是byte,short或char,运算结果提升为int类型
  2. 对与二元操作符来说,提升规则是从以下几条依次选择一条执行
  3. 所有的byte型. short型和char型将被提升到int型
    • 例外: final修饰的short, char变量相加后不会被自动提升。
  4. 如果一个操作数是long形 计算结果就是long型;
  5. 如果一个操作数是float型,计算结果就是float型;
  6. 如果一个操作数是double型,计算结果就是double型;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

public static void main (string args[]){
byte b = 50;
char c = 'a';
short s = 1024;
int i = 50000;
float f =5.67f;
double d =0.1234;
double result = (f * b) + (i / c) - (d * s);
}
第一个表达式f * b中,b被提升为float类型,该子表达式的结果也提升为float类型。
第二个表达式i / c中,变量c被提升为int类型,该子表达式的结果提升为int类型。
第三个表达式d * s中,变量s被提升为double类型,该子表达式的结果提升为double型。
最后,这三个结果类型分别是floatintdouble类型,想减后该表达式的最后的结果就是double类型。


byte a = 1;
byte b = 2;
a = a+b; //编译出错自动类型提升成int
a += b; //自加没有自动类型提升问题
把高字节转成低字节,需要作强制类型转换. byte c=(byte)a+b;


byte b1=1,b2=2,b3,b6;
final byte b4=4,b5=6;
b6=b4+b5;
//没有final修饰的变量相加后会被自动提升为int型,需要强制转换(向下转型)。
b3=(b1+b2); //会发生编译错误
System.out.println(b3+b6);


byte b;
b=3;
//编译出错,因为(byte)的运算级别比*高,所以会先转换b后再*3
b=(byte)b*3
b=(byte)(b*3) //正确

运算符

运算符有哪些

  • 算术运算符
  • 赋值运算符
  • 关系运算符
  • 逻辑运算符
  • 三目运算符
  • 特殊运算符:位运算符

根据操作数个数分类:

  • 一元  //a++
  • 二元  //a + b
  • 三元  //a>b?a:b

算术运算符

  • + ,- , * , / , %【取余】 , ++【自加】, --【自减】

  • 加法:

    • 当+号左右有字符串的时候,+ 为字符串的连接符
  • / 除法

    • 除数和被除数都是整数 ,结果为整数

    • 除数为0,时,触发java.lang.ArithmeticException: / by zero

    • 除数或被除数有小数的时候,结果为double类型

      1
      2
      3
      System.out.println(5/2.0);		//2.5
      System.out.println(5.0/2); //2.5
      System.out.println(5.0/2.0); //2.5
  • 浮点运算特殊值

    1
    2
    3
    4
    5
    6
    7
    System.out.println(0/0.0);		//NaN
    System.out.println(5/0.0); //Infinity
    System.out.println(-5/0.0); //-Infinity

    System.out.println(0.0/0); //NaN
    System.out.println(5.0/0); //Infinity
    System.out.println(-5.0/0); //-Infinity
  • 取余

    1
    2
    3
    4
    5
    6
    7
    8
    9
    System.out.println(5%0);		//java.lang.ArithmeticException: / by zero
    System.out.println(5%2); //1
    System.out.println(5%-2); //1
    System.out.println(-5%2); //-1
    System.out.println(5%0.0); //NaN
    System.out.println(5%2.0); //1.0
    System.out.println(-5%2.0); //-1.0
    System.out.println(0.0%5); //0.0
    System.out.println(-0.0%5); //-0.0
  • 自增自减运算符

    • 前自增和后自增、前自减和后自减的区别。
    • 自增(++):将变量的值加1,分前缀式(如++i)和后缀式(如i++)。
      • 前缀式是先加1再使用;
      • 后缀式是先使用再加1。
    • 自减(–):将变量的值减1,分前缀式(如–i)和后缀式(如i–)。
      • 前缀式是先减1再使用;
      • 后缀式是先使用再减1。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public static void main(String [] args){
    int i = 0;
    int j = i++ + i++; //这条语句等价于j = (i++) + (i++)
    System.out.println("输出i的结果为"+i);
    System.out.println("输出j的结果为"+j);
    }
    }
    =======================
    输出i的结果为2
    输出j的结果为1

    分析:
    第一个:因为是前缀式:(此时的i = 0)
    所以第一个(i++)==0
    第二个:因为是前缀式:(此时的i = 1)
    所以第一个(i++)==1
    所以最后的j = 1
    i自增了两次,所以 i = 2

关系运算符

  • == , > , < , >= , <= , !=
  • 运算结果是boolean类型

逻辑运算符

  • & ,^ ,| ,&& ,|| ,!
  • & ,^ ,|:还可以进行位运算
  • &&短路逻辑运算符
  • 一假为假
    • 全真为真
    • *左边为假,后边不执行*
  • ||
  • 一真为true
    • 全假为false
    • *左边为真,后边不执行*
  • 真变假,假变真
  • &,|,!
    • 不管左边为真为假,后面都要执行

赋值运算符

  • 先算右边,然后将值给左边
  • = , += , -= , *= , /= , %=
  • +=  -= *= /=运算的时候会自动强转处理
1
2
3
4
short n3 =5;
n3 = n3 + 5; //会报错 short = int
n3 += 5; //不会报错,自动强转
n3=(short)(n3+5);

三目运算符

  • a == b ? c : d

  • 格式:

    1
    表达式一 ?表达式二 : 表达式三;
    • 表达式一的结果必须为boolean类型
      • true —> 表达式二
      • false —> 表达式三
    • 结果必须接收或输出打印。

位运算符

  • & 与

    • 有一个为0,结果为0
    • 二个都为1,结果为1
  • | 或

    • 有一个为1,结果为1
    • 二个为0, 结果为0
  • ^ 异或

    • 相同为0, 不同为1
    • 一个数异或二次,结果不变
  • ~ 取反

    • 1 — 0
    • 0 — 1
    • ~a = -a -1 5取反为-6
  • <<左移

    • 向左移动 几位,右边底位用0补位
      • 这意味着左移int类型操作数时,如果某些位一旦超出31位,那么这些位将丢失。
      • 如果操作数是long类型,那么超出位63的位会丢失。
      • 当左移byte和short型数据时,Java的自动类型提升会导致意外的结果。
      • 如果左移byte型数值,会先将该数值提升为int型,然后左移。这意味着如果想要的结果是移位后的byte型数值,就必须丢弃结果的前三个字节,可以通过将结果强制转换为byte类型来完成位数截取。
    • 因为每次左移都相当于将原始值乘2,所以可以将之作为乘法的搞笑替代方法。
    • 但是如果将二进制1移进高阶位,结果将会变成负数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public static void main(String[] args) {
    public static void main(String[] args) {
    //0011 1100
    byte a = 60;
    // a首先被提升为int类型,即(0000 0000 0000 0000 0000 0000 0011 1100)
    // 左移两位,结果为(0000 0000 0000 0000 0000 0000 1111 0000),即240
    int i = a << 2;
    // 先左移两位,结果为(0000 0000 0000 0000 0000 0011 1100 0000)
    // 舍弃前三个字节,得到(1100 0000),即-64
    byte b = (byte) (i << 2);
    System.out.println("i等于:" + i);
    System.out.println("b等于:" + b);
    }
    }

    // 输出结果是:
    i等于:240
    b等于:-64
  • >>右移

    • 向右移动 几位, 左边高位,是什么用什么补位
    • 每次右移一位,相当于将该值除以2,并舍弃所有余数
    • 当进行右移操作时,右移后的顶部(最左边)位使用右移前顶部为使用的值填充,这称为符号扩展。当对负数进行右移操作时,该特性可以保留负数的符号。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public static void main(String[] args) {
    //0011 1100
    byte a = 60;
    // a首先被提升为int类型,即(0000 0000 0000 0000 0000 0000 0011 1100)
    // 右移两位,结果为(0000 0000 0000 0000 0000 0000 0000 1111),即15
    int i = a >> 2;
    // 先右移两位,结果为(0000 0000 0000 0000 0000 0000 0000 0011)
    // 舍弃前三个字节,得到(0000 0011),即3
    byte b = (byte) (i >> 2);
    System.out.println("i等于:" + i);
    System.out.println("b等于:" + b);
    }

    i等于:15
    b等于:3


    public static void main(String[] args) {
    byte a=(byte) 0b11111000;
    System.out.println("a等于:"+a);
    int b=a>>1;
    System.out.println("b等于:"+b);
    }
    a等于:-8
    b等于:-4
  • >>>无符号右移

    • 每次移位时,“>>”运算符自动使用原来的内容填充高阶位,这个特性可以保持数值的正负性。
    • 有时候对那些非数值的内容进行移位操作,并不关心高阶位初始值是多少,只希望用0来填充高阶位,这就是无符号右移。
    • Java的无符号右移运算符“>>>”,该运算符总是将0移进高阶位。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int a=3;
System.out.println(a<<2); //3*4=12
System.out.println(a>>1); //3/2=1
System.out.println(5>>>2); //5/4=1
int a1=-4;
System.out.println(a1<<2); //-4*4=-16
System.out.println(a1>>1); //-4/2=-2
System.out.println(a1>>>28); //15


11111111 11111111 11111111 11111100
>>>28 00000000 00000000 00000000 00001111 =8+4+2+1=15
>> 28 11111111 11111111 11111111 11111111 =-1
------------------------------------------

负数用补码表示 11111111 11111111 11111111 11111111
转换为原码: 10000000 00000000 00000000 00000001 = -1

运算符的优先级

  • 括号>单元操作符>算术运算符>移位操作符>关系运算符>位运算符>逻辑运算符>三元操作符>赋值运算符
  • 口诀:单目乘除为(位)关系,逻辑三目后赋值。
    • 单目:单目运算符+ –(负数) ++ – 等
    • 乘除:算数单目运算符* / % + -
    • 为:位移单目运算符<< >>
    • 关系:关系单目运算符> < >= <= == !=
    • 逻辑:逻辑单目运算符&& || & | ^
    • 三目:三目单目运算符A > B ? X : Y
    • 后:无意义,仅仅为了凑字数
    • 赋值:赋值=