Java核心编程笔记
目录
- 变量的命名:变量类型 变量名字 赋值符号 值;
①不能使用Java里有功能的单词;如(不能用int、double、char、final等作名字)
②不能用数字做变量名开头;
③不能包含除_和﹩之外的符号;
④中间不能有空格;
- 全局变量:定义在方法(函数)和代码块之外的变量。
- 局部变量:定义在方法或者代码块之间的变量。
- Java是强类型语言,严格区分大小写。
- 在Java的方法中,定义一个常量必须用关键字final。常量一旦初始化就不可以被修改。
- Java中的默认浮点型是double。
- 浮点型数据根据存储长度和精度的不同,进一步分为double和float两种具体类型,doubled的精度高于float。注意:让一个float型的变量等于一个带小数的数的时候,数字后面需要加一个在字母f或F。
Java中的数据类型:
1、基本数据类型(八种):
字节型 | byte | 1 字节 |
短整型 | short | 2 字节 |
整型 | int | 4 字节 |
长整型 | long | 8 字节 |
单精度浮点型 | float | 4 字节 |
双精度浮点型 | double | 8 字节 |
字符型 | char | 2 字节 |
布尔型 | boolean | 1 字节 |
2、字符型, 字符型的值使用单引号引起来,当值为整形时不需要单引号
char ch1 = 3;
char ch2 = 'a';
char ch3 = 97;
System.out.println(ch1);
System.out.println(ch3);
3、布尔值类型,注意:Java中布尔值类型只有true和false两个值
boolean bool1 = true;
boolean bool2 = false;
4、 引用数据类型
除了基本数据类型,其他全部是引用数类型,如:String、数组等
Java注释
- // 单行注释
2、/*
* 多行注释
*/
3、/**
* 文档注释
*/
变量的类型可以强制改变
在使用变量的时候,其类型可以暂时被强行转换成另一个类型,方法是:(另一个数据类型)变量。列如:
int a = 9;
System.out.println((double)a);
(double)a强行把int型的a转换成double型。
进制
十进制数形式:如 54、-67、0。
八进制数形式:**Java 中的八进制常数的表示以 0 开头,如 0125 表示十进制数 85,-013 表示十进制数 -11。
十六进制数形式:Java 中的十六进制常数的表示以 0x 或 0X 开头,如 0x100 表示十进制数 256,-0x16 表示十进制数 -22。
第二次:2022/10/27
Java数据类型转换
一、自动转换
1、两种数据类型彼此兼容。
2、小数据类型转换为大数据类型时可以自动转换。例如:
例如:byte (1字节)类型向 short(2字节) 类型转换时,由于 short 类型的取值范围较大,会自动将 byte 转换为 short 类型。
可以自动转换的数据类型如下:
- 数值型数据的转换:byte→short→int→long→float→double。
- 字符型转换为整型:char→int。
二、强制转换
1、大数据类型转换为小数据类型时需要强制转换:
小类型 变量名 = (需要转换的类型) 大类型;
2、short类型与char类互相转化需要强制转换
例如:
int num1 = 1000;
byte b3 = (byte) num1;
3、基本数据类型与引用数据类型不能相互转换。
Java算数运算符
- 一元运算符:
“-”取反 “++”自加 “--”自减
- 二元运算:
取模运算(%)。加(+)、减(-)、乘(`*`)、除(\)
- 算数赋值运算:
=:赋值符号
+=:如, num += 2; -----> 本质:num = num + 2;
-=: 如, num -= 2; -----> 本质:num = num - 2;
*=: 如, num *= 2; -----> 本质:num = num * 2;
/=: 如, num /= 2; -----> 本质:num = num / 2;
%=: 如, num %= 2; -----> 本质:num = num % 2;
Java逻辑运算符
- && 短路与:a && b (a和b同时为真时为真)
- || 短路或:a && b (a和b有一个为真时为真)
- & 逻辑与:同&&
- | 逻辑或:同||
- ! 逻辑非:!a (a为真时,值为假;a为假时,值为真)
短路与、短路或和逻辑与、逻辑或的区别:
- a && b :如果 a 为 fase,则不计算 b(因为不论 b 为何值,结果都为 fase)
- a || b :如果 a 为 true,则不计算 b(因为不论 b 为何值,结果都为 true)
- a & b : a无论是true或fase,b都会进行计算
- a | b : a无论是true或fase,b都会进行计算
java关系运算符
注意:当引用数据类型使用==和!=做比较运算时的区别:
public class Demo02 {
public static void main(String[] args) {
/**
* 当引用数据类型使用==和!=做比较运算时的区别:
*
*/
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
/**
* s1.equals(s3):比较s1与s3的内容是否相同
*/
System.out.println(s1.equals(s3));
quals(obj)方法和 == 的区别:
1、 equals方法比较的是两个对象的内容是否相等
2、 == 比较的是两个对象再内存中存放的地址是否为同一个
}
}
结果:
创建扫描器对象
Scanner scan = new Scanner(System.in);
System.out.println("请输入您的名字:");
name = scan.next();
next()与nextLine()方法的区别:
1、当遇到空格或者回车的时候 next()方法停止读取
2、当遇到回车的时候 nextLine()方法停止读取,读取整行数据
Java位移运算符
>> 右位移运算符:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。(相当于原数整除 2 的结果)
<< 左位移运算符:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。(相当于原来数的 2 倍)
分支结构
- if (条件表达式) {
语句块;
}
- if (表达式) {
语句块1;
} else {
语句块2;
}
- 木运算语法(本质:还是if语句):
条件表达式 ? 表达式1 :表达式2
当表达式结果true,执行表达式1,否则执行表达式2
-
switch(表达式) {小括号里要放一个整型变量或字符型变量。表达式必须为 byte,short,int,char类型。
case 值1:
语句块1;
break;
case 值2:
语句块2;
break;
…
case 值n:
语句块n;
break;
default:
语句块n+1;
break;
}
循环结构
- while(条件表达式) {
语句块;
}
- do {
语句块;
}while(条件表达式);
while循环与do...while循环的区别:
1、while是先判断后执行,do...while循环是先执行然后再判断
2、do...while循环至少执行一次
while循环与do...while的特点:都是循环执行某一语句,循环次数素不固定
- for(表达式1; 表达式2; 表达式3) {
语句块;
foreach 循环语句是 for 语句的特殊简化版本,主要用于执行遍历功能的循环。 |
}
foreach 语句的用法
foreach语法:
for(迭代变量类型 变量的名字 :需要遍历(迭代)的对象){
语句块;
}
break语句和continue 语句
- break:表示跳出当前层循环。
- continue :结束本次循环,但不影响下一次循环。
- return:跳出当前方法的循环
方法
- 定义方法的语法: 修饰符 返回值类型 方法名(参数1,参数2...) { 方法体... }
- 方法(函数)的类型:
1、无参无返回值
修饰符 void 方法名(){ 方法体 }
2、无参有返回值
修饰符 返回值类型 方法名(){ 方法体}
3、有参无返回值
修饰符 void 方法名(参数1, 参数2,....){ 方法体}
4、有参有返回值
修饰符 返回值类型 方法名(参数1, 参数2,....){ 方法体}
- 方法重载:
重载就是在一个类中,有相同的函数名称,但参数列表不相同的方法。
注意:
方法重载只与方法名字和参数列表有关,与方法返回值类型无关
方法签名:方法名字 + 参数列表
- 方法调用 1、通过 对象.方法名字(参数) 2、类名.方法(参数) 3、方法(参数)
数组
一维数组
- 数组定义:
用来存放相同类型的一组数据
数组下标从0开始,对数组元素进行操作是通过数组的下标(索引),数组的最后一个元素的下标为:数组长度-1
数组一旦被创建,则数组的长度不可被修改
语法:
静态创建数组
数据类型[] 数组名 = {值1,值2....}
数据类型 数组名[] = {值1,值2....}
动态创建数组
数据类型[] 数组名 = new 数据类型[数组长度]
数据类型 数组名[] = new 数据类型[数组长度]
- 数组元素必须是相同类型的,不允许出现混合类型。
- 数组的默认初始化、
int a2[] = new int[2];//默认值0,0
boolean[] b = new boolean[2];//默认值 false,false
String[] s = new String[2];//默认值null
随机数:
1、Random random = new Random();
生成指定范围内的随机数 random.nextInt(10)
2、double random = Math.random();
生成随机数的范围 0.0-1.0,但是永远到不了1
二维数组
数据类型[ ][ ] 数组名字 = new 数据类型[m][n]
例如:
int [ ][ ] arr = new int[5][3]; //也可以理解为“5行3例”。
- 遍历二维数组:
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + "\t");
}
System.out.println();
} |
- 静态初始化数组:
数据类型[][] 数组名 = {{元素1,元素2....},{元素1,元素2....},{元素1,元素2....}.....};
数组扩容
数组扩容与缩容的实质:就是创建一个新的数组,新数组的长度比原来的数组(大,扩容,小,缩容),然后将原来数组中的内容全部拷贝到新的数组中,最后将新数组重新赋给原来的数组。
// 对数组进行缩容
int arr1[] = Arrays.copyOf(arr, 5); |
// 扩容,案例:将arr数组长度扩容到15
int[] arr2 = Arrays.copyOf(arr, 15); |
Arrays类
数组的复制:
- System.arraycopy(src, 1, dest, 0, 6);
src为原数组,1为复制的起始位置(数组下标值),dest为目的数组,0为目的数组放置的起始位置(数组下标值),6为复制的长度
int arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 案例:将arr1数组的 3-8的元素复制到arr2中去
int arr2[] = new int[6];
System.arraycopy(arr1, 2, arr2, 0, 6); |
- Arrays.copyOf(arr, length)
// 案例:将arr1数组进行复制,复制的范围下标为5之前的所有元素
int arr3[] = Arrays.copyOf(arr1, 5); |
- Arrays.copyOfRange(src, 1, 3);
// 案例:将arr1数组中的元素复制到arr4数组中,复制到范围为下标1开始,到下标6结束
int[] arr4 = Arrays.copyOfRange(arr1, 1, 6); |
(面向对象)oop
建对象语法:
数据类型 引用类型变量 指向(引用) new关键字 对象
Student zs = new Student();
OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。OOP 主要有以下的概念和组件:
组件 - 数据和功能一起在运行着的计算机程序中形成的单元,组件在 OOP 计算机程序中是模块和结构化的基础。
抽象性 - 程序有能力忽略正在处理中信息的某些方面,即对信息主要方面关注的能力。
封装 - 也叫做信息封装:确保组件不会以不可预期的方式改变其它组件的内部状态;只有在那些提供了内部状态改变方法的组件中,才可以访问其内部状态。每类组件都提供了一个与其它组件联系的接口,并规定了其它组件进行调用的方法。
多态性 - 组件的引用和类集会涉及到其它许多不同类型的组件,而且引用组件所产生的结果依据实际调用的类型。
继承性 - 允许在现存的组件基础上创建子类组件,这统一并增强了多态性和封装性。典型地来说就是用类来对组件进行分组,而且还可以定义新类为现存的类的扩展,这样就可以将类组织成树形或网状结构,这体现了动作的通用性
Java内存分析
堆:存放所有new出来的对象;
栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(对象可能在常量池里)(字符串常量对象存放在常量池中。
封装
封装的意义:
1、对外提供可调用的,稳定的功能。
2、封装容易变化的,具体的细节,外界不可访问,这样封装的意义在于:
a. 降低代码出错的可能性,便于维护。
b. 当内部的实现细节改变时,只要保证对外的功能定义不变,其他的模块就不会因此而受到牵连。
封装的核心:属性私有化,行为(方法)公开化
关于super 与 this 关键字的对比(区别):
1. super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)。
2. this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)。
3. super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)。
4. this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
5、调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
6、super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
7、super()和this()均需放在构造方法内第一行。
8、尽管可以用this调用一个构造器,但却不能调用两个。
9、this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
10、 this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
11、 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
方法重写
方法重写要遵循两同两小原则:
两同:
1、方法名称相同
参数列表相同
两小:
派生类方法的返回值类型小于或等于超类方法的
a、void时,必须相同
b、基本数据类型时,必须相同
c、引用数据类型时,小于或等于
派生类方法抛出的异常小于或等于超类方法的
一大:
派生类方法的访问权限大于或等于超类方法的
多态
- 多态: 是指同一行为,具有多个不同表现形式。
- 多态的前提:有继承关系,子类对象是可以赋值给父类类型的变量。
父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();
引用类型转换
向上转型:多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。
使用格式:
父类类型 变量名 = new 子类类型();
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
使用格式:
子类类型 变量名 = (子类类型) 父类变量名;
Final关键字
fina: 不可改变,最终的含义。可以用于修饰类、方法和变量。
-
- 类:被修饰的类,不能被继承。
- 方法:被修饰的方法,不能被重写。
- 变量:被修饰的变量,有且仅能被赋值一次。
- final修饰的类,不能被继承。
格式如下:final class 类名 {
}
- final修饰的方法,不能被重写。
格式如下:
修饰符 final 返回值类型 方法名(参数列表){
方法体
}
抽象类
父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了(因为子类对象会调用自己重写的方法)。换句话说,父类可能知道子类应该有哪个功能,但是功能具体怎么实现父类是不清楚的(由子类自己决定),父类只需要提供一个没有方法体的定义即可,具体实现交给子类自己去实现。我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。
抽象方法: 没有方法体的方法。
抽象类:包含抽象方法的类。
abstract使用格式
abstract是抽象的意思,用于修饰方法方法和类,修饰的方法是抽象方法,修饰的类是抽象类。
抽象方法
使用`abstract` 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
定义格式:
修饰符 abstract 返回值类型 方法名 (参数列表);
抽象类
如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。
定义格式:
abstract class 类名字 {
}
接口
定义格式
//接口的定义格式:
interface 接口名称{
// 抽象方法
}
// 接口的声明:interface
// 接口名称:首字母大写,满足“驼峰模式”
内部类
按定义的位置来分
1. 成员内部内,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
2. 静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
3. 局部内部类,类定义在方法内
4. 匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。
内部类的使用格式:
外部类.内部类。 // 访问内部类的类型都是用 外部类.内部类
获取成员内部类对象的方式:
外部类.内部类 变量 = new 外部类().new 内部类();
枚举
声明枚举时必须使用 enum 关键字,然后定义枚举的名称、可访问性、基础类型和成员等。
任意两个枚举成员不能具有相同的名称,且它的常数值必须在该枚举的基础类型的范围之内,多个枚举成员之间使用逗号分隔。
例 1
下面代码定义了一个表示性别的枚举类型 SexEnum 和一个表示颜色的枚举类型 Color。
public enum SexEnum{
male,female;
}
public enum Color{
RED,BLUE,GREEN,BLACK;
}
String字符串
- 字符串截取:
substring(int start): 从指定位置开始截取,start表示开始位置下标
substring(int start, int end):截取指定范围内的字符串,含前不含尾
- 字符串与int相互转换:
(字符串转int类型时字符串只能是纯数字)
- String转int
1、Integer.parseInt(str)
2、Integer.valueOf(str).intValue()
- int转String
1、String s = String.valueOf(i);
2、String s = Integer.toString(i);
3、String s = "" + i;
字符串大小写转换
- 字符串名.toLowerCase() // 将字符串中的字母全部转换为小写,非字母不受影响
- 字符串名.toUpperCase() // 将字符串中的字母全部转换为大写,非字母不受影响
StringBuffer类
三种构造方法:
- // 定义一个空的字符串缓冲区,含有16个字符的容量
StringBuffer str1 = new StringBuffer();
- // 定义一个含有10个字符容量的字符串缓冲区
StringBuffer str2 = new StringBuffer(10);
- // 定义一个含有(16+4)的字符串缓冲区,"青春无悔"为4个字符
StringBuffer str3 = new StringBuffer("青春无悔");
str1.capacity() 用于查看 str1 的容量
字符串附加
StringBuffer 类的 append() 方法用于向原有 StringBuffer 对象中追加字符串。
例如:buffer.append(str);
替换字符
StringBuffer 类的 setCharAt() 方法用于在字符串的指定索引位置替换一个字符。
列如: StringBuffer sb = new StringBuffer("hello");
sb.setCharAt(1,'E');
System.out.println(sb); // 输出:hEllo
反转字符串
StringBuffer sb = new StringBuffer("java");
sb.reverse();
System.out.println(sb); // 输出:avaj
删除字符串
- StringBuffer 对象.deleteCharAt(int index); (用于移除序列中指定位置的字符)
- StringBuffer 对象.delete(int start,int end); (删除指定位置的字符,然后将剩余的内容形成一个新的字符串)
Math类
abs (绝对值)
max(最大值)
min(最小值)
……
正则表达式
字符类
- [abc]:代表a或者b,或者c字符中的一个。
- [^abc]:代表除a,b,c以外的任何字符。
- [a-z]:代表a-z的所有小写字符中的一个。
- [A-Z]:代表A-Z的所有大写字符中的一个。
- [0-9]:代表0-9之间的某一个数字字符。
- [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
- [a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符。
逻辑运算符
- &&:并且
- | :或者
- \ :转义字符
预定义字符
- "." : 匹配任何字符。
- "\d":任何数字[0-9]的简写;
- "\D":任何非数字[^0-9]的简写;
- "\s": 空白字符:[ \t\n\x0B\f\r] 的简写
- "\S": 非空白字符:[^\s] 的简写
- "\w":单词字符:[a-zA-Z_0-9]的简写
- "\W":非单词字符:[^\w]
数量词
- X? : 0次或1次
- X* : 0次到多次
- X+ : 1次或多次
- X{n} : 恰好n次
- X{n,} : 至少n次
- X{n,m}: n到m次(n和m都是包含的)
内置类和包装类
拆箱与装箱:
拆箱:将包装类转为基本数据类型
装箱:将基本数据类型转为包装类
包装类:int --- Integer char --- Character
其他 基本类型 包装类都是把首字母改为大写
集合
ArrayList集合(数组)
ArrayList <元素的数据类型> 集合名字 = new ArrayList();
例:ArrayList <String> list = new ArrayList();
list.add(~~) // 添加元素
list.get (4) // 获取指定位置的元素
list.size() // 获取集合的长度
list.set (5,”~~”) // 修改指定位置元素为~~
list.IndexOf(“~~”) // 查找元素~~第一次在集合中出现的位置
list.lastIndexOf(“~~”) // 查找元素~~最后一次在集合中出现的位置
LinkedList集合(链表)
需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,但是 LinkedList 类随机访问元素的速度则相对较慢。
set集合
set集合不能保证输入与输出的对象顺序相同。
- HashSet <String> courseSet = new HashSet<String>();
- TreeSet<Double> scores = new TreeSet<Double>();
Map集合
Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。
Key唯一对应一个value(因此Map 的 key 不允许重复,value 可以重复,value重复后会覆盖上一个的value值)