一、Java程序基本结构

1.1 基本结构

Java程序基本结构示例代码:

/**
* 这里是文档注释
* 这是一个HelloWorld程序
*/
public class HelloWorld {public static void main(String[] args) {// 向控制台输出文本:System.out.println("Hello, world!");/* 这里是多行注释注释内容*/}
} 

1.2 结构解析

1、Java是面向对象的语言,一个程序的基本单位就是class,class是关键字,这里定义的class名字就是HelloWorld,类的概念,会在后面的面向对象部分学习。这里我们可以认为,所有的Java程序,必须写在一个类里。

2、public是访问修饰符,表示该class是公开的。

3、{...}类名HelloWorld后面的大括号,是类的内容。大括号要前后对应。

4. 在class内部,可以定义若干方法(method),方法定义了一组执行语句,方法内部的代码将会被依次顺序执行。
这里的方法名是main,返回值是void,表示没有任何返回值。在java中main()表示程序的执行入口;

5、我们注意到public除了可以修饰class外,也可以修饰方法。而关键字static是另一个修饰符,它表示静态方法,后面我们会讲解方法的类型,目前,我们只需要知道,Java入口程序规定的方法必须是静态方法,方法名必须为main,括号内的参数必须是String数组。

6、java编译器为每个类生成一个字节码文件(也就是后缀名为class的文件),且文件名与类名相同,同名的类有可能发生冲突。为了解决这一问题,java提供包来管理类名空间,什么是包呢,实际就是文件夹。相同的名字的类,在不同的包下,就像是同样的东西,放在不同的抽屉中一样.

7、一个java源文件,可以有多个类,但是只能有一个公共类(由public修饰的类),而且经过编译之后,会生成与类名对应的字节码文件(有几个类就有几个字节码文件)。

二、Java关键字和保留字

正确识别java语言的关键字(keyword)和保留字(reserved word)是十分重要的。
    
        Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等。保留字是为java预留的关键字,他们虽然现在没有作为关键字,但在以后的升级版本中有可能作为关键字。
    
        识别java语言的关键字,不要和其他语言如c/c++的关键字混淆。

2.1 关键字(keyword)

定义:被Java语言赋予了特殊含义,用做专门用途的单词。在给类、变量等命名是不能使用。
    
