1. Java基本语法
2021/10/14 22:14:38
本文主要是介绍1. Java基本语法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录主要来自于《尚硅谷Java教程》
- 变量和运算符
- 关键字和保留字
- 标识符
- 变量
- 数据类型
- 基础数据类型
- 整数类型
- 浮点类型
- 字符类型
- 布尔类型
- String数据类型
- 基础数据类型
- 类型转换
- 自动类型提升
- 强制类型转换
- 进制转换
- 二进制
- 运算符
- 算数运算符
- 取模运算
- 自增/自减运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 位运算符
- 三元运算符
- 算数运算符
- 程序流程控制
- 使用Scanner从键盘获取数据
- 分支结构
- 循环结构
- 带标签的break和continue
- 数组
- 概述
- 一维数组
- 初始化
- 默认初始化值
- 内存结构的简单说明
- 初始化
- 多维数组
- 二维数组
- 默认初始化值
- 二维数组
- 常见算法
- 随机生成一个两位数
- 数组的反转
- 二分查找
- 排序算法
- 冒泡排序
- 快速排序
- Arrays工具类的使用
变量和运算符
关键字和保留字
-
关键字(keyword)是被Java赋予了特殊含义、用作特殊用途的字符串,全部为小写,如定义数据类型的
class
,boolean
和用于定义流程控制的switch
,while
等。 -
保留字(reserved word)在现有Java版本尚未使用,但以后版本可能会作为关键字使用,需要在命名标识符时避免使用,包括:
goto
,const
。
标识符
标识符(identifier)是对变量、方法和类等命名时使用的字符序列。
-
由26个英文字母、0-9、
_
或$
组成。 -
严格区分大小写。
-
不能以数字开头、不能包含空格。
命名规范:
- 包名:多单词的所有字母都小写,
helloworldtest
。 - 类名、接口名:所有单词首字母大写,
HelloWorldTest
。 - 变量名、方法名:第一个单词首字母小写,其余单词首字母大写,
helloWorldTest
。 - 常量名:所有字母大写,多单词时用下划线连接,
HELLO_WORLD_TEST
。
变量
变量用于在内存中保存数据,概念:
- 内存中的一个存储区域。
- 该区域的数据可以在同一类型范围内不断变化,Java属于强类型语言。
- 变量是程序中最基本的数据单元,包含变量类型、变量名和储存的值。
需要注意:
- 变量的作用域:其定义所在的一对{}内。
数据类型
按照数据类型可以分为:
- 基本数据类型(primitive type):整数(
byte
,short
,int
,long
)、浮点(float
,double
)、字符(char
)、布尔(boolean
)。 - 引用数据类型(reference type):类(
class
)、接口(interface
)、数组([]
)。
按照声明位置的不同可以分为:
- 成员变量:在方法体外,类体内声明的变量,分为实例变量与类变量(以
static
修饰)。 - 局部变量:在方法体内部声明的变量,包括形参(方法、构造器中的变量)、方法局部变量(在方法内定义)、代码块局部变量(在代码块定义)。
具体内容参考面向对象。
基础数据类型
整数类型
类型 | 占用空间 | 范围 |
---|---|---|
byte |
1 byte = 8 bit | \(-128\) ~ \(127\) |
short |
2 bytes | \(-2^{15}\) ~ \(2^{15}-1\) |
int |
4 bytes | \(-2^{31}\) ~ \(2^{31}-1\) |
long |
8 bytes | \(-2^{63}\) ~ \(2^{63}-1\) |
主要注意,Java各个整数类型有固定的字段长度和表达范围,不受OS影响,以保证可移植性。
- Java的整数类型默认为
int
。 - 声明
long
类型时,如果数字大小超过int
的范围,数字后须加l
或者L
,这是因为Java默认把数字当成int
类型来处理。
浮点类型
类型 | 占用空间 | 范围 |
---|---|---|
单精度float |
4 bytes | \(-3.403\times 10^{38}\) ~ \(3.403\times 10^{38}\) |
双精度double |
8 bytes | \(-1.798\times 10^{308}\) ~ \(1.798\times 10^{308}\) |
Java的浮点类型常量默认为double
,声明float
类型,需要加f
或F
。浮点型常量有两种表现形式:
- 十进制:如5.12, 512.0f, .512。
- 科学计数法:5.12e2, 512E2, 100E-2。
字符类型
char
类型用来表示通常意义上的字符,占用2 bytes。
- Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母或一个汉字。
- 可以直接用Unicode编码来表示字符常量:
\u000a
表示\n
,其中000a
为十六进制整数。 char
类型可以运算,因为它有对应的Unicode码。
布尔类型
boolean
只能取ture
和false
。
String数据类型
String
属于引用数据类型,声明时使用一对""
。
String
类型可以和8种基本数据类型变量做运算,且只能是连接运算+
,运算的结果仍然是String
。
不能通过强制类型转换将String
转换为其他基本数据类型。
String str1 = 123 + ""; // int num1 = (int) str1; // 编译不通过 int num1 = Integer.parseInt(str1); // 123
字符串连接:
char c = 'a'; int num = 10; String str = "hello"; System.out.println(c + num + str); // output: 107hello System.out.println(c + str + num); // output: ahello10 System.out.println(c + (num + str)); // output: a10hello System.out.println(str + num + c); // output: hello10a
类型转换
只讨论7种基本数据类型变量间的运算,不包含boolean
。
自动类型提升
- 当容量小的数据类型变量转换为容量大的数据类型的变量时,结果自动提升为容量大的数据类型。
- 顺序表示为:
byte
/short
/char
<int
<long
<float
<double
,这里的容量指表示数据范围的大小而不是占用空间的大小,例如:long
占用8个字节,float
占用4个字节,但是float
的表示范围比long
更大。
short s1 = 123; double b1 = s1; System.out.println(d1); // output: 123.0
- 特别地,当
byte
/short
/char
这3种类型做运算时,结果为int
型,包括相同种类(如2个byte
变量相加)。
byte b1 = 1; short s1 = 10; // short s3 = b1 + s1; // 编译不通过 int i1 = b1 + s1;
强制类型转换
将容量大的数据类型变量强制赋值给容量小的数据变量,可能会导致精度损失。
// 没有精度损失 long l1 = 123; short s1 = (short) l1; // 123 // 精度损失,截断 double d1 = 12.9; int i1 = (int) d1; // 12 // 精度损失,溢出 int i2 = 128; byte b = (byte) i2; // -128
进制转换
对于整数类型,有4种表达方式:
- 二进制(binary):以
0b
或0B
开头。 - 十进制(decimal):0-9。
- 八进制(octal):0-7,以
0
开头。 - 十六进制(hex):以
0x
或0X
开头,A-F不区分大小写,0x21af + 1 == 0x21b0
。
二进制
Java整数常量默认是int
类型,当用二进制定义整数时,第32位是符号位。正数的原码、补码、反码相同,负数的补码为其反码+1。 计算机底层都以补码的方式存储数据。
- 原码:直接将一个数值转换为二进制,最高位为符号位。
- 负数的反码:符号位为1,其余对原码按位取反。
- 负数的补码:其反码+1。
运算符
算数运算符
取模运算
结果的符号与被模数相同。
int m1 = 12; int n1 = 5; System.out.println(m1 % n1); // 2 int m2 = -12; int n2 = 5; System.out.println(m2 % n2); // -2 int m3 = 12; int n3 = -5; System.out.println(m3 % n3); // 2 int m4 = -12; int n4 = -5; System.out.println(m4 % n4); // -2
自增/自减运算符
自增/自减运算符不会改变变量的数据类型。
short s1 = 100; s1 -= 1; s1--; // s1 = s1 - 1; // 编译失败,需要强制类型转换 System.out.println(s1); // 98
赋值运算符
与自增运算符类似,+=
, -=
, *=
, /=
等赋值运算符不会改变数据类型。
比较运算符
比较运算符的结果都是boolean
类型,包括==
, !=
, <
, >
, <=
, >=
, instanceof
,其中instanceof
用来检查是否是类的对象,用法如下:
System.out.println("Hello" instanceof String); // ture
逻辑运算符
运算符 | 含义 |
---|---|
& |
逻辑与 |
&& |
短路与 |
| |
逻辑或 |
|| |
短路或 |
! |
逻辑非 |
^ |
逻辑异或 |
位运算符
注意,没有<<<
运算符。
运算符 | 含义 | 示例 |
---|---|---|
<< |
左移 | 3 << 2 => 12 |
>> |
右移 | 3 >> 1 => 1 |
>>> |
无符号右移 | 3 >>> 1 => 1 |
& |
与运算 | 6 & 3 => 2 |
| |
或运算 | 6 | 3 => 7 |
^ |
异或运算 | 6 ^ 3 => 5 |
~ |
取反运算 | ~6 => -7 |
- 位运算符操作的都是整数类型的数据。
<<
:空位补0,被移除的高位丢弃,在一定范围内,每向左移动1位,相当于* 2
。>>
:正数右移后空缺位补0,负数补1,在一定范围内,每向右移动1位,相当于/ 2
。>>>
:最高位无论是1还是0,右移空缺位都补0。~
:按照补码,各位取反。
2 << 3
和 8 << 1
的复杂度是\(O(1)\),比2 * 8
效率更高。
三元运算符
结构:(条件表达式) ? 表达式1 : 表达式2
。
- 三元表达式可以改写为
if-else
语句,反之则不一定,参见下一条。 表达式1
和表达式2
要求是一致的,例如(m > n) ? 2 : "n is bigger"
编译不通过。
程序流程控制
使用Scanner从键盘获取数据
- 导包:
import java.util.Scanner;
- 实例化
Scanner
类。 - 调用
next()
等方法读取数据。
import java.util.Scanner; public class HelloWorld{ public static void main(String[] args){ Scanner scan = new Scanner(System.in); int num = scan.nextInt(); String str = scan.next(); System.out.println(num + str); } }
分支结构
除了if-else
结构外,有关switch-case
结构需要注意:
switch
中的表达式只能是这6种数据类型之一:byte
、short
、char
、int
、枚举(JDK5.0新增)、String
(JDK7.0新增)。case
之后只能声明常量,不能声明范围。default
结构是可选的,而且位置灵活。
另外switch-case
结构比if-else
结构效率稍高。
循环结构
带标签的break和continue
label: for(int i = 1; i <= 4; i++){ for(int j = 1; j <= 10; j++){ System.out.println(j); if (j % 4 == 0){ // continue; // 结束包裹此关键字最近的一层循环结构 continue label; // 结束指定标签的一层循环结构 } } }
数组
概述
数组(array)是多个相同类型数据按一定顺序排列的集合。
- 有序排列。
- 数组属于引用数据类型的变量。
- 创建数组对象会在内存中开辟一整块连续的空间。
- 数组的长度一旦确定就不能修改。
- 分类:按照维度分为一维数组和多维数组;按照数据类型分为基本数据类型元素的数组和引用数据类型元素的数组。
一维数组
初始化
数组一旦初始化完成,其长度就确定了。
// 静态初始化:数组的初始化和数组元素的赋值操作同时进行 int[] ids = new int[] {1001, 1002, 1003, 1004}; // 动态初始化:数组的初始化和元素赋值分开进行 String[] names = new String[5]; names[0] = "Wang"; // 获取数组长度 System.out.println(ids.length + " " + names.length);
默认初始化值
- 整型:0
- 浮点型:0.0
char
型:0或\u0000
,而非'0'
boolean
型:false
- 引用数据类型:
null
内存结构的简单说明
JVM中的内存结构简单分为:
- 栈(stack):局部变量,如上面代码中的变量
ids
和names
(仅存放数组的地址)。 - 堆(heap):
new
出来的对象、数组等,如上述代码中ids
和names
对应数组开辟的连续空间。 - 方法区:常量池、静态域等。
多维数组
二维数组
初始化方法如下:
// 静态初始化:数组的初始化和数组元素的赋值操作同时进行 int[][] arr1 = new int[][] {{1, 2, 3}, {4, 5}, {6}}; // 动态初始化:数组的初始化和元素赋值分开进行 String[][] arr2 = new String[5][3]; String[][] arr3 = new String[6][]; // 也是正确的写法 int[][] arr4 = {{1, 2, 3}, {4, 5}, {6}}; // 类型推断 int arr5[][] = new int[][] {{1, 2, 3}, {4, 5}, {6}};
默认初始化值
针对动态初始化方法一,例如int[][] arr = new int[3][4];
,则初始化值为
- 外层元素:地址值。
- 内层元素:与一维数组相同。
int[][] arr = new int[3][4]; System.out.println(arr[0]); // 地址值:[I@28d93b30 System.out.println(arr[0][0]); // 0
针对动态初始化方法二,例如int[][] arr = new int[3][];
,则初始化值为
- 外层元素:
null
。 - 内层元素:不能调用,否则报错。
常见算法
随机生成一个两位数
(int) (Math.random() * (99 - 10 + 1) + 10); /* * Math.random() => [0.0, 1.0) * Math.random() * 90 => [0.0, 90.0) * (int) (Math.random() * 90) => [0, 89] * (int) (Math.random() * 90 + 10) => [10, 99] */
数组的反转
在空间复杂度为常数级的情况下,反转数组。主要思想为交换头尾元素。
// 随机生成20个两位数 int[] arr = new int[20]; for(int i = 0; i < arr.length; i++){ arr[i] = (int) (Math.random() * 90 + 10); System.out.print(arr[i] + " "); } System.out.println(); // reverse 1 /* for (int i = 0; i < arr.length / 2; i++){ int temp = arr[i]; arr[i] = arr[arr.length - 1 - i]; arr[arr.length - 1 - i] = temp; } */ // reverse 2: 双指针交换,实际操作上与方法一相同 for (int i = 0, j = arr.length - 1; i < j; i++, j--){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
二分查找
// 二分查找(必须是有序的) int [] arr2 = new int[] {-98, -34, 2, 34, 54, 66, 79, 105, 210, 333}; int head = 0; // 初始前索引 int end = arr2.length - 1; // 初始后索引 boolean isFound = false; // 是否被找到 int target = 210; // 查找的目标值 while (head < end){ int middle = (head + end) / 2; if (target == arr2[middle]){ System.out.println("Find " + target + ", index = " + middle + "."); isFound = true; break; } else if (target < arr2[middle]){ end = middle - 1; } else { head = middle + 1; } } if (!isFound){ System.out.println("Can't find " + target + "."); }
排序算法
衡量排序算法:
- 时间复杂度:关键字比较次数和记录的移动次数。
- 空间复杂度:算法需要多少辅助内存。
- 稳定性:若两个记录A和B的关键字值相等,排序后A、B的先后次序保持不变,则称算法是稳定的。
冒泡排序
for (int i = 0; i < arr.length - 1; i++){ for (int j = 0; j < arr.length - 1 - i; j++){ if (arr[j] > arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
快速排序
public class QuickSort { // 交换数组的两个索引上的值 private static void swap(int[] data, int i, int j){ int temp = data[i]; data[i] = data[j]; data[j] = temp; } // 子方法 private static void subSort(int[] data, int start, int end){ if (start < end){ int base = data[start]; int low = start; int high = end + 1; while (true){ // 通过两个while循环,向右移动low,向左移动high // 直到找到大于base的low和小于base的high while (low < end && data[++low] <= base); while (high > start && data[--high] >= base); // low和high没有碰面,需要交换,循环继续 if (low < high){ swap(data, low, high); } else { break; } } // 将base移到中间,base左边全部是比它小的数字,右边全部是比它大的数字 swap(data, start, high); // 递归地对base左半部分和右半部分排序 subSort(data, start, high - 1); subSort(data, high + 1, end); } } // 快速排序 public static void quickSort(int[] data){ subSort(data, 0, data.length - 1); } }
Arrays工具类的使用
java.util.Arrays
是操作数组的工具类,里面定义了很多操作数组的方法。
// 1. 判断两个数组是否相等 int[] arr1 = new int[] {1, 2, 3, 4, 5}; int[] arr2 = new int[] {1, 2, 3, 4, 5}; System.out.println(Arrays.equals(arr1, arr2)); // true // 2. 输出数组 System.out.println(Arrays.toString(arr1)); // [1, 2, 3, 4, 5] // 3. 将数组填充为指定值 Arrays.fill(arr1, 10); System.out.println(Arrays.toString(arr1)); // [10, 10, 10, 10, 10] // 4. 对数组排序 int [] arr3 = new int[] {98, 34, 2, 34, 54, -66, -79, 105, -210, 333}; Arrays.sort(arr3); System.out.println(Arrays.toString(arr3)); // [-210, -79, -66, 2, 34, 34, 54, 98, 105, 333] // 5. 二分查找 System.out.println(Arrays.binarySearch(arr3, 105)); // 如果找到,输出索引 System.out.println(Arrays.binarySearch(arr3, -2)); // 负数表示没找到 // 8 // -4
这篇关于1. Java基本语法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-27消息中间件底层原理资料详解
- 2024-11-27RocketMQ底层原理资料详解:新手入门教程
- 2024-11-27MQ底层原理资料详解:新手入门教程
- 2024-11-27MQ项目开发资料入门教程
- 2024-11-27RocketMQ源码资料详解:新手入门教程
- 2024-11-27本地多文件上传简易教程
- 2024-11-26消息中间件源码剖析教程
- 2024-11-26JAVA语音识别项目资料的收集与应用
- 2024-11-26Java语音识别项目资料:入门级教程与实战指南
- 2024-11-26SpringAI:Java 开发的智能新利器