java基础
java语言细分
- java SE:java平台标准版
- java EE:java平台企业版(用于构建企业级应用)
- java ME:java平台微型版
语言特点
- 跨平台性(安装JVM,由JVM来负责Java程序在该系统中的运行)
- 面向对象
- 分布式
- 稳健安全性(健壮性)
- 动态性
- 高性能
- 多线程
- 可移植
- 易学
常用的****DOS命令
- dir : 列出当前目录下的文件以及文件夹
- md : 创建目录
- rd : 删除目录
- cd . : 进入指定目录
- cd … : 退回到上一级目录
- cd\: 退回到根目录
- del : 删除文件
- exit : 退出 dos 命令行
编译与执行
- 源文件——>编译器(生成字节码文件.class)——>解释器——>机器语言
JDK,JRE,JVM之间的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V1sghqdj-1669561346492)(F:\传一\一阶段理论\笔记\assets\image-20221122235025114.png)]
两大核心机制
-
JVM:是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指
令,管理数据、内存、寄存器。
-
垃圾收集机制:提供一种系统级线程跟踪存储空间的分配情况。并在JVM空闲时,检查并释放那些可被释放的存储空间。
JDK目录结构
- \bin:java开发工具包,包括Java编译器,解释器等
- \demo:一些实例程序
- \lib:Java开发类库
- \jre:Java运行环境,包括Java虚拟机,运行类库等
- \src:jdk系统类库源代码
一个简单的java应用程序
public class Hello_world{
public static void main(String[] args){
System.out.println("Hello World")
}
}
注:
- 关键字public称为访问修饰符, main方法必须声明为public.
- java区分大小写,如果出现了大小写拼写错误,程序将无法运行.
- 类名常使用"骆驼命名法"命名
- 类名要与文件名相同,运行时不要加 .class扩展名
进制
进制书写
-
十进制:不需要加任何修饰
System.out.println(10)
-
二进制:前面加0b
System.out.println(0b10) ##2 表示10为二进制下的
-
八进制:0开头
System.out.println(010) ##8 表示10为八进制下的
-
十六进制:0x开头
System.out.println(0x10) ##16 表示10为十六进制下的
-
判断:观察前缀
注释
- 最常用的方式://
- 使用**/*** 和 */ 注释界定符将一段比较长的注释括起来
- 使用**/**** 和 ***/**来自动生成文档
- 注: /* */注释不能嵌套
数据类型
java是强类型语言,对于每一种数据都给出明确的数据类型,可分为基本数据类型和引用数据类型
整数
类型 | 存储需求 | 取值范围 |
---|---|---|
int(默认) | 4字节 | -刚刚超过20亿 |
short | 2字节 | -32768 ~ 32767 |
long | 8字节 | -9223372036854775808 ~9223372036854775807 |
byte | 1字节 | -128 ~ 127 |
浮点类型
类型 | 存储需求 | 取值范围 |
---|---|---|
float | 4字节 | 有效位数为6 ~ 7位 |
double(默认) | 8字节 | 大约有效位数为15位 |
char
-
转义字符
转义序列 名称 Unicode值 \b 退格 \u0008 \t 制表 \u0009 \n 换行 \u000a \r 回车 \u000d \" 双引号 \u0022 \’ 单引号 \u0027 \\ 反斜杠 \u005c
boolean
- 布尔类型有两个值:true 和 false
变量与常量
变量
变量就是内存中的一个存储空间,空间中存储着的经常发生改变的值
-
格式: 数据类型 变量名 = 数据值;
-
注意:
- 不能重复定义同名变量
- 在变量使用之前,必须赋值
- 变量的作用范围:只能在当前的大括号中有效
- 定义float类型的变量,在数值后面要加一个后缀F
- 定义long类型的变量,在数值后面要加一个后缀L
标识符
-
数字,字母,下划线,美元$组成
-
不能以数字开头
-
不能是关键字
-
区分大小写
**注:**建议使用小驼峰命名法
常量
- 在Java中,利用关键字 final 指示常量,且只能被赋值一次
- 常量一旦被赋值,就不能再更改
- 类常量的定义常在main方法的外部。如果一个常量被声明为public,那么其他类的方法也可以使用这个常量
注:单下划线 _ 不能作为变量名
运算符
算数运算符
符号 | 名称 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
数学函数与常量
Math类中,包含了各种各样的数学函数
函数 | 名称 |
---|---|
sqrt | 平方根 |
pow | 幂运算 |
sin | 正弦 |
cos | 余弦 |
exp | 指数函数 |
log | 对数 |
PI | π |
E | e |
数据类型转换
- 合法转换:小的转大的
- 隐式转换(核心:把小的转大的)
- 直接转换
- 小的直接转为大的
- 不同的数据类型参与计算
- 晓得数据类型和大的数据类型参与运算,会提升为大的那个
- 值比int小的,不管有没有其他类型,都转化为int类型,
- 直接转换
- 强制类型转换(核心:把大的转小的)
- 格式:(变量类型) 变量
- 强制转换可能丢失一些信息,若超过范围,则结果出错。
- 如果想对浮点数进行舍入运算,可以使用Math.round()方法
- 整数常量优化机制
- 触发时机:等号的右边全部都是整数参与计算时,
- 字符参与运算(查询对应的ASCII码表进行运算)
- 字符赋值给整数类型的变量
- 字符参与了运算
结合赋值和运算符
- 可以在赋值中使用二元运算符:+= , -= ,*= ,%= ,/=
关系和boolean运算符
- 返回值为True或false:== , !=
- 三元运算符:条件 ? 表达式1 :表达式2
x<y ? x : y #符合返回x,不符合返回y
位运算符
符号 | 描述 |
---|---|
&& | 与 |
|| | 或 |
^ | 非 |
~ | 不 |
>> | 右移 |
<< | 左移 |
字符串
java字符串就是Unicode字符序列。在标准java类库中提供了一个预定义类,叫 String
子串
- String类的substring方法可以从一个较大的字符串提取出一个子串
String greeting = "Hello";
String s = greeting.substing(0,3);
//创建一个由字符“Hell”组成的字符串。
拼接
- java语言允许使用 + 号连接(拼接)两个字符串.
String a1 = "Hello";
String a2 = "Marry";
String s = a1 + a2; //"HelloMarry"
- 如果需要把多个字符串放在一起,用一个界定符分隔,可以使用静态方法join方法:
String all= String.join("/","S","M","L","XL");
//all = "S/M/L/XL"
不可变类型
- java中的String类成为不可变的
- 优点: 编译器可以让字符串共享
- 可以提取想保留的子串,在于希望替换的字符拼接
String greeting = "Hello";
greeting = greeting.substring(0,3 + "p!"); //"help"
检测字符串是否相等
- 可以使用equals方法检测两个字符串是否相等, 如果相等, 则返回true,否则返回false ( eg : s.equals ( t ) )
- 要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase
"Hello".equalsIgnoreCase("Hello");
注 : 不要使用 == 运算符检测连个字符是否相等, 因为实际上只有字符串字面量是共享的,而 + 或 substring等操作得到的字符串并不共享.
空串与Null串
- 空串 “” 是长度为0的字符串
//检查一个字符串是否为空
if (str.length() == 0);
//或
if (str.length(""))
- String变量还可以存放一个特殊的值, 名为Null ,表示目前没有任何对象与该变量关联.
//检查一个字符串是否为null
if (str == null);
//检查一个字符串既不是null ,也不是空串
if (str != null && str.length() !=0);
码点与代码单元
- length方法将返回采用UTF-16编码表示给定字符串所需的代码单元数量.
String a1 = "Hello";
int a = a1.length(); //5
- 调用s.charAt(n)将返回位置n的代码单元,n介于0 ~ s.length-1之间.
char first = a1.charAt(1); //'H'
- 使用codePoints方法,它会生成一个int值的"流 " ,每个int值对应一个码点.可以将它装换为一个数组,在完成遍历
int[] codePoints = str.codePoint().toArray();
//反之, 要把一个码点数组转换为一个字符串,可以使用构造器
String str = new String(codePoints, 0, cidePoints.lengh);
输入与输出
读取输入
- 需要构造一个与"标准输入流" System.in关联的Scanner对象
- 使用Scanner类的各种方法读取输入
- nextLine方法:输入一行
- next方法 : 读取一个单词
- nextInt方法:读取一个浮点数
- nextDouble方法 : 读取小数
Scanner in = new Scanner(System.in);
System.out.print("What is your name?");
String name = in.next();
格式化输出
java5沿用了C语言函数库中的printf方法
//例如
System.out.printf("%8.2f", x);
转换符
转化符 | 类型 | 实例 | 转换符 | 类型 | 实例 |
---|---|---|---|---|---|
d | 十进制整数 | 123 | s | 字符串 | Hello |
x | 十六进制整数 | 9f | c | 字符 | H |
o | 八进制 | 236 | b | 布尔 | true |
f | 定点浮点数 | 32.4 | h | 散列码 | 32432b3 |
e | 指数浮点数 | 1,23e+01 | % | 百分号 | % |
g | 通用浮点数 | — | n | 与平台有关的行分隔符 | |
a | 十六十进制浮点数 | 0x1.fccdp3 |
标志:
标志 | 目的 |
---|---|
+ | 打印正数和复数的符号 |
空格 | 在正数之前添加空格 |
0 | 数字之前添加空格 |
- | 左对齐 |
( | 将负数括在括号内 |
, | 添加分组分隔符 |
#(对于f格式) | 包含小数点 |
#(对于x或0格式) | 添加前缀0x或0 |
$ | 指定要格式化的参数索引. |
< | 格式化前面说明的数值 |
文件输入与输出
- 要读取构造一个Scanner对象
Scanner in = new Scanner(Path.of("myfile.tx"), StandardCharsets.UTG_8);
-
Scanner(Path p , String encoding)
构造一个使用给定字符编码从给定路径读取数据的Scanner
-
Scanner(String data)
构造一个从给定字符串读取数据的Scanner
-
PrintWriter(String fileName)
构造一个将数据写入文件的PrintWriter.
-
static Path of(String pathname)
根据给定的路径名构造一个Path
控制流程
选择语句
if语句
if(条件){
执行语句;
}
if/else语句
if(条件){
执行语句;
}else{
否则执行;
}
if/else if/else语句
if(条件){
执行语句;
}else if(条件){
符合执行;
}else if(条件){
符合则执行;
}else{
否则执行;
}
switch语句
//case中若没有break终止,则会发生case穿透.直到遇见break
switch(选择){
case (对象):
执行语句;
break;
case (对象):
执行语句;
break;
...
default:
没有匹配对象再执行;
}
注 case标签对象 :
- 类型为char, byte, short或int的常量表达式
- 枚举类型
- 从Java7开始,case标签还可以是字符串字面量
循环语句
for循环
for (计数器初始化 ; 循环条件 ; 更新计数器){
执行语句
}
while循环
while (条件){
执行语句;
}
do while语句
do
{
执行语句
}
while(终止条件);
break与continue
break : 用于跳出当前循环
带标签的break语句 :
//标签必须放在希望跳出的最外层循环之前,并且必须紧跟一个冒号.
//如果输入有误,执行带标签的break会跳转到带标签的语句块末尾.
//如:
Scanner sc = new Scanner(System.in);
int n;
red_data: //标签是自定义的
while(true){
System.out.println("进入循环");
for (int i=1; i<=10;i++){
System.out.println("内层循环");
n = sc.nextInt();
if (n<10)
break red_data; //跳到标签指向块的末尾
System.out.println("not");
System.out.println("not");
}
System.out.println("yes");
}
System.out.println("跳出循环");
continue: 越过循环体的剩余部分,立刻跳到循环首部
带标签的continue语句 : 将跳到与标签匹配的循环的首部
数组
声明数组
-
格式一: 数据类型[] 数组名
-
格式二: 数据类型 数组名[]
常使用格式一, 他可以将类型与变量名清晰地分开
数组初始化值动态初始化
- 初始化: 在内存中,为数组开辟一个空间
- 格式 : 数据类型[] 变量名 = new 数据类型 [数据长度]
- 如: int [] arr = new int [100];
- 数组一旦创建好了,长度是不能发生变化的
静态初始化
静态初始化: 初始化时,就可以指定数组要存储的元素, 系统还会自动计算该数组长度
- 格式 : 数据类型[] 变量名 = new 数据类型[] {数据1 , 数据2 , 数据3 …}
- 简化格式 : 数据类型 [] 变量名 = {数据1, 数据2 , 数据3, …}
int[] as = {1,3,4,5}
//等于,同样为左边在栈, 右边在堆
int[] as = new int[] {1,3,4,5}
创建数组对象并同时提供初始值的简写形式
- 格式:int[] 数组名 = {1,2,3,4,5}
- 同时可以声明一个匿名数组:new int[] {1,2,3,4,5}
数组元素访问
-
索引是数组中空间的编号
- 特征1 : 索引从0开始
- 特征2 : 索引是连续的
- 特征3 : 索引逐一增加, 每次加1
-
格式 : 数组名[索引]
-
作用:访问数组元素
数组的默认值
整数 : 默认值0
小数 : 默认值0.0
布尔 : 默认值false
字符 : 默认值空字符 或 0 或 \u000
应用数据类型 : 默认值null
数组的特点
1. 数组是序排列的
2. 数组属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型
3. 创建数组对象会在内存中开辟一整块连续的空间
4. 数组的长度一旦确定,就不能修改
循环遍历
普通遍历
在idea中可使用 数组名称 + fori +回车 可快速补充遍历内容
for (int i= 0 ; i<a.length; i++)
System.out.println(a[i]);
for each循环
- 格式 : for (variable : collection) statement
例如:
for (int element : a)
System.out.println(element);
解释:循环a中每一个元素(for each element in a)
数组操作的两个常见小问题
-
数组角标越界的异常:ArrayIndexOutofBoundsException
-
空指针异常:NullPointerException
int[] arr= newint[3];
//把原来的地址给覆盖了,现在的arr就无法找到堆里面的小空间,原小空间没有被指向,将自动消失
arr= null;
System.out.println(arr[0]);
//所以在后面不能用null赋值
内存分配
- 栈内存 : 方法运行时, 进入的内存, 局部变量都存放于这块内存当中
- 堆内存 : new出来的内容都会进入堆内存, 并且会存在地址值
- new会在堆内存中开辟一个新内存
- 方法区 : 字节码文件(. class文件)加载时进入的内存
- 本地方法栈 : 调用操作系统相关资源
- 寄存器 : 交给CPU去使用
多维数组
- 静态初始化
int[][] arr = new int[][]{{1,2,3},{1,2},{1,2,3}};
- 动态初始化
int[] arr = new int[2][3];
//或者
int[] arr = new int[3][];
-
地址表示
[[f@6d9802
- [[ 表示二维数组
- f 表示float类型
- @6d9802 表示内存地址
-
数组的内存解析
Arrays工具类
- 导入Arrays类:import java.util.Arrays
- 常用的方法
String
String的使用
- 实例化的方式
- 通过字面量定义的方式
- 通过new + 构造器() 的方式
- String的存放
- 常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量
- 只要其中有一个结果是变量,结果就在堆中
- 如果拼接的结果调用intern()方法,返回值就在常量池中
加上代码便于理解
核心原理
String类位于java.lang包下,是Java语言的核心类,提供了字符串的比较、查找、截取、大小写转换等操作;Java语言为“+”连接符(字符串连接符)以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
...
}
- String类被final关键字修饰,意味着String类不能被继承,并且它的成员方法都默认为final方法;字符串一旦创建就不能再修改。
- String类实现了Serializable、CharSequence、 Comparable接口。
- String实例的值是通过字符数组实现字符串存储的。
“+”连接符
-
实现原理:字符串连接是通过 StringBuilder(或 StringBuffer)类及其append 方法实现的,对象转换为字符串是通过 toString 方法实现的
-
效率:使用“+”连接符时,JVM会隐式创建StringBuilder对象,大量StringBuilder创建在堆内存中,肯定会造成效率的损失,所以在这种情况下建议在循环体外创建一个StringBuilder对象调用append()方法手动拼接
-
特殊情况:当"+"两端均为编译期确定的字符串常量时,编译器会进行相应的优化,直接将两个字符串常量拼接好
equals和==
-
String中==判断的是两个对象的地址值是否相同,equals被String对象底层重写,进而判断两字符串是否相同。
-
重写equals的注意事项:
- 任何对象和null判等都是false
- 任何对象和自己本身判等都是true
- 如果要相等,必须是同一个类型
- 对比你关心的业务数据
@Override public boolean equals(Object obj){ if(obj == null){ return false; } if(obj == this){ return true; } if(this.getClass() != obj.get.Class()){ return false; } Student other = (Student)obj; return this.id == other.id && this.name.equals(other.name); }
字符串常量池
- 内存分配的3种常量池:Class常量池,运行时常量池,字符串常量池
- 常量池中一定不存在两个相同的字符串
- intern方法:ntern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回
String,StringBuilder和StringBuffer
- 主要区别
- String是不可变字符序列,StringBuilder和StringBuffer是可变字符序列。
- 执行速度StringBuilder > StringBuffer > String。
- StringBuilder是非线程安全的,StringBuffer是线程安全的。
方法
定义
- 格式:
public static void 方法名(){
//方法体
}
//方法名遵循小驼峰命名法
-
作用:
- 提高代码的复用性
- 提高代码的可维护性
-
调用 : 方法名()
带返回值方法定义
- 格式
public static 数据类型 方法名(参数){
return 数据;
}
return关键字
- 作用(核心思想):
- 结束方法,让方法停止
- 将后面的值返回给调用者
注意事项
- 方法不能嵌套定义
- void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据
方法重载
-
方法重载概念
方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
- 多个方法在同一个类中
- 多个方法具有相同的方法名
- 多个方法的参数不相同,类型不同或者数量不同
-
注意:
- 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
- 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载
-
例子:
public class Test { public static void main(String[] args) { //调用方法 System.out.println(compare(10, 20)); System.out.println(compare((byte) 10, (byte) 20)); } //int public static boolean compare(int a, int b) { System.out.println("int"); return a == b; } //byte public static boolean compare(byte a, byte b) { System.out.println("byte"); return a == b; }
-
重载概念:方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
- 多个方法在同一个类中
- 多个方法具有相同的方法名
- 多个方法的参数不相同,类型不同或者数量不同
-
注意:
- 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
- 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载
-
例子:
public class Test { public static void main(String[] args) { //调用方法 System.out.println(compare(10, 20)); System.out.println(compare((byte) 10, (byte) 20)); } //int public static boolean compare(int a, int b) { System.out.println("int"); return a == b; } //byte public static boolean compare(byte a, byte b) { System.out.println("byte"); return a == b; }