        特点:所有字母都小写。(在很多编程软件中会显示出一种颜色)。

官方地址:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html

用于定义数据类型的关键字:

关键字 含义 描述
class 用来声明新的 Java类,该类是相关变量和/或方法的集合。类是面向对象的程序设计方法的基本构造单位。类通常代表某种实际实体,如几何形状或人。类是对象的模板。每个对象都是类的一个实例。要使用类,通常使用 new 操作符将类的对象实例化,然后调用类的方法来访问类的功能。
interface 接口 用来声明新的 Java 接口,接口是方法的集合。接口是 Java 语言的一项强大功能。任何类都可声明它实现一个或多个接口,这意味着它实现了在这些接口中所定义的所有方法。 实现了接口的任何类都必须提供在该接口中的所有方法的实现。一个类可以实现多个接口。
enum 枚举 枚举类型,可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。这句话是个什么意思呢? 你比如说季节类,它只能有春夏秋冬四个对象;星期类,他只有周一到周天七个对象。诸如这种对象的个数有限的,我们都可以用枚举实现它。
byte 字节型 Java 原始类型。byte 可存储在 [-128, 127] 范围以内的整数值。
short 短整型 Java 原始类型。short 变量可以存储 16 位带符号的整数。
int 整型 Java 原始类型。int 变量可以存储 32 位的整数值。
long 长整型 Java 原始类型。long 变量可以存储 64 位的带符号整数。
float 单精度浮点型 Java 原始类型。float 变量可以存储单精度浮点值。 使用此关键字时应遵循下列规则: Java 中的浮点文字始终默认为双精度。要指定单精度文字值,应在数值后加上 f 或 F,如 0.01f。
double 双精度浮点型 Java 原始类型。double 变量可以存储双精度浮点值。
char 字符型 Java 原始类型。char 变量可以存储一个 Unicode 字符。
boolean 布尔型 Java 原始类型。boolean 变量的值可以是 true 或 false。 boolean 变量只能以 true 或 false 作为值。boolean 不能与数字类型相互转换。
void 无返回值 void 可以用作方法的返回类型,以指示该方法不返回值。

用于定义流程控制的关键字:

关键字 含义 描述
if 如果 指示有条件地执行代码块。条件的计算结果必须是布尔值。 if 语句可以有可选的 else 子句,该子句包含条件为 false 时将执行的代码。 包含 boolean 操作数的表达式只能包含 boolean 操作数。
else 否则,或者 总是在 if-else 语句中与 if 关键字结合使用。else 子句是可选的,如果 if 条件为 false,则执行该子句。
switch 开关 用于基于某个表达式选择执行多个代码块中的某一个。
case 返回开关里的结果 用来标记 switch 语句中的每个分支。 case 块没有隐式结束点。break 语句通常在每个 case 块末尾使用,用于退出 switch 语句。 如果没有 break 语句,执行流将进入所有后面的 case 和/或 default 块。
default 默认 用来标记 switch 语句中的默认分支。 default 块没有隐式结束点。break 语句通常在每个 case 或 default 块的末尾使用,以便在完成块时退出 switch 语句。 如果没有 default 语句,其参数与任何 case 块都不匹配的 switch 语句将不执行任何操作。
while 当什么的时候 用于指定一个只要条件为真就会重复的循环。
do 运行 用于指定一个在每次迭代结束时检查其条件的循环。 do 循环体至少执行一次。 条件表达式后面必须有分号。
for 满足三个条件时 用于指定一个在每次迭代结束前检查其条件的循环。
break 跳出循环 用于提前退出 for、while 或 do 循环,或者在 switch 语句中用来结束 case 块。 break 总是退出最深层的 while、for、do 或 switch 语句。
continue 继续 用来跳转到 for、while 或 do 循环的下一个迭代。 continue 总是跳到最深层 while、for 或 do 语句的下一个迭代。
return 返回 会导致方法返回到调用它的方法,从而传递与返回方法的返回类型匹配的值。 如果方法具有非 void 的返回类型,return 语句必须具有相同或兼容类型的参数。 返回值两侧的括号是可选的。

用于定义访问权限修饰符的关键字:

关键字 含义 描述
private 私有的 可以应用于类、方法或字段(类中声明的变量),只能在声明的类内部中引用这些类、方法或字段,在外部或者对于子类而言是不可见的,类的默认访问范围是package访问,除非存在特殊的访问控制修饰符。可以从一个包中的任何类访问类成员
protected 受保护的 应用于类、方法或字段(类中声明的变量),可以在声明 protected 类、方法或字段的类、同一个包中的其他任何类以及任何子类(无论子类是在哪个包中声明的)中引用这些类、方法或字段。
public 公有的 应用于类、方法或字段(在类中声明的变量)的访问控制修饰符。 可能只会在其他任何类或包中引用 public 类、方法或字段。

用于定义类,函数,变量修饰符的关键字:

关键字 含义 描述
abstract 声明抽象 可以修改类或方法。abstract类可以扩展(增加子类),但不能直接实例化。abstract方法不在声明它的类中实现,但必须在某个子类中重写。采用 abstract方法的类本来就是抽象类,并且必须声明为abstract。
final 最终的不可被改变的 方法和类都可以用final来修饰。final修饰的类是不能被继承的 修饰的方法是不能被子类重写。常量的定义:final修饰的属性就是常量。
static 静态的 属性和方法都可以用static修饰,直接使用类名.属性和方法名。 只有内部类可以使用static关键字修饰,调用直接使用类名.内部类类名进行调用。 static可以独立存在。静态块
synchronized 线程,同步 可以应用于方法或语句块,并为一次只应由一个线程执行的关键代码段提供保护。 可防止代码的关键代码段一次被多个线程执行。

用于定义类与类之间关系的关键字:

关键字 含义 描述
extends 继承 用在 class 或 interface 声明中,用于指示所声明的类或接口是其名称后跟有 extends 关键字的类或接口的子类。子类继承父类的所有 public 和 protected 变量和方法。 子类可以重写父类的任何非 final 方法。一个类只能扩展一个其他类。
implements 实现 在 class 声明中使用,以指示所声明的类提供了在 implements 关键字后面的名称所指定的接口中所声明的所有方法的实现。类必须提供在接口中所声明的所有方法的实现。一个类可以实现多个接口。

用于定义建立实例及引用实例,判断实例的关键字:

关键字 含义 描述
new 新建、实例化 用于创建类的新实例。 new 关键字后面的参数必须是类名,并且类名的后面必须是一组构造方法参数(必须带括号)。
this 当前类的对象 用于引用当前实例。 当引用可能不明确时,可以使用 this 关键字来引用当前的实例。
super 调用父类的 用于引用使用该关键字的类的超类。
instanceof 实例判断 用来确定对象所属的类。

用于异常处理的关键字:

关键字 含义 描述
try 捕获异常 用于包含可能引发异常的语句块。 每个 try 块都必须至少有一个 catch 或 finally 子句。
catch 处理异常 用来在 try-catch 或 try-catch-finally 语句中定义异常处理块。
finally 最终的,有没有异常都执行 用在异常处理的最后一个语句块,无论是否产生异常都要被执行。finally是对异常处理的最佳补充使代码总要被执行,使用finally可以维护对象的内部状态,并可以清理非内存资源。
throw 抛出一个异常对象 用于引发异常。
throws 声明一个异常可能被抛出 可以应用于方法,以便指出方法引发了特定类型的异常。throws 关键字将逗号分隔的 java.lang.Throwables 列表作为参数。

用于包的关键字:

关键字 含义 描述
package 定义包的关键字 指定在 Java 源文件中声明的类所驻留的 Java 包。 package 语句(如果出现)必须是 Java 源文件中的第一个非注释性文本。 例:java.lang.Object。 如果 Java 源文件不包含 package 语句,在该文件中定义的类将位于“默认包”中。
import 引入包的关键字 使一个包中的一个或所有类在当前 Java 源文件中可见。

其他修饰符关键字:

关键字 含义 描述
native 本地 以指示该方法是用 Java 以外的语言实现的。Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
strictfp 严格,精准 strictfp的意思是FP-strict,也就是说精确浮点的意思。
transient 短暂 可以应用于类的成员变量,以便指出该成员变量不应在包含它的类实例已序列化时被序列化。
volatile 易失 用于表示可以被多个线程异步修改的成员变量。volatile 的目标用途是为了确保所有线程所看到的指定变量的值都是相同的。Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;
assert 断言 表示断言,如果为true,则程序继续执行,如果为false,则程序抛出AssertionError并终止运行。

用于定义数据类型值的字面值:

关键字 含义 描述
true 表示 boolean 变量的两个合法值中的一个。
false 代表 boolean 变量的两个合法值之一。
null 表示空值。 将 null 赋给非原始变量相当于释放该变量先前所引用的对象。

2.2 保留字

保留字(reserved words):是语言已经定义过的字,一些保留字可能没有相对应的语法,考虑到扩展性,为了向后兼容不能再将其作为变量名。

const和goto是java的保留字。

三、Java标识符及命名规范

3.1 标识符概述

应该说命名规范是一种约定,也是程序员之间良好沟通的桥梁。良好的命名规范可以为团队合作开发推波助澜,无论在项目开发,还是产品维护上都起到了至关重要的作用。

Java 对各种变量、方法和类、接口等要素命名时使用的字符序列称为标识符(在Java里面,所有可以自己起名字的地方都叫标识符)。

3.2 标识符命名规则

1、由字母(含大小写)、数字、下划线“_”、美元符“$”组成。
        2、不能以数字开头。
        3、不可以是Java的关键字和保留字,但能包含关键字和保留字。
        4、严格区分大小写,且长度无限制。

注:如果不遵守标识符命名规则,编译不通过,需要严格遵守。

3.3 标识符命名规范

1、见名之意。
                为了提高阅读性,要尽量有意义,“见名知意”。
        2、驼峰原则:首字母小写,多个单词组成的话,首个单词的首字母小写,之后每个单词的首字母都大写

Java采用匈牙利命名规范,它的基本原则是名称要有明确的意义。具体要求为:
                类名/接口名:首字母大写,如果包含多个单词,每个单词首字母都大写:XxxYyyZzz
                变量名/方法名:首字母小写,如果包含多个单词,每个单词首字母都大写:xxxYyyZzz
                常量名:全部大写,多个单词组成,则每个单词由_分割:XXX_YYY_ZZZ
                包名:全部小写,多单词组成时所有字母都小写:xxxyyyzzz。
                        我们在项目中,包名一律使用这种方式:[cn.]com.公司名.项目名.模块名

注:java采用unicode字符集,因此标识符也可以使用汉字声明,但是不建议使用。

四、Java变量

4.1 变量的概念

在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量。
                程序运行过程中会发生改变的量,叫变量
                程序运行过程中不允许发生改变的量,叫常量

变量的本质:其实就是内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化,不同数据存入具有不同内存地址的空间,相互独立。

变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值

变量的作用:用于在内存中保存数据

内存如何存放数据:

电脑使用内存来记忆程序运行所使用的数据(程序中所有的数据都是存储在内存里面)

内存如何存储数据?
                1、开房间(单人间、双人间、总统套间)     
                2、入住

内存像旅馆
                数据各式各样,要先根据数据的需求(即类型)为它申请一块合适的空间

已经将数据存入内存,但是:怎么找到存入的数据?

内存地址不好记,怎么办?
                通过内存中房间的别名找到数据存储的位置。

通过变量名可以简单快速地找到它存储的数据。

4.2 变量的定义与使用

要声明一个变量,需要指明变量的类型和变量名称。
        语法为:数据类型 变量名称
        例如:int var;
    
变量的赋值可以通过=,可以在先声明后赋值,也可以在声明变量时直接赋值。
        语法为:变量名称 = 值
        例如:var = 10;

声明并赋值变量。
        语法为:数据类型 变量名 = 初始化值
        例如:int var = 10;
    
使用变量,只需要使用变量名,就可以得到该变量的值。
        例如:System.out.println(var);

变量赋值后,可以改变。

Java变量示例代码:

// 声明变量,即“根据数据类型在内存申请空间” 数据类型 变量名;
int num;// 赋值,即“将数据存储至对应的内存空间”
num = 100;// 使用变量,即“取出数据使用”
System.out.println(num);//声明变赋值语法
int age = 100;//重新赋值
age = 200;
age = 250;
String name = "张三";

使用变量注意事项:

1、Java中每个变量必须先声明,后使用
        2、使用变量名来访问这块区域的数据
        3、变量的作用域:其定义所在的一对{ }内 变量只有在其作用域内才有效
        4、同一个作用域内,不能定义重名的变量

4.3 变量的分类

按数据类型划分:

对于每一种数据都定义了明确的具体数据类型(强类型语言),在内存中分配了不同大小的内存空间。

按声明的位置划分:

在方法体外,类体内声明的变量称为成员变量。

在方法体内部声明的变量称为局部变量,局部变量必须先声明并赋值才可以使用;

注意:类外面(类对应的大括号外面)不能有变量的声明不能有任何代码出现。

局部变量、成员变量、静态变量的区别:

局部变量定义在方法内部或语句块内部; 成员变量定义在方法外部,类内部; 静态变量定义在方法外部,类内部,由static修饰;
        局部变量没有初始值,必须先赋值才能使用; 成员变量和静态变量都由默认的初始值;
        局部变量通过变量名调用; 成员变量通过对象调用; 静态变量既可以通过对象调用,也可以通过类名调用;
        局部变量在栈内存; 成员变量在堆内存; 静态变量在方法区;
        局部变量的生命周期: 与方法共存亡; 成员变量的生命周期: 与对象共存亡; 静态变量的生命周期: 与类共存亡;

4.4 变量的数据类型

Java语言是一门强类型语言,也就是说,每个变量或者符号常量甚至一个方法都必须有明确的数据类型或者是返回值类型。在 Java 中,数据类型分为两种,分别是基本类型和引用类型。
    
