JAVA程序基础

整理BY:Misayaas

内容来自廖雪峰的官方网站: https://www.liaoxuefeng.com/

变量和数据类型

  • byte是最小储存单位 == 8位二进制数(8个bit) 0-255
  • 一个字节是1byte,1024byte = 1K,1024K = 1M,1024M = 1G,1024G = 1T
  • int4字节,long8字节,float4字节,double8字节,char2字节
  • float类型要加上f,例如==float f1 = 3.14f==
  • 理论上布尔类型只要1bit,但是JVM内部会把boolean表示为4字节整数
  • char用引号且只有一个字符,String用引号(String是引用类型)
  • 引用类型类似于C的指针,指向某个对象在内存的位置

final关键字

修饰的变量会变为常量,常量初始化后不可赋值

var关键字

省略变量类型,例如:

1
StringBuilder sb = new StringBuilder(); 

可以变为
1
var sb = new StringBuilder();

整数运算

  • 整数除法对于除数为0的情况运行会报错,编译不报错
  • byteshort类型进行移位时会先转化为int
  • 如果运算的类型不同,自动转化为大类型
  • 超出范围的强制转型会得到错误的结果

浮点数运算

  • 浮点数在计算机无法精确表示,因此常常出错,只能保存个近似值(二进制
  • 浮点数在除数为0时不会报错,但会返回三个特殊值:NaN表示Not a Number、Infinity表示无穷大、-Infinity表示负无穷大

字符和字符串

字符类型

  • java在内存中使用Unicode表示字符,所以一个英文字符和一个中文字符都占两个字节
  • char类型赋给int类型即可显示Unicode编码
  • 还可以使用转义字符\u+Unicode编码表示一个字符
    1
    2
    3
    // 注意是十六进制:
    char c3 = '\u0041'; // 'A',因为十六进制0041 = 十进制65
    char c4 = '\u4e2d'; // '中',因为十六进制4e2d = 十进制20013

    字符串类型

  • 从java13开始可以用"""..."""表示多行字符串
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Main {
    public static void main(String[] args) {
    String s = """
    SELECT * FROM
    users
    WHERE id > 100
    ORDER BY name DESC
    """;
    System.out.println(s);
    }
    }
    上述多行字符串实际上是5行,在最后一个DESC后面还有一个\n。如果我们不想在字符串末尾加一个\n,就需要这么写:
    1
    2
    3
    4
    5
    String s = """ 
    SELECT * FROM
    users
    WHERE id > 100
    ORDER BY name DESC""";
    还需要注意到,多行字符串前面共同的空格会被去掉,即总是以最短的行首空格为基准。

    不可变特性

  • 只会改变变量的指向,不会改变字符串
  • String[] 类型的对象是可变的,也就是说,可以修改数组中的元素值。
  • 空字符串不等于null

数组类型

数组一旦创建后,大小就不可改变

流程控制

输入输出

占位符 说明
%x 十六进制整数
%e 科学计数法
  • 连续两个%%表示一个%字符本身

有了Scanner对象后,用scanner.nextLine()读取字符串,用scanner.nextInt()读取输入的整数

  • Scanner自动转换数据类型,因此不必手动转换

if判断

==表示“引用是否相等”,或者说,是否指向同一个对象

要判断引用类型的变量内容是否相等,必须使用equals()方法

  • 执行语句s1.equals(s2)时,如果变量s1null,会报NullPointerException
  • 要避免NullPointerException错误,可以利用短路运算符&&
    1
    2
    3
    if (s1 != null && s1.equals("hello")) {
    System.out.println("hello");
    }

switch判断

如果没有匹配到任何case,那么switch语句不会执行任何语句。这时,可以给switch语句加一个default,当没有匹配到任何case时,执行default

case语句并没有花括号{},而且,case语句具有“_穿透性_”,漏写break将导致意想不到的结果

  • 后续语句将全部执行,直到遇到break语句

如果有几个case语句执行的是同一组语句块,可以这么写

1
2
3
4
case 2:
case 3:
System.out.println("Selected 2, 3");
break;

case匹配字符串时,是比较内容相等

数组操作

遍历数组

Arrays.toString()用于快速打印数组内容

数组排序

实际上,Java的标准库已经内置了排序功能,我们只需要调用JDK提供的Arrays.sort()就可以排序

必须注意,对数组排序实际上修改了数组本身

如果对一个字符串数组进行排序,原来的3个字符串在内存中均没有任何变化,但是ns数组的每个元素指向变化了

  • 排序前,这个数组在内存中表示如下:
1
2
3
4
5
6
7
8
9
                   ┌──────────────────────────────────┐
┌───┼──────────────────────┐ │
│ │ ▼ ▼
┌───┬─┴─┬─┴─┬───┬────────┬───┬───────┬───┬──────┬───┐
ns ─────▶│░░░│░░░│░░░│ │"banana"│ │"apple"│ │"pear"│ │
└─┬─┴───┴───┴───┴────────┴───┴───────┴───┴──────┴───┘
│ ▲
└─────────────────┘

  • 调用Arrays.sort(ns);排序后,这个数组在内存中表示如下:
    1
    2
    3
    4
    5
    6
    7
    8
                      ┌──────────────────────────────────┐
    ┌───┼──────────┐ │
    │ │ ▼ ▼
    ┌───┬─┴─┬─┴─┬───┬────────┬───┬───────┬───┬──────┬───┐
    ns ─────▶│░░░│░░░│░░░│ │"banana"│ │"apple"│ │"pear"│ │
    └─┬─┴───┴───┴───┴────────┴───┴───────┴───┴──────┴───┘
    │ ▲
    └──────────────────────────────┘

冒泡排序(从小到大)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Arrays;

public class Main {
public static void main(String[] args) {
int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
// 排序前:
System.out.println(Arrays.toString(ns));
for (int i = 0; i < ns.length - 1; i++) {
for (int j = 0; j < ns.length - i - 1; j++) {
if (ns[j] > ns[j+1]) {
// 交换ns[j]和ns[j+1]:
int tmp = ns[j];
ns[j] = ns[j+1];
ns[j+1] = tmp;
}
}
}
// 排序后:
System.out.println(Arrays.toString(ns));
}
}

二维数组

二维数组的每个数组元素的长度并不要求相同,例如,可以这么定义ns数组:

1
2
3
4
5
int[][] ns = {
{ 1, 2, 3, 4 },
{ 5, 6 },
{ 7, 8, 9 }
};

要打印一个二维数组,可以使用两层嵌套的for循环,或者使用Java标准库的Arrays.deepToString()