Java 学习笔记

发布时间 2023-10-04 14:58:18作者: lcgogo

dos 环境下(Windows 即 cmd)的 Java 命令

  1. 先用javac 文件名.java;命令,编译 java 文件,生成一个后缀为 class、名与类名相同的文件。
  2. 再用java 类名命令,执行文件。

注释

当类名前的修饰符为 public 时,类名必须和源文件名一致。并且以上操作不能执行带 package 的 java 文件。
和 C 语言一样。
//:单行注释。
/**/:多行注释。
编译后生成的 class 文件里没有注释里的内容,即写再多的注释,class 文件的大小也不会变。
/** *...*/:文档注释,用javadoc -encoding UTF-8 -d mydir -version -author HelloWorld.java命令后,会生成一个类似 API 文档的网页,注释里的内容会成为网页的一部分。
javadoc 和 java 文件间的内容都是命令行参数。


注意文档注释写的位置,有些在类外,有些在类里面。

输出

System.out.println():输出数据之后,会换行。

当括号里不填内容时,相当于换行操作,等价于System.out.print("\n")
System.out.print():输出数据后,不换行。

pubilc 修饰符

同一源文件中可定义多个类,每个类都会生成一个 class 文件(字节码文件),且 class 文件名与类名相同。
public 修饰的类在每个源文件中最多一个,且类名必须与源文件名相同。

包(package)

​ 包(类似于文件夹,用于管理class文件)的命名采用域名倒置的规则;

标识符

命名规则

​ 标识符可以包含字母,数字,_,$,但是不能以数字开头,不能包含空格;

命名习惯

包名

多单词组成时所有字母都小写
例如:java.lang、com.atguigu.bean 等。

类名、接口名

多单词组成时,所有单词的首字母大写
例如:HelloWorld、String、System 等。

变量名、方法名

多单词组成时,第一个单词首字母小写,第二个单词开始每个单
词首字母大写
例如:age、name、bookName、main、binarySearch、getName 等。

在同一作用域下,不能声明 2 个同名的变量。

常量名

所有字母都大写。多单词时每个单词用下划线连接。
例如:MAX_VALUE、PI、DEFAULT_CAPACITY 等。

基本数据类型

整型

Java 各整数类型有固定的表数范围和字段长度,不受具体操作系统的影响,以保证 Java 程序的可移植性。

类型 占用存储空间 表示范围
byte 1 字节 -128 ~ 127
short 2 字节 -215 ~ 215-1
int 4 字节 -231 ~ 231-1(约21.4亿)
long 8 字节 -263 ~ 263-1

定义 long 类型的变量,赋值时需要以"l"或"L"作为后缀。

开发过程中,整型变量通常声明为 int 型。

整型常量默认为 int。

浮点型

浮点型有固定的表数范围和字段长度,不受具体操作系统的影响。

类型 占用存储空间
float 4 字节
double 8 字节

定义 float 类型的变量,赋值时需要以"f"或"F"作为后缀。

float、double 的数据不适合在不容许舍入误差的金融计算领域。如果需要精确数字计算或保留指定位数的精度,需要使用 BigDecimal 类

字符型

char 占 2 个字节。值用单引号('')括起来,例子:char a = 'a';char b = '中';char 和 int 、char 和 char 做运算会变为 int。

布尔型

boolean 类型数据只有两个值:true、false,无其它

不可以使用 0 或非 0 的整数替代 false 和 true,这点和 C 语言不同,布尔型不能和其他基本数据类型做运算。

类型转换

自动类型转换

byte ,short,char ==> int ==> long ==> float ==> double

表示范围小的可以转变为表示范围大的,而不是看占用存储空间大小。float 能表示的数比 long 还大。

注:byte 和 byte 运算、byte 和 short 运算、short 和 short 运算,结果需要用 int 存储。

byte a = 10;
byte b = a + 12; 
//会报错,算式里的整数常量 12 默认是 int ,需要用 int 变量接收
//浮点数同理,而浮点数常量默认为 double。

强制类型转换

和 C 语言类似,但 String 类型不能通过强制类型()转换为其他的类型,因为 String 不是基本数据类型。

引用数据类型

字符串

String 和基本数据类型(包括布尔型)可以用“+”拼接。

String a = "abc";
System.out.println(a+1); //结果是abc1,类型为字符串

进制

二进制

0b0B开头。

 int a = 0b110;//或者0B110
 System.out.println(a); //输出为:6,以10进制输出

十进制

0x0X开头,a-f不区分大小写。

 int a = 0x110;//或者0X110
 System.out.println(a); //输出为:272

计算机数据的存储使用二进制补码形式存储,并且最高位是符号位。

  • 正数:最高位是 0
  • 负数:最高位是 1
    正数的补码与反码、原码一样,称为三码合一
    负数的补码与反码、原码不一样:
  • 负数的原码:把十进制转为二进制,然后最高位设置为 1。
  • 负数的反码:在原码的基础上,最高位不变,其余位取反(0 变 1,1 变0)。
  • 负数的补码:反码加 1

最快方法是:除符号位、最后个 1 及以后的位不变,其余位全取反。

补码转原码:最高位不变,其余位取反再加 1,因此也可以使用最快方法

运算

运算符的细微差异

java 中的 % 是取余,商向 0 靠近。

System.out.print(-5%2); //本身商为 -2.5,但是向0取整则为 -2,余数为 -1
System.out.print(-5/2); //本身商为 -2.5,但是向0取整则为 -2,    