        基本类型一共有四大类八种基本数据类型,它们是:四种整型,两种浮点型,一种字符型和一种布尔型。
        引用类型有类,接口和数组等

4.4.1 基本数据类型

Java八种基本数据介绍:
        1、boolean:数据值只有true或false,适用于逻辑计算,占一字节
        2、byte:byte型(字节型)数据在内存中占用1个字节,表示的存储数据范围为:-128~127,因为第一位是符号位。
        3、char:char型(字符型)数据在内存中占用2个字节。char型数据用来表示通常意义上的字符。
        4、short:short型(短整型)数据在内存中占用2个字节
        5、int:int型(整型)数据在内存中占用4个字节。
        6、long:long型(长整型)数据在内存中占用8个字节。
        7、float:float型(单精度浮点型)数据在内存中占用4个字节。
        8、double:double型(双精度浮点型)数据在内存中占用8个字节。

1、整数类型

从小到大取值范围分别是:byte、short、int、long。
    
        Java各整数类型有固定的表述范围和字段长度,不受具体 OS 的影响,以保证 java 程序的可移植性。
    
        Java 的整型常量默认为 int 型,声明 long 型常量须后加 ‘l’ 或 ‘L’

1个字节 = 8bit,每一个bit都有两种情况 0 或 1,所以就存在2的8次方种组合,就可以存储256个数,语言规定一半正,一半负,但是因为存在0,所以规定是-128 - 127。

表数范围公式:-2^位数-1次幂 ~ 2^位数-1次幂 - 1

Java整数类型示例代码:

// 定义byte类型变量
byte b1 = 100;// 定义short类型变量
short s1 = -100;// 定义int类型变量
int i1 = 100000;// 定义long类型变量
lonf l1 = 123456789L;

2、浮点类型

与整数类型类似,Java 浮点类型也有固定的表数范围和字段长度,不受具体OS的影响。
    
        浮点型常量有两种表示形式:
                十进制数形式:如:5.12 512.0f 
                科学计数法形式:如:5.12e2 512E2 100E-2
    
        float:单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求。
        double:双精度,精度是float的两倍。通常采用此类型。

Java 的浮点型默认为 double 型,声明 float 型变量,须后加 ‘f’ 或 ‘F’。

为什么float 4个字节比long 8个字节所表示的数值范围还大?

为了方便说明,这里借用维基百科中【单精度浮点数】定义中的一张图。

其中,左边第一位为符号位,0表示正,1表示负。上图中sign为0,所以为正数。

中间8bit表示指数,但是这里和byte不同,byte型也是8bit,表示的数值范围是-27到27-1,即-128到127。这里exponent的8bit表示的则是-127到128。在IEEE 754(IEEE二进制浮点数算术标准)中规定,在指数的实际值上要加上一个固定的值,目的是为了方便浮点数的计算,该固定值为2e-1-1,其中e表示存储指数的bit的长度。在单精度浮点数中,e的值为8,所以固定值是127。所以,exponent中存储的数值是0(-127+127)到255(128+127),共256个数。在上图中,指数部分存储的是01111100,转换为十进制是124,124减去127(加的固定值)即为实际指数值,即-3。

在小数部分中,最左侧省略了一个1,上图中的小数部分为01,其实就是1.01(二进制),转换为十进制就是1+2-2(这里看不懂的话去复习二进制小数转十进制)。
        所以,最终上图所表示的数值为(-1)sign × \times× fraction × \times× 2exponent = (+1) × \times× (1 + 2-2) × \times× 2-3 = 0.15625。

不过还没有结束,关于浮点数其实还分为零、非规约形式,规约形式、无穷以及NaN,以4字节单精度浮点数为例,具体如下:

形式 指数 小数部分
0(实际-127) 0
非规约形式 0(实际-126) 大于0小于1
规约形式 1到254(实际-126到127) 大于等于1小于2
无穷 255(实际128) 非0
NaN 255(实际128) 非0

规约形式的浮点数就是指数大于0小于等于2e-2(e为8时值为254),fraction最高位省略了1。“规约”就是指用唯一确定的浮点形式去表示一个值。

如果指数部分的值为0(实际-126,为什么不是0-固定值127 = -127?因为IEEE 754规定非规约形式的浮点数的指数偏移值比规约形式的浮点数的指数偏移值小1),小数部分不为0,那么这个浮点数就是非规约形式的浮点数,这个时候最高位省略的就不是1了,而是0了,所以小数部分是大于0小于1的。所有的非规约浮点数比规约浮点数更加接近0。

下面列出了单精度浮点数各种极值的情况:

我们常说的float型的表示范围其实说的是单精度浮点数最大的规约数的范围。

回到这个问题,我想你已经有答案了。
                就是float型它有指数部分,规约数的指数可以表示到2127,差不多是1038这么大。

3、字符类型

char 型数据用来表示通常意义上“字符”(2字节)。
    
        Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符。

字符型变量的三种表现形式:
        字符常量是用单引号(‘ ’)括起来的单个字符。
                例如:char c1 = 'a'; char c2 = '中'; char c3 = '9';
        Java中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。
                例如:char c3 = ‘\n’; // '\n'表示换行符
        直接使用 Unicode 值来表示字符型常量:‘\uXXXX’。其中,XXXX代表一个十六进制整数。如:\u000a 表示 \n。

char类型是可以进行运算的。因为它都对应有Unicode码。

注:window cmd窗口的默认字符集是GBK,为了不乱码,Java文件应该以ANSI(window10没有GBK可选)。

4、布尔类型

boolean 类型适于逻辑运算,一般用于程序流程控制:
                if条件控制语句; 
                while循环控制语句;
                do-while循环控制语句;  
                for循环控制语句;
    
        boolean类型数据只允许取值true和false,无null。
                不可以使用0或非 0 的整数替代false和true,这点和C语言不同。
                Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达所操作的boolean值,在编译之后都使用java虚拟机中的int数据类型来代替:true用1表示,false用0表示。

4.4.2 引用数据类型

引用数据类型:类、接口、数组;
    
        String不是基本数据类型,属于引用数据类型。
    
        使用方式与基本数据类型一致。例如:String str = “abcd”;
    
        一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据。例如:
                String str = "qq";
                str = str + “xyz” ;
                int n = 100;
                str = str + n;
        
        注:我们暂且讲解String,其他内容在后面讲解。

4.5 基本数据类型转换

4.5.1 自动类型转换

容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:

将一种类型的变量赋给另一种类型的变量时,只要满足以下条件,就会发生自动类型转换。
                两种类型兼容;
                目标类型大于源类型;

有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。

byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。

boolean类型不能与其它数据类型运算。

当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。

注:这里的容量大小指的是表示数的范围的大小。比如float容量要大于long的容量。

4.5.2 强制类型转换

自动类型转换(隐式转换)的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(),但可能造成精度降低或溢出,格外要注意。

通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。
                例如: String a = “43”; int i = Integer.parseInt(a);

boolean类型不可以转换为其它的数据类型。

判断是否能通过编译:

short s = 100;
s = s-1; //判断:nobyte b = 10;
b = b + 4; //判断:no
b = (byte)(b+4); //判断:yeschar c = 'a';
int i = 5;
float d = .314F;
double result = c+i+d; //判断:yesbyte b = 5;
short s = 3;
short t = s + b; //判断:no

4.5.3 类型转换对于表达式

如果一个操作数为 long 型,则整个表达式提升为 long 型。
        如果一个操作数为 float 型,则整个表达式提升为 float 型。
        如果一个操作数为 double 型,则整个表达式提升为 double 型。
        在整个运算表达式中找到最大的类型,这个类型及是表达式运算后的类型。

4.6 理解字符集

所有的一切,在计算机物理设备上保存的都是二进制数,因此在代码文件中的代码保存的也都是二进制数。

那么,所谓字符集就是对一个字符采取的编码方式(按多少位去存储、传输、读取一个字符)。

当出现乱码的时候,就是存储的方式是字符集A,读取的时候确是按照字符集B读取的,所以导致乱码问题。

字符集可以理解成一个对照表,某种编码规则的字符集规定:机器内某个长度一定二进制数表示代表一个对应的字符;

乱码:世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。

4.6.1 ASCII 码

ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符 。比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

缺点:
                不能表示所有字符。
                相同的编码表示的字符不一样:比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel(ג)。

4.6.2 Unicode 编码

统一码,也叫万国码、单一码(Unicode)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式发布1.0版本,2020年发布13.0版本。

缺点:Unicode 只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储:无法区别 Unicode 和 ASCII:计算机无法区分三个字节表示一个符号还是分别表示三个符号。另外,我们知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储空间来说是极大的浪费。

4.6.3 UTF-8

UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是针对Unicode的一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部分修改后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。

UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式。
        UTF-8 是一种变长的编码方式。它可以使用 1-6 个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则:
                对于单字节的UTF-8编码,该字节的最高位为0,其余7位用来对字符进行编码(等同于ASCII码)。
                对于多字节的UTF-8编码,如果编码包含 n 个字节,那么第一个字节的前 n 位为1,第一个字节的第 n+1 位为0,该字节的剩余各位用来对字符进行编码。在第一个字节之后的所有的字节,都是最高两位为"10",其余6位用来对字符进行编码。

五、原码、反码、补码

5.1 机器数和真值

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。
        比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。那么,这里的 00000011 和 10000011 就是机器数。
    
        因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
        例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

5.2 原码

原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码。

举例说明,比如如果是8位二进制:
                [+1]原 = 0000 0001
                [-1]原 = 1000 0001

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:
                [1111 1111 , 0111 1111],即:[-127 , 127]

原码是人脑最容易理解和计算的表示方式.

但是原码有几个缺点,零分两种 +0 和 -0 。很奇怪是吧!还有,在进行不同符号的加法运算或者同符号的减法运算的时候,不能直接判断出结果的正负。你需要将两个值的绝对值进行比较,然后进行加减操作 ,最后符号位由绝对值大的决定。于是反码就产生了。

5.3 反码

反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。

举例说明:
                [+1] = [00000001]原 = [00000001]反
                [-1] = [10000001]原 = [11111110]反

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算。

5.4 补码

补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

还是举例说明:
                [+1] = [00000001]原 = [00000001]反 = [00000001]补
                [-1] = [10000001]原 = [11111110]反 = [11111111]补

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

5.5 为何要使用原码, 反码和补码

在开始深入学习前, 我的学习建议是先”死记硬背”上面的原码, 反码和补码的表示方式以及计算方法。

现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:
                [+1] = [00000001]原 = [00000001]反 = [00000001]补
    
        所以不需要过多解释. 但是对于负数:
                [-1] = [10000001]原 = [11111110]反 = [11111111]补
        可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘除已经是最基础的运算, 要设计的尽量简单. 计算机辨别”符号位”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码。计算十进制的表达式: 1-1=0
                1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码。计算十进制的表达式:1-1=0
                1 - 1 = 1 + (-1)
                = [0000 0001]原 + [1000 0001]原
                = [0000 0001]反 + [1111 1110]反
                = [1111 1111]反 = [1000 0000]原
                = -0

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在”0”这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:
                1-1 = 1 + (-1)
                = [0000 0001]原 + [1000 0001]原
                = [0000 0001]补 + [1111 1111]补
                = [0000 0000]补=[0000 0000]原

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
                (-1) + (-127) = [1000 0001]原 + [1111 1111]原
                = [1111 1111]补 + [1000 0001]补
                = [1000 0000]补

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

简单理解:计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。

5.6 总结

正数的反码和补码都与原码相同。

负数的反码为对该数的原码除符号位外各位取反。
        负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1  
        对于负数原码转补码 符号位不变,然后按位取反+1;
        对于负数补转原码 符号位不变,然后按位取反+1;

六、进制与进制转换

进制也就是进位计数制,是人为定义的带进位的计数方法。 对于任何一种进制---X进制,就表示每一位置上的数运算时都是逢X进一位。

十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。.比如在运算中常见的进制有十进制、二进制、八进制、十六进制,在日常生活中星期是七进制,秒是60进制,月是12进制等等。

二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。

所有数字在计算机底层都以二进制形式存在,计算机以二进制补码的形式保存所有的整数。

对于整数,有四种表示方式:
                二进制(binary):0,1 ,满2进1.以0b或0B开头。
                十进制(decimal):0-9 ,满10进1。
                八进制(octal):0-7 ,满8进1. 以数字0开头表示。
                十六进制(hex):0-9及A-F,满16进1. 以0x或0X开头表示。此处的A-F不区分大小写。如:0x21AF +1= 0X21B0。

进制的四种表示方式示例代码:

int num1 = 0b110;
int num2 = 110;
int num3 = 0127;
int num4 = 0x110A;System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
System.out.println("num3 = " + num3);
System.out.println("num4 = " + num4);

6.1 二进制和十进制之间的转换

二进制转十进制

方法为:二进制转换成十进制,需要二进制的每一位的数值乘以相应的2的幂次方,然后相加。

基数: X进制的基数是X
                系数: 每一位上面的数值
                权: 每一位上基数的幂(乘方)

公式:系数乘以基数的权次幂

十进制转二进制

方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。

6.2 二进制与八进制之间的转换

二进制转八进制

方法为:3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。

八进制转成二进制

方法为:八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。

6.3 二进制与十六进制之间的转换

二进制转十六进制

方法为:与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。

十六进制转二进制

方法为:十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。

6.4 十进制与八进制与十六进制之间的转换

十进制转八进制或十六进制有两种方法

第一:间接法—把十进制转成二进制,然后再由二进制转成八进制或者十六进制。这里不再做图片用法解释。

第二:直接法—把十进制转八进制或者十六进制按照除8或者16取余,直到商为0为止。

八进制或者十六进制转成十进制

方法为:把八进制、十六进制数按权展开、相加即得十进制数。

6.5 十六进制与八进制之间的转换

八进制与十六进制之间的转换有两种方法
                第一种:他们之间的转换可以先转成二进制然后再相互转换。
                第二种:他们之间的转换可以先转成十进制然后再相互转换。

七、Java运算符

Java提供了一组丰富的运算符来操作变量,运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。我们可以将所有Java运算符划分为以下几个分类:
        算术运算符
        关系运算符(比较运算符)
        按位运算符
        逻辑运算符
        赋值运算符
        其他运算符

7.1 算术运算符

算术运算符在数学表达式中的使用方式与在代数中使用的方式相同。下表列出了算术运算符的使用示例 - 假设整数类型变量A的值为:10,变量B的值为:20,则

注: 算数运算符一般是用来做数值运算的(char类型可以参与到数值运算);但是在java里面,字符串可以和任意数据类型做+运算,都是字符串的拼接。

操作符 描述 例子
+ 加法 - 相加运算符两侧的值 A + B 等于 30
- 减法 - 左操作数减去右操作数 A – B 等于 -10
* 乘法 - 相乘操作符两侧的值 A * B等于200
/ 除法 - 左操作数除以右操作数 B / A等于2
取余 - 左操作数除以右操作数的余数 B%A等于0
++ 自增: 操作数的值增加1 B++ 或 ++B 等于 21
-- 自减: 操作数的值减少1 B-- 或 --B 等于 19

Java算术运算符示例代码:

public class Test {public static void main(String args[]) {int a = 10;int b = 20;int c = 25;int d = 25;System.out.println("a + b = " + (a + b) ); System.out.println("a - b = " + (a - b) ); System.out.println("a * b = " + (a * b) );System.out.println("b / a = " + (b / a) );System.out.println("b % a = " + (b % a) );System.out.println("c % a = " + (c % a) );System.out.println("a++   = " +  (a++) );System.out.println("b--   = " +  (a--) );// 对比 d++ 和 ++d 有什么区别System.out.println("d++   = " +  (d++) );System.out.println("++d   = " +  (++d) );//除号:/int num1 = 12;int num2 = 5;int result1 = num1 / num2;System.out.println(result1);//2int result2 = num1 / num2 * num2;System.out.println(result2);//10double result3 = num1 / num2;System.out.println(result3);//2.0}
}

运行结果为:

a + b = 30
a - b = -10
a * b = 200
b / a = 2
b % a = 0
c % a = 5
a++   = 10
b--   = 11
d++   = 25
++d   = 27

除法运算的注意事项:

1、两个整数类型做运算,得到的肯定是整数类型
        2、0不能作为除数,但是和浮点类型做运算可以作为除数

int num1 = 12;
int num2 = 5;
int result1 = num1 / num2;
System.out.println(result1);//2int result2 = num1 / num2 * num2;
System.out.println(result2);//10double result3 = num1 / num2;
System.out.println(result3);//2.0double result4 = num1 / num2 + 0.0;//2.0
double result5 = num1 / (num2 + 0.0);//2.4
double result6 = (double)num1 / num2;//2.4
double result7 = (double)(num1 / num2);//2.0
System.out.println(result5);
System.out.println(result6);

取余运算的注意事项:

取余结果的符号与被模数的符号相同;

int m1 = 12;
int n1 = 5;
System.out.println("m1 % n1 = " + m1 % n1);int m2 = -12;
int n2 = 5;
System.out.println("m2 % n2 = " + m2 % n2);int m3 = 12;
int n3 = -5;
System.out.println("m3 % n3 = " + m3 % n3);int m4 = -12;
int n4 = -5;
System.out.println("m4 % n4 = " + m4 % n4);

自增(++)自减(--)运算符是一种特殊的算术运算符,在算术运算符中需要两个操作数来进行运算,而自增自减运算符是一个操作数。

Java自增自减运算符示例代码:

public class selfAddMinus{public static void main(String[] args){int a = 3;//定义一个变量;int b = ++a;//自增运算int c = 3;int d = --c;//自减运算System.out.println("进行自增运算后的值等于"+b);System.out.println("进行自减运算后的值等于"+d);}
}

运行结果为:

进行自增运算后的值等于4
        进行自减运算后的值等于2

解析:
        int b = ++a; 拆分运算过程为: a=a+1=4; b=a=4, 最后结果为b=4,a=4

int d = --c; 拆分运算过程为: c=c-1=2; d=c=2, 最后结果为d=2,c=2

前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算。

后缀自增自减法(a++,a--): 先进行表达式运算,再进行自增或者自减运算

7.2 关系运算符

Java语言支持以下关系运算符。假设变量A的值是10,变量B的值是20,则

注:关系运算符的返回值都是boolean类型。一般结合流程控制语句使用

运算符 描述 例子
== 检查如果两个操作数的值是否相等,如果相等则条件为真。 (A == B)为假。
!= 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 (A> B)为假。
< 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 (A <B)为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 (A> = B)为假。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 (A <= B)为真。

Java关系运算符示例代码:

public class Test {public static void main(String args[]) {int a = 10;int b = 20;System.out.println("a == b = " + (a == b) );System.out.println("a != b = " + (a != b) );System.out.println("a > b = " + (a > b) );System.out.println("a < b = " + (a < b) );System.out.println("b >= a = " + (b >= a) );System.out.println("b <= a = " + (b <= a) );}
}

运行结果为:

a == b = false
a != b = true
a > b = false
a < b = true
b >= a = true
b <= a = false

7.3 按位运算符

Java定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。

位运算符作用在所有的位上,并且按位运算。假设a = 60,b = 13;它们的二进制格式表示将如下:

a = 0011 1100b = 0000 1101// 1.参加运算的两个数据,按照二进制进行按位与的运算。
// 运算规则:0&0=0;   0&1=0;    1&0=0;     1&1=1;
// 即:两位同时为“1”,结果才为“1”,否则为0。
a&b = 0000 1100// 2.参加运算的两个对象,按二进制位进行“或”运算。
// 运算规则:0|0=0;   0|1=1;   1|0=1;    1|1=1;
// 即 :参加运算的两个对象只要有一个为1,其值为1。
a|b = 0011 1101// 3.参加运算的两个数据,按二进制位进行“异或”运算。
// 运算规则:0^0=0;   0^1=1;   1^0=1;   1^1=0;
// 即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为 0。
a^b = 0011 0001~a  = 1100 0011

下表列出了位运算符的基本运算,假设整数变量 A 的值为 60 和变量 B 的值为 13:

操作符 描述 例子
如果相对应位都是1,则结果为1,否则为0 (A&B),得到12,即0000 1100
| 如果相对应位都是 0,则结果为 0,否则为 1 (A | B)得到61,即 0011 1101
^ 如果相对应位值相同,则结果为0,否则为1 (A ^ B)得到49,即 0011 0001
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 (〜A)得到-61,即1100 0011
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。 A << 2得到240,即 1111 0000
>> 按位右移运算符。左操作数按位右移右操作数指定的位数。 A >> 2得到15即 1111
>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 A>>>2得到15即0000 1111

Java按位运算符示例代码:

public class Test {public static void main(String[] args) {int a = 60; /* 60 = 0011 1100 */ int b = 13; /* 13 = 0000 1101 */int c = 0;c = a & b;       /* 12 = 0000 1100 */System.out.println("a & b = " + c );c = a | b;       /* 61 = 0011 1101 */System.out.println("a | b = " + c );c = a ^ b;       /* 49 = 0011 0001 */System.out.println("a ^ b = " + c );c = ~a;          /*-61 = 1100 0011 */System.out.println("~a = " + c );c = a << 2;     /* 240 = 1111 0000 */System.out.println("a << 2 = " + c );c = a >> 2;     /* 15 = 1111 */System.out.println("a >> 2  = " + c );c = a >>> 2;     /* 15 = 0000 1111 */System.out.println("a >>> 2 = " + c );}
} 

运行结果为:

a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2  = 15
a >>> 2 = 15

三种移位符号

>> 是带符号右移,若左操作数是正数,则高位补“0”,若左操作数是负数,则高位补“1”。

<< 将左操作数向左边移动,并且在低位补0。

>>> 是无符号右移,无论左操作数是正数还是负数,在高位都补“0”。

注:如果是对负数移位,则是对补码移位。
    
        三种移位符号作用的左操作数有五种:long,int,short,byte,char。

但是在作用不同的操作数类型时,其具体过程不同, 遵循一下几个原则:
                1、int移位时,左边的操作数是32位的,此时的移位符号作用在32位bit上。如:`1 >> 3`, 是将00000000 00000000 00000000 00000001这32位向右边移动3位。
                2、long 移位时,左边的操作数是64位的,此时移位符号作用在64位bit上。如:`1L >> 3`。
                3、short, byte,char 在移位之前首先将数据转换为int,然后再移位,此时移位符号作用在32为bit上。如:`(byte)0xff >>> 7`, 是将11111111 11111111 11111111 11111111向右边移动7位,得到00000001 11111111 11111111 11111111
    
        有1,2可知,当左操作数是long时,移位之后得到的类型是long,当左操作数是其它四中类型时,移位之后得到的类型是int,所以如果做操作数是byte,char,short 时,你用 `>>=`,`>>>=`, `<<=` 其实是将得到的int 做低位截取得到的数值。

7.4 逻辑运算符

下表列出了逻辑运算符的基本运算,假设布尔变量A为真,变量B为假

操作符 描述 例子
&& 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 (A && B)为假。
| | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 (A | | B)为真。
称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 !(A && B)为真。

Java逻辑运算符示例代码:

public class Test {public static void main(String[] args) {boolean a = true;boolean b = false;System.out.println("a && b = " + (a&&b));System.out.println("a || b = " + (a||b) );System.out.println("!(a && b) = " + !(a && b));}
}

运行结果为:

a && b = false
a || b = true
!(a && b) = true

&&与||的短路问题,&与|也可以用于逻辑运算,但是不存在短路情况。
    
        当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。

Java短路与运算示例代码:

public class Logic{public static void main(String[] args){int a = 5;//定义一个变量;boolean b = (a<4)&&(a++<10);System.out.println("使用短路逻辑运算符的结果为"+b);System.out.println("a的结果为"+a);}
}

运行结果为:

使用短路逻辑运算符的结果为false
        a的结果为5

解析: 该程序使用到了短路逻辑运算符(&&),首先判断 a<4 的结果为 false,则 b 的结果必定是 false,所以不再执行第二个操作 a++<10 的判断,所以 a 的值为 5。

7.5 赋值运算符

下面是Java语言支持的赋值运算符:

操作符 描述 例子
= 简单的赋值运算符,将右操作数的值赋给左侧操作数 C = A + B将把A + B得到的值赋给C
+ = 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 C + = A等价于C = C + A
- = 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 C - = A等价于C = C - A
* = 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 C * = A等价于C = C * A
/ = 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 C / = A,C 与 A 同类型时等价于 C = C / A
(%)= 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 C%= A等价于C = C%A
<< = 左移位赋值运算符 C << = 2等价于C = C << 2
>> = 右移位赋值运算符 C >> = 2等价于C = C >> 2
&= 按位与赋值运算符 C&= 2等价于C = C&2
^ = 按位异或赋值操作符 C ^ = 2等价于C = C ^ 2
| = 按位或赋值操作符 C | = 2等价于C = C | 2

Java赋值运算符示例代码:

public class Test {public static void main(String[] args) {int a = 10;int b = 20;int c = 0;c = a + b;System.out.println("c = a + b = " + c );c += a ;System.out.println("c += a  = " + c );c -= a ;System.out.println("c -= a = " + c );c *= a ;System.out.println("c *= a = " + c );a = 10;c = 15;c /= a ;System.out.println("c /= a = " + c );a = 10;c = 15;c %= a ;System.out.println("c %= a  = " + c );c <<= 2 ;System.out.println("c <<= 2 = " + c );c >>= 2 ;System.out.println("c >>= 2 = " + c );c >>= 2 ;System.out.println("c >>= 2 = " + c );c &= a ;System.out.println("c &= a  = " + c );c ^= a ;System.out.println("c ^= a   = " + c );c |= a ;System.out.println("c |= a   = " + c );}
}

运行结果为:

c = a + b = 30
c += a  = 40
c -= a = 30
c *= a = 300
c /= a = 1
c %= a  = 5
c <<= 2 = 20
c >>= 2 = 5
c >>= 2 = 1
c &= a  = 0
c ^= a   = 10
c |= a   = 10

7.6 其它运算符

Java语言支持的其他运算符很少。

7.6.1 三目运算符 (?:)

三目运算符也称为三元运算符。 此运算符由三个操作数组成,用于计算布尔表达式。 运算符的目标是确定应将哪个值赋给变量。

运算符语法:
                variable x = (expression) ? 表达式1 : 表达式2;
                expression为true,运算后的结果是表达式1;
                expression为true,运算后的结果是表达式2;
                表达式1和表达式2为同种类型
    
        三目运算符与if-else的联系与区别:
                三目运算符可简化if-else语句
                三目运算符要求必须返回一个结果。
                if后的代码块可有多个语句

Java三目运算符示例代码:

public class Test {public static void main(String[] args){int a , b;a = 10;// 如果 a 等于 1 成立,则设置 b 为 20,否则为 30b = (a == 1) ? 20 : 30;System.out.println( "Value of b is : " +  b );// 如果 a 等于 10 成立,则设置 b 为 20,否则为 30b = (a == 10) ? 20 : 30;System.out.println( "Value of b is : " + b );}
}

运行结果为:

Value of b is : 30
Value of b is : 20

7.6.2 instanceof运算符

此运算符仅用于对象引用变量,算符检查对象是否属于特定类型(类类型或接口类型)。 
    
        instanceof运算符语法:
                ( Object reference variable ) instanceof  (class/interface type)

如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。

Java instanceof运算符示例代码:

public class Test {public static void main(String args[]) {String name = "Jimbo";// 当 name 的类型是 String 时,则返回为:trueboolean result = name instanceof String;System.out.println( result );}
}

如果要比较的对象与右侧类型兼容,则此运算符仍将返回true。 以下是另一个例子:

class Vehicle {}public class Car extends Vehicle {public static void main(String[] args){Vehicle a = new Car();boolean result =  a instanceof Car;System.out.println( result);}
}

7.7 运算符的优先级

当多个运算符出现在一个表达式中,谁先谁后呢?这取决于优先级。小括号的优先级是最高的。下表中具有最高优先级的运算符在的表的最上面,最低优先级的在表的底部。

类别 操作符 关联性
后缀 () [] . (点操作符) 左到右
一元 expr++ expr-- 从左到右
一元 ++expr --expr + - ~ ! 从右到左
乘性 * /% 左到右
加性 + - 左到右
移位 >> >>> << 左到右
关系 > >= < <= 左到右
相等 == != 左到右
按位与 左到右
按位异或 ^ 左到右
按位或 | 左到右
逻辑与 && 左到右
逻辑或 | | 左到右
条件 ?: 从右到左
赋值 = + = - = * = / =%= >> = << =&= ^ = | = 从右到左
逗号 左到右

速记:

第一优先级: () [] .

第二优先级: 算数运算符

第三优先级: 关系运算符

第四优先级: 逻辑运算符

第五优先级:赋值运算符

八、课后练习题

8.1 程序题

1、将以下十进制数转换为十六进制和二进制
        // 117 256 89 63 45 22
        十进制数    十六进制    二进制
        117            75        111 0101
        256            100        100000000
        89            59        101 1001
        63            3F        11 1111
        45            2D        10 1101
        22            16        1 0110

2、将以下十六进制数转换为十进制和二进制
        // 0x123 0x25F 0x38 0x62
        十六进制数    十进制        二进制
        0x123        291        1 0010 0011    
        0x25F        607        10 0101 1111
        0x38        56        11 1000
        0x62        98        110 0010

3、下面程序的输出结果

public class SignTest{public static void main(String[] args){int i1 = 10;int i2 = 20;int i = i1++;System.out.print("i="+i);System.out.println(" i1="+i1);i = ++i1;System.out.print("i="+i);System.out.println(" i1="+i1);i = i2--;System.out.print("i="+i);System.out.println(" i2="+i2);i = --i2;System.out.print("i="+i);System.out.println(" i2="+i2);}
}
// 运行结果:
i=10 i1=11
i=12 i1=12
i=20 i2=19
i=18 i2=18

4、随意给出一个整数,打印显示它的个位数,十位数,百位数的值。
        格式如下:
            数字xxx的情况如下:
            个位数:
            十位数:
            百位数:

例如:
            数字153的情况如下:
            个位数:3
            十位数:5
            百位数:1

int num = 153;// 个位
int units = num % 10;
// 十位
int  tens= num / 10 % 10;
// 百位
int hundreds = num / 100;System.out.println(units);
System.out.println(tens);
System.out.println(hundreds);

5、下面程序的输出结果

short s = 3;
// ①和②有什么区别?
s = s+2; // ① 编译错误,计算结果是int类型,无法把int类型直接赋值给short
s += 2; // ② += 不会改变数据类型int i = 1;
i *= 0.1;
System.out.println(i);// 0
i++;
System.out.println(i);// 1int m = 2;
int n = 3;
n *= m++;
System.out.println("m=" + m);
System.out.println("n=" + n);// 运行结果
//m=3
// n=6int n = 10;
n += (n++) + (++n);
System.out.println(n); // 32

6、为抵抗洪水,战士连续作战89小时,编程计算共多少天零多少小时?

int times = 89;
// 获取天数
int days = 89 / 24;
// 获取小时数
int hours = 89 % 24;
System.out.println("共"+days+"天"+hours+"小时");

7、今天是周二,100天以后是周几?

// 今天是周二
int week = 2;
// 一百天以后
week += 100;
// 获取周几
int afterWeek = week % 7;
System.out.println("今天是周二,100天以后是:周"+afterWeek);

8、编写代码实现两个变量值交换,int m = 3, n =5;

int m = 3, n =5;
// 方式一
int temp = m;
m = n;
n = temp;
System.out.println("m="+m+",n="+n);// 方式二
int m1 = 3, n1 = 5;
m1 = m1 + n1;
n1 = m1 - n1;
m1 = m1 - n1;
System.out.println("m1="+m1+",n1="+n1);

9、根据天数(46)计算周数和剩余的天数;

// 天数46
int days = 46;
// 周数
int week = days / 7;
// 剩余天数
int remainDays = days % 7;
System.out.println("46天相当于"+week+"周,剩余"+remainDays+"天");

10、已知圆的半径radius= 1.5,求其面积
        扩展:Math类中已经定义了圆周率值,查找API,了解其用法实现。

// 圆的半径
double radius= 1.5;
// 圆周率 Math.PI// 圆的面积
double area = Math.PI * radius * radius;
System.out.println("圆的面积是:"+area);

8.2 改错题

1、下面程序的错误点?

int age = 19;
char sex = '女';
char result = age + sex;  // 运行结果为int类型,不能直接赋值给char

2、下面哪条语句有错?

int a = 10;
int b = 10.2; // 10.2 是double类型
double c = 10;
c = a;
int d = c; // c是double类型,不能直接赋值给int    

3、检查下面这些是否是合法的标识符?

principal    $lastname   zip code    123rate     discount%
marks_3     city        City        int         cost_price

8.3 简答题

1、什么是关键字和保留字?
        关键字: 被Java语言赋予了特殊含义的单词。
        保留字: 语言已经定义过的字,一些保留字可能没有相对应的语法,考虑到扩展性,为了向后兼容不能再将其作为变量名。
        无论是关键字还是保留字,都不能作为变量名;

2、goto是不是Java关键字?
        goto不是关键字,是Java的保留字;
        注:const和goto是java的保留字。

3、列举常用关键字?
        见上述课件;

4、请简述标识符的概念及命名规则?
        Java 对各种变量、方法和类、接口等要素命名时使用的字符序列称为标识符(在Java里面,所有可以自己起名字的地方都叫标识符)。
    (1)标识符由字母、数字、下划线“_”、美元符“$”组成
    (2)标识符不能以数值开头。
    (3)不可以是Java的关键字/保留字。
    (4)Java 标识符大小写敏感,且长度无限制。
    (5)见名之意。
    (6)驼峰原则:首字母小写,多个单词组成的话,首个单词的首字母小写,之后每个单词的首字母都大写。
                类名/接口首字母大写,如果包含多个单词,每个单词首字母都大写。
                变量/方法首字母小写,如果包含多个单词,之后的每个单词首字母都大写。
    (7)常量全部大写,多个单词组成,则每个单词由_拼接。
    (8)包名全部小写。我们在项目中,包名一律使用这种方式。
                [cn.]com.公司名.项目名.模块名
                com.xxx.cuds.模块名

5、什么是变量和常量?
        在程序运行过程中,可以发生改变的量,就是变量;
                专业说法: 一个数据存储空间的表示;不同数据存入具有不同内存地址的空间,相互独立。
        在程序运行过程中,不允许发生改变的量,就是常量;常量是由final修饰的变量;

6、局部变量、成员变量、静态变量的区别?
        局部变量定义在方法内部或语句块内部; 成员变量定义在方法外部,类内部; 静态变量定义在方法外部,类内部,由static修饰;
        局部变量没有初始值,必须先赋值才能使用; 成员变量和静态变量都由默认的初始值;
        局部变量通过变量名调用; 成员变量通过对象调用; 静态变量既可以通过对象调用,也可以通过类名调用;
        局部变量在栈内存; 成员变量在堆内存; 静态变量在方法区;
        局部变量的生命周期: 与方法共存亡; 成员变量的生命周期: 与对象共存亡; 静态变量的生命周期: 与类共存亡;

7、Java数据类型分类?
        基本数据类型
                整数类型: byte、short、int、long
                浮点类型: float、double
                布尔类型: boolean
                字符类型: char
                注: 整形数据默认为int数据类型,浮点型默认为double数据类型;如果要表示long型数据或float型数据,要在相应的数值后面加上l、L或f、F,否则会出现编译问题。
        引用数据类型
                类类型、接口类型、数组等

8、八种基本数据类型的取值范围?
        取值范围算法: -2^位数次幂-1 ~ 2^位数次幂-1 - 1
        1byte = 8bit
        数据类型    占几个字节       取值范围
        byte        1               -2^7次幂 ~ 2^7次幂 -1       -128 ~ 127
        short       2               -2^15 ~ 2^15 -1     -32,768 ~ 32767
        int         4               -2^31 ~ 2^31 -1
        long        8               -2^63 ~ 2^63 -1
        float       4
        double      8
        char        2               0 ~ 65535
        boolean     1               只有两个值,true和false

9、Java的基本数据类型有哪些? String是不是基本数据类型?
        八种基本数据类型:byte、short、int、long、float、double、boolean、char
        String不是基本数据类型,它是引用类型

10、整型默认的是什么类型,浮点型默认的是什么类型?
        整型默认是int类型
        浮点型默认是double类型

11、计算机里面的数据单位及换算规则?
        bit(位,又名“比特”): bit的缩写是b,是计算机中的最小数据单位(属于二进制的范畴,其实就是0或者1)
        Byte(字节):Byte的缩写是B,是计算机文件大小的基本计算单位
        1Byte(字节)= 8bit(位)
        1 KB = 1024 B
        1 MB = 1024 KB
        1 GB = 1024 MB
        1 TB = 1024GB

12、char类型的变量能存放汉字吗?
        可以,因为java采用unicode编码。

13、float单精度和double双精度的区别?
        float 精度为7~8位
        double 精度是15~16位

14、定义float f=3.4;是否正确?
        不正确,浮点类型的默认类型是double,double比float范围大;
        应该写成 float f = 3.4f;或 float f = (float)3.4;

15、Java数据类型转换?
        自动类型转换: 容量小的类型自动转换为容量大的数据类型。它们的顺序是: byte、short(char)、int、long、float、double
        强制类型转换: 将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(()),但可能造成精度降低或溢出,格外要注意。
        如果一个操作数为 long/float/double 型,则整个表达式提升为 long/float/double 型.

16、计算机中常用的进制?
        进制          范围       前缀
        二进制         0-1         0b
        八进制         0-7         0
        十进制         0-9         \
        十六进制       0-9, A-F     0x

17、进制转换规则?
        二进制、八进制、十进制、十六进制
        基数: X进制的基数是X
        系数: 每一位上面的数值
        权: 每一位上基数的幂(乘方)
        注: 任何数值的0次幂都是1
        二进制和十进制相互转换:
                十进制转二进制: 十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。从最后一个余数为读到第一个;
                二进制转十进制: 二进制转换成十进制,需要二进制的每一位的数值乘以相应的2的幂次方,然后相加。

八进制、十六进制和十进制相互转换:
                十进制转八进制和十六进制: 把十进制转八进制或者十六进制按照除8或者16取余,直到商为0为止。
                八进制和十六进制转十进制: 把八进制、十六进制数按权展开、相加即得十进制数。

二进制与八进制之间的转换:
                间接转换法: 把二进制转换为十进制,在转换为八进制; 把八进制转换为十进制,在转换为二进制;
                二进制转八进制: 3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。
                八进制转成二进制: 八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。

二进制与十六进制之间的转换:
                二进制转十六进制: 与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。
                十六进制转二进制: 十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。

十六进制与八进制之间的转换:
                第一种:他们之间的转换可以先转成二进制然后再相互转换。
                第二种:他们之间的转换可以先转成十进制然后再相互转换。

18、Java是强类型语言还是弱类型语言?
        强类型,声明变量必须指明其类型;

19、什么是原码、反码、补码
        我们经常使用十进制来表示我们的数值;
        机器数: 一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.
        真值: 为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
        原码: 原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码
        反码: 正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
        补码: 正数的补码就是其本身; 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1.

20、为何要使用原码, 反码和补码?
        为了让计算机运算的设计更简单了;
    
21、Java运算符的分类有哪些? 
        算术运算符        + - * / % ++ --
        比较/关系运算符    > >= < <= != ==
        逻辑运算符         && || !  
        赋值运算符        = += -+ *= %= /=
        三目运算符        条件表达式?值1:值2;  如果表达式true,则得到值1,否则值2
        位运算符        & | ^ ~ >> << >>>
        instanceof运算符

22、除法运算的陷阱有哪些?
        两个整数值进行除法运算,得到的肯定是整数值,不会保留小数位;
        0和整数类型进行除法运算,不能作为除数; 0和浮点类型进行除法运算,可以作为除数;
        当两个数的绝对值均为0.0时候,商等于NaN。

23、0可以不可以作为除数?
        0和整数类型进行除法运算,不能作为除数,否则抛出异常; 
        0和浮点类型进行除法运算,可以作为除数,得到无穷大的值;

24、++/--在前和在后的区别?
        ++ 递增运算,在原有值的基础上+1
        -- 递减运算,在原有值的基础上-1
        如果++/--是一行单独的运算,那么在前和在后没有区别;
        如果++/--参与运算或调用,那么在前是先递增/递减运算再调用值,在后是先调用值再递增/递减运算

25、位运算符>> 和 >>>的区别?
        两者都是二进制右移运算符;
        >> 是带符号右移,若左操作数是正数,则高位补“0”,若左操作数是负数,则高位补“1”.
        >>> 是无符号右移,无论左操作数是正数还是负数,在高位都补“0”

26、2 << 2的结果?
        8

27、用最有效的方式计算2乘以8?
        2 << 3;

28、& 和 && 的区别?
        & 按位与运算符,&& 逻辑与运算符;两者都可以进行逻辑与运算;
        & 不具备短路功能;&&具备短路功能,一旦表达式出现了false,则之后的表达式都不再运行;

29、| 和 || 的区别?
        | 按位或运算符,|| 逻辑或运算符;两者都可以进行逻辑或运算;
        | 不具备短路功能,||具备短路功能,一旦表达式出现了true,则之后的表达式都不再运行;

30、short s = 10; s = s + 1的结果是什么? s += 1结果是什么,为什么?
        s = s + 1的结果是报错,short在进行运算的时候,转换成int类型运算,int类型给short类型赋值,需要强转
                s = s + 1写法应该改为 s = (short)(s + 1);
        s += 1正常运行,s = 11;因为+=是Java内置的运算符,它会自动类型转换;

31、instanceof 运算符的作用?
        实例对象 instanceof 类, 判断某个对象是否属于某个类的实例
        Son son = new Son();
        System.out.println(son instanceof Son); // true
        System.out.println(son instanceof Father); // true

【Java基础系列教程】第三章 Java变量与运算符相关推荐

  1. 【Java基础系列教程】第二章 Java语言概述、配置环境变量

    一.计算机编程语言概述 1.1 语言 语言(英文:Language)是人类进行沟通交流的表达方式.例如:中国人与中国人用普通话沟通.而中国人要和英国人交流,就要学习英语.              语 ...

  2. 【Java基础系列教程】第八章 Java面向对象详解(三)_抽象类、接口、内部类、深拷贝与浅拷贝

    一.JavaBean规范 1.1 什么是JavaBean JavaBeans是Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中.特点是可序列化,提供无参构造器,提供getter方法和 ...

  3. 【Java基础系列教程】第一章 编程入门

    一.计算机概述 1.1 计算机简介 计算机(computer)俗称电脑,是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能.是能够按照程序运行,自动.高速处 ...

  4. Java NIO系列教程(十) Java NIO DatagramChannel

    转载自  Java NIO系列教程(十) Java NIO DatagramChannel 译文链接    作者:Jakob Jenkov    译者:郑玉婷     校对:丁一 Java NIO中的 ...

  5. Java NIO系列教程(三) Buffer

    2019独角兽企业重金招聘Python工程师标准>>> Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本 ...

  6. [转载] 夯实Java基础系列8:深入理解Java内部类及其实现原理

    参考链接: Java内部类 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tut ...

  7. 夯实Java基础系列11:深入理解Java中的回调机制

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  8. 夯实Java基础系列14:深入理解Java枚举类

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  9. 夯实Java基础系列18:深入理解Java内部类及其实现原理

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  10. 夯实Java基础系列23:深入理解Java继承、封装、多态的底层实现原理

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

最新文章

  1. textview html字体颜色变粗,安卓使用Html实现textview部分字体变色加粗的效果(使用Html实现多种字体效果)-Go语言中文社区...
  2. 2017年前端面试题整理汇总100题
  3. 用好这 12 款 Chrome 扩展,让你的「新标签页」变得好看又实用
  4. VTK:隐藏线移除用法实战
  5. [转载] Knowledge Management and Enginnering——02 知识表示方法
  6. Kafka是靠什么机制保持高可靠,高可用的?
  7. SAP 电商云 Spartacus UI 里如何捕捉语言设置的更改
  8. selenium通过加载火狐Firefox配置文件FirefoxProfile,实现免登陆访问网站
  9. 3d打印机 form3_桌面SLA卖掉5万台后,Formlabs发布新机型Form3和Form 3L
  10. 注册事件的两种方式(传统注册事件、方法监听注册事件)
  11. 盛大“传奇”的网游启示录
  12. 数据标准详细概述-2022
  13. 海量数据处理技巧-转载
  14. 注册表改win 7更新服务器,uefi安装win7卡在更新注册表设置解决新方法(完美解决)...
  15. 第一次养狗_如何度过艰难的第一个月
  16. Unhandled exception at 0x0133bc63 ....0xC0000005: Access violation reading location 0x00000004.
  17. 2021-2025年中国卡波芬金行业市场供需与战略研究报告
  18. 浪潮发布PS Cloud 开源+云ERP会给中小企业带来哪些红利?
  19. python中 {0:2.2f}与{1:2.2f}的区别
  20. php 统计中英混杂word文档字数,wordfrequencycount

热门文章

  1. AI分析:微信热文有什么特点?兼谈中文分词算法
  2. JAVA 繁体 转 简体 简体转翻译 繁体简体互转
  3. Python数据分析及可视化的基本环境
  4. wsl2 + ubuntu安装下载和一些安装推荐
  5. 抖音+今日头条副业项目,新玩法,后期收益月入过万
  6. 欧标插头EN50075测试项目
  7. 南京邮电大学java实验报告_南京邮电大学java第二次实验报告
  8. 不容错过, Paintinglite轻量级Sqlite3框架
  9. 常用计算机控制芯片有哪些,电脑基本芯片的认识的常用知识介绍
  10. java存储字节_Java字节与字符流永久存储json数据