python中 % 为取模,商向负无穷靠近。

print(5//2) #地板除,得 2.
print(5/2) #得2.5
print(-5%2) #本身商为 -2.5,但是向负无穷取整得 -3,取模为 1,-5 = 2*(-3) + 1

a+=2;a= a+2;的细微差别,a+=2; int b =1000; a+=b;中 a 的类型不会改变,比如 a 的类型为 byte,则运算完也为 byte,只是把高位抛弃,只看地位对应哪个值, -=、*=、 /=、%= ++具有相同的性质。

short s1 = 10;
s1 += 2; //因为在得到 int 类型的结果后,JVM 自动会进行强制类型转换,将 int 类型强转成 short
s1++;

比较运算符

  1. 比较运算符的结果都是 boolean 型,也就是要么是 true,要么是 false。
  2. > < >= <= :只适用于基本数据类型(除 boolean 类型之外)。
  3. == != :适用于基本数据类型和引用数据类型。

逻辑运算符

& &&:表示“且”。
| || :表示“或”。

a&ba&&b的区别在于 a 为 false 时,&仍会判断b,从而执行b中的表达式,比如age++;而&&会短路,不再判断 b。|||同理,推荐使用&&||
^:表示”异或“。
!:表示“非”。

位运算符

a<<n:左移 n 位,低位补0。在一定范围内,相当于乘 2n(正负数都是),这里也涉及到自动类型转换(byte、short 移位后会变为int)。

有可能会移成负数,把数值的 1 移到符号位。是移位时,移的是补码。当左移的位数 n 超过该数据类型的总位数时,相当于左移(n % 总位数)位。
a>>n:右移 n 位,高位补与符号位相同的值。在一定范围内,相当于除 2n,然后向下取整(正负数都是),这里也涉及到自动类型转换(byte、short 移位后会变为int)。
a>>>n::右移 n 位,高位补 0。(正数、负数都适用),这里也涉及到自动类型转换(byte、short 移位后会变为int)。
负数会变成正数。
a&b、a|b、a^b、~a:都是用二进制补码运算,运算时也包括了符号位。

条件运算符

c = 条件表达式 ? A : B;表达式为true执行 c = A,表达式为false执行 c = B。也可以syetem.out.println(条件表达式 ? "我是A" : "我是B");

switch-case

写法和 C 语言一样,case 子句中的值必须是常量,不能是变量名或不确定的表达式值或范围。

break 和 continue

break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块,continue 类似。

label1: for(...){ //for1
    label2:for(...){ //for2
        label3:for(...){ //for3
            break label2; //跳出紧跟 label2 的这个循环,即for2,再执行for1。
        }
	}
}

continue 结束此次循环,然后再次进入所属循环语句的下轮循环。 若上面 break 换成 continue,则是跳出 for2,再进入 for2。

标签语句只能用在循环的头部

Scanner

步骤:

  1. 导包:import java.util.Scanner;
  2. 创建 Scanner 对象:Scanner scan = new Scanner(System.in);
  3. next() / nextXxx(),来获取指定类型的变量,如nextInt() 获取一个 Int 型整数,nextDouble() 获取一个 Double 型浮点数。
    • next()nextLine()都是读取字符串的方法。
    • 使用nextLine(),空格不作为两个字符串的间隔,而是看作字符串的一部分;并且使用后光标会到下一行
    • 使用next()nextInt(),遇到空格时会停止读取,返回的结果为空格前读取到的部分,光标仍在本行。
    • 这里涉及到一个nextInt()、next()、nextDouble()等与nextLine()的问题,先nextInt(),光标在本行,nextLine()可能会读到空字符串或者脏数据(带空格),解决办法:在nextInt()后,先调用nextLine()把脏数据读走,将光标移到下一行,再用nextLine()读取需要的数据,也就是使用 2 次nextLine()
  4. 释放资源:scan.close();

Math.random()

Math.random()会返回范围在 [0,1) 的 double 浮点数。
获取 [a,b] 范围内的随机整数(int)(Math.random() * (b - a + 1))+a,取整使得范围从 [a,b+1) 变成[a,b]。

包(package)

在 IDEA 中,一个 Project 可以有多个 module,一个module 下可以有多个 package,一个 package 下可以有多个 class。
实际上就是把不同功能的 class 放到不同的文件夹下,package 的命名采用域名倒置的规则,比如 www.lc.com下的包可以写成 com.lc.包名

数组

数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。

声明数组

类型[] 数组名;,例如int[] arr;

Java 中声明数组时,不能指定长度。

未初始化的数组不能直接使用。

初始化

  • 静态初始化

    初始化的同时赋初值。

    • 写法 1:int[] arr = new int[]{1,2,3,4,5};
    • 写法 2:int[] arr = {1,2,3,4,5};,这种不能写成int[] arr; arr = {1,2,3,4,5};,因为编译器识别出不来。
  • 动态初始化
    • int[] arr = new int[5];,[] 中指定数组长度,但不赋初值。

      指定长度后,无法修改长度。arr.length 可以得到数组 arr 的长度。

      当使用动态初始化创建数组时,元素值是默认值。

一维数组内存存储

public static void main(String[] args) {
 	int[] arr = new int[3];
 	 System.out.println(arr);
}

只有在 new 数组对象时,才会在堆中分配。声明数组只会在栈中分配。