Java基础学习笔记
一、基础入门
1.1 JRE和JDK
-
JDK是什么?由哪些内容组成
JDK是Java开发工具包
- JVM虚拟机:Java程序运行的地方
- 核心类库:Java已经写好的东西,我们可以直接用
- 开发工具:javac、java、九点半、jhat等
-
JRE是什么?由哪些内容组成?
JRE是Java运行环境
JVM、核心类库、运行工具
-
JDK、JRE、JVM三者的包含关系
JDK包含了JRE
JRE包涵了JVM
二、Java的基础语法
2.1 注释
注释内容不会参与编译和运行,仅仅是对代码的解释说明
2.1.1 单行注释
// 注释信息
2.1.2 多行注释
/* 注释信息 */
2.1.3 文档注释
/** 注释信息*/
2.2 关键字
2.2.1 什么是关键字
被Java赋予了特殊含义的英文单词
2.2.2 关键字的特点
- 关键字的字母全部小写
2.2.3 Class关键字的含义
用于创建/定义一个类,类是JAVA最基本的组成单元,后面跟随类名
2.3 字面量
数据在程序中国呢的书写格式
2.3.1 字面量类型
字面量类型 | 说明 | 举例 |
---|---|---|
整数类型 | 不带小数点的数字 | 123 |
小数类型 | 带小数点的数字 | 1.3,44.3 |
字符串类型 | 用双引号括起来的内容 | "HelloWorld","我对自己" |
字符类型 | 用单引号括起来的,内容只能有一个 | 'A','B' |
布尔类型 | 只有两个值 | true,false |
空类型 | 特殊的值:null | null |
2.3.2 特殊符号
-
\t
制表符在打印的时候,把前面字符串的长度补齐到8,或者8的整数倍。至少补一个空格,最多补8个空格。
-
\n
2.4 变量
2.4.1 变量的定义格式
数据类型 变量名 = 数据值;
2.4.2 变量的注意事项
- 只能存储一个值
- 变量名不允许重复定义
- 一条语句可以定义多个变量
- 变量在使用之前一定要进行赋值
- 变量的作用域范围
三、 计算机的存储规则
计算机中,任意数据都是一二进制的形式来存储的
- 二进制:由0和1组成,代码中以
0b
开头 - 十进制:由0~10组成
- 八进制:由0~7组成,代码中以
0
开头 - 十六进制:由0~F组成,代码中以
0x
开头
任意进制转十进制
公式:系数*基数的权次幂. 相加
- 系数:每一位上的数
- 基数:当前进制数
- 权:从右向左,一次为0,1,2,3,4,5…
十进制转其他进制
除基取余法
- 不断的除以基数,得到余数,直到商为0,再将鱼属倒着拼起来即可
3.1 Text文本
3.1.1 数字
转二进制存储
3.1.2 字母
对应的ASCII表的值转二进制
3.1.3 汉字
对应的uniCode码表转二进制
3.2 Image图片
通过每一个像素点钟的RGB来存储
3.3 Sound声音
对声音的波形图进行采样再存储
四、 JAVA的基本语法
4.1 数据类型
4.1.1 基本数据类型
数据类型 | 关键字 | 取值范围 |
---|---|---|
数字 | byte | -128~127 |
short | -32768~32767 | |
int | -214743648~2147483647 | |
long | -9223372036854775808~9223372036854775807 | |
浮点数 | float | -3.401298e-38~3.402823e+38 |
double | -4.9000000e-324~1.797693e+308 | |
字符 | char | 0~65535 |
布尔 | boolean | true,false |
long类型在数据后面要添加字母
L
,虽然大小写不限,但建议使用大写long l = 999999999L;
float类型要再数据后添加
F
,同上float f = 9999.3F;
数字类型的取值范围的排列:
double
>float
>long
>int
>short
>byte
4.1.2 引用数据类型
暂时空
4.2 标志符
就是给类、变量、方法起的名字
-
由数字、字母、下划线和美元符组成
-
不能以数字开头
-
不能是关键字
-
区分大小写
4.2.1 小驼峰命名法
用于给方法、变量命名
- 首单词首字母小写,后面的单词首字母大写
- 只有一个单词时,全部小写
4.2.2大驼峰命名
用于类名命名
- 所有单词首字母大写
4.3 键盘录入
步骤:
-
导包:导出
Scanner
这个包import java.util.Scanner; // 导包的动作必须在类定义的上面
-
创建对象:准备使用
Scanner
这个包Scanner sr = new Scanner(System.in); // sr是变量名,可变,其他的不允许
-
接受数据:真正使用这个
Scanner
int number1 = sr.nextInt(); // 只有i是变量名,别的不允许变
eg:
import java.util.Scanner;
public class PrintSomeSthing {
public static void main(String[] args){
Scanner sr = new Scanner(System.in);
System.out.println("请输入第一个数字");
int number1 = sr.nextInt();
System.out.println("请输入第二个数字");
int number2 = sr.nextInt();
System.out.println("两个数的和为:"+(number1+number2));
}
}
五、运算符
-
运算符和表达式
运算符:对字面量或者变量进行操作的符号
表达式:用运算符将变量或者字面量连接起来,符合Java运算的式子称为表达式
int a = 10; int b = 15; System.out.println(a+b)
+
就是运算符a + b
就是表达式- 由于
+
是算数运算符,所以a + b
叫做算数表达式
5.1 算数运算符
-
加
+
-
减
-
-
乘
*
-
除
/
-
取模/取余
%
-
但是算数运算符在计算浮点数的时候并不是完全准确,如下:
System.out.println(1.1 + 1.01); //2.1100000000000003 System.out.println(1.1 - 1.01); //0.09000000000000008 System.out.println(1.1 * 1.01); //1.1110000000000002 System.out.println(0.1+0.2); //0.30000000000000004
这种情况是因为算数过程基于
IEEE754
运算,导致的误差。
-
练习:
/**
* 剥离number的个、十、百位的数字
* */
public class demo1 {
public static void main(String[] args) {
int number = 321;
int g = number % 10;
int s = number /10%10;
int b = number / 100%10;
System.out.println(g);
System.out.println( s);
System.out.println(b);
}
}
5.1.2 隐式转换
当数据类型不同时,是不能直接进行计算的
-
把一个取值范围小的数值类型,转换成取值范围大的数据类型后再进行计算
/** * 算数运算符的隐形转换 */ public class demo2 { public static void main(String[] args) { int number1 = 12; double double1 = 22.0; System.out.println(number1+double1); //34.0 } }
-
byte
,short
,char
三种数据类型会先提升为int
再进行计算/** * 算数运算符的隐形转换 */ public class demo2 { public static void main(String[] args) { short short1 = 23; byte byte1 = 10; System.out.println(short1+byte1); //43 } }
5.1.3 强制转换
如果我们想把一个取值范围较大的变量,复制给取值范围较小的变量,那么我们就需要强制转换
-
格式:
目标数据类型 变量名 = (目标数据类型) 被强转的数据
/** * 数据强转 * */ public class demo3 { public static void main(String[] args) { int number1 = 123; short cha1 = (short) number1; System.out.println(cha1); } }
使用计算运算符+
转化数据类型为字符串
数值相加
- 略,与正常计算无异
字符串相加
- 当
+
操作出现字符串时,这个+
是字符串连续符,而不是算数运算符,会讲前后的数据进行拼接,产生一个新的字符串 - 连续进行
+
操作时,从左到右逐个执行
字符相加
-
byte
,short
,char
这三种类型的数据在运算时,会提升为int
再进行计算当与一个
char
类型进行操作的时候,会将这个char
转换成相应的ASCII
值,再进行操作/** * 加号不同操作运算 */ public class demo4 { public static void main(String[] args) { //1.数值与数值相加 int num1 = 12; float f1 = 12.3F; System.out.println(num1 + f1); //24.3 // 2. 与字符串相操作 System.out.println(1+"123"); //1123 // 连续操作的时候,从左到右逐次操作 System.out.println(1+3+"333"); //4333 //3. 与字符相操作 System.out.println(1+'a'); //98 System.out.println(1+3+"dd"+'a'); //4dda } }
小结
- 字符串并没有
-
,*
,/
,%
的运算的; /
和%
的区别:两个数据做除法,/
取结果的商,%
取结果的余数- 整数与整数操作,只能得到整数,想得到小数,必须有浮点数参与运算
5.2 自增自减运算符
符号 | 说明 |
---|---|
++ |
自加 |
-- |
自减 |
- 前置
++
,--
,先操作后使用- 后置
++
,--
,先使用后操作
5.3 赋值运算符
符号 | 作用 | 说明 |
---|---|---|
= |
将右面的值赋值给做面 | int a = 10 |
+= |
加后赋值 | a+=b |
-= |
~ | ~ |
*= |
~ | ~ |
/= |
~ | ~ |
%= |
取余后赋值 | ~ |
以上,除了等号(
=
)其他的扩展运算符,都包含了强制转换。/** * 扩展赋值运算符的强制类型转换 * */ public class demo5 { public static void main(String[] args) { int d1 = 123; d1 += 1.1; System.out.println(d1); // 124 } }
会将被操作值的数据类型(在案例里的
1.1
)强制转化为目标数据类型(案例里d1
),即将1.1
转化为int
后再进行相加赋值给d1
.
Java
中将浮点数转化为int
时,会直接去掉小数点后的数值。
5.4 关系运算符
符号 | 说明 |
---|---|
== |
a==b 判断a 和b 是否相等,成立为true ,不成立为false |
!= |
a!=b 判断a 与b 不想等,成立返回true ,不成立返回false |
> |
判断大于~ |
>= |
判断大于等于~ |
< |
判断小于~ |
<= |
判断小于等于~ |
5.5 逻辑运算符
-
普通逻辑运算法
符号 作用 说明 &
逻辑与(且) 两遍均为 true
,结果才是true
` ` 逻辑或 ^
逻辑异或 相同为 false
,不同为true
!
逻辑非 取反 -
短路逻辑运算符
符号 作用 说明 &&
短路与 结果与 &
相同,但是有短路效果` ` Eg:
a&&b
,若a
表达式的结果为false
那么b
表达式不会执行,否则两边都执行a||b
,若a
表达式的结果为true
那么b
表达式不会执行,否则两边都执行
5.6 三元运算符
-
三元运算符为
?
格式为:
关系表达式 ?表达式1 : 表达式2
计算规则:
- 先计算关系表达式
- 关系表达式的结果为
true
,结果为表达式1的结果,否则为表达式2的结果
5.7运算符优先级
优先级 | 运算符 |
---|---|
1 | . ,() ,{} |
2 | ! ,~(安位取反) ,++ ,-- |
3 | * ,/ ,% |
4 | + ,- |
5 | << ,>> ,>>> (位运算) |
6 | < ,<= ,> ,>= ,instanceof |
7 | == ,!= |
8 | & |
9 | ^ |
10 | ` |
11 | && |
12 | ` |
13 | ?:(三目) |
14 | = ,+= ,-= ,= ,/= ,%= ,&= … |
六、流程控制语句
6.1 顺序结构
默认就是顺序结构
6.2 分支结构
6.2.1 if
-
写法一
if(关系表达式){ //代码段 }
-
写法二
if() //只有一行的代码
要注意,定义变量,无论是否显性赋值,都算两句代码(1.定义变量的语句;2. 给变量赋值的语句)
- Java语言中规定当
if
语句不佳大括号时,不可以发表声明,因为作用域就一条语句,而现在这个语句却用来声明变量或创建一个对象,这个局部斌量和对象是没有意义的(因为,刚创建,声明周期就结束了),因此禁止这样使用。
- Java语言中规定当
-
写法三
if(){ }else{ } //========================== if (){ }else if(){ }else{ }
6.2.2 switch
-
传统写法
略,与其他语言相同
-
jdk12
以上版本新特性public class demo7 { public static void main(String[] args) { int num = 2; switch (num) { case 1 -> { System.out.println("这是1"); } case 2 -> System.out.println("这是2"); case 3 -> System.out.println("这是3"); default -> System.out.println("这是default"); } } }
- 可以用
case ***->{}
的方式来不写break
,如果只有一行代码{}
可以省略。
- 可以用
6.3 循环结构
for
while
使用时的选择:
for
循环中:知道循环次数,或者循环范围while
循环中,不知道循环次数和范围,只知道循环的结束条件
-
do...while
do{ }while(条件表达式)
6.4 跳转控制语句
continue
跳过本次循环,继续下一次循环break
,结束循环
七、 数组
7.1 数组介绍
数组指的是一种容器,可以用来存储同种数据类型的多个值;
- 容器在存储数据的时候,需要结合隐式转换考虑。
- 如:
int
类型的数组容器(byte
,short
,int
是可以存入到这个int
类型的数组中的,但是boolean
,double
并不能存入) - 如:
doubule
类型的数组容器(byte
,short
,int
,long
,float
,double
)都可以存入到double
的数组中
- 如:
7.2 数组的定义与静态初始化
7.2.1 数组的定义
-
格式一
数据类型 [] 数组名
int [] array1
-
格式二
数据类型 数组名[]
int array2[]
7.2.2 数组的初始化(静态初始化)
-
静态初始化
格式:
数据类型 []数组名 = new 数据类型[]{元素1,元素2,元素3,元素4,...};
int [] array1 = new int[]{1,2,3,8,5,6,0,7};
可简化为:
数据类型 []数组名 = {元素1,元素2,元素3,元素4,...};
int [] array1 = {1,2,3,8,5,6,0,7};
public class test1 { public static void main(String[] args) { double [] array1 = {1,2,3,8,55,5,6,0,7}; System.out.println(array1); //[I@372f7a8d } }
直接打印数组,不会直接打印数组的值,而是打印数组的地址
[
代表是个数组I
代表是int
类型(D
代表double
等等)@
是固定格式372f7a8d
是数据的地址
-
动态初始化
格式:
数据类型 [] 变量名 = new 数据类型[数组长度]
//定义了一个长度为5的数组 int [] arr = new int[5]
7.2.3 动态初始化与静态初始化的区别
- 动态初始化:手动指定数组长度,由系统给出默认初始化值。
- 只明确各书,不明确具体数值
- 静态初始化:手动指定数组元素,系统会根据元素个数,计算长度
- 已知道具体的数据
7.3 数组元素访问
格式:数组名[索引]
。
索引从
0
开始,逐个+1
。
public class test1 {
public static void main(String[] args) {
double [] array1 = {1,2,3,8,55,5,6,0,7};
System.out.println(array1); //[I@372f7a8d
System.out.println(array1[5]); // 5.0
// 给数组第一个值修改为100
array1[0] = 100;
System.out.println(array1[0]); // 100.0
}
}
7.4 数组遍历
public class test2 {
public static void main(String[] args) {
int[] arr = new int[]{1, 3, 4, 5, 6, 7, 23, 7, 8, 9, 0};
for (int i = 0; i < arr.length - 1; i++)
System.out.println(arr[i]);
//1
//3
//4
//5
//6
//7
//23
//7
//8
//9
}
7.5 数组动态内存图
Java
内存分配:
- 栈:方法运行时使用的内存,比如
main
方法运行,进入方法栈中执行 - 堆:存储对象或者数组,new来创建的都存储在堆内存
- 方法区:存储可以运行的
class
文件 - 本地方法栈:JVM在使用操作系统功能的时候使用,与开发无关
- 寄存器:给CPU使用过,与开发无关
JDK8开始,取消方法区,新增元空间,把原来方法区的多种功能进行拆分,有的功能放到了堆中,有的功能做到了元空间中。
八、 方法
8.1 什么是方法
方法是程序中最小的执行单元
方法的作用:
- 提高代码的复用性
- 提高代码可维护性
8.2 方法的格式
-
简单的方法定义
public static void 函数名() { // 函数体 }
e g:
public class function1 { public static void main(String[] args) { printName(); } public static void printName() { // 函数体 System.out.println("hhhhh"); } }
-
带参数的方法定义
-
public class function1 { public static void main(String[] args) { printName(90,10); } //定义的函数 public static void printName(int num,int age ) { // 函数体 System.out.println("hhhhh"+num+age); } }
-
带返回值的方法定义
-
public class function1 { public static void main(String[] args) { //调用 System.out.println(sum(12, 54)); //66 //调用 int res = sum(12,54); System.out.println(res); // 66 } // 定义一个函数 public static int sum(int a, int b) { int res = a + b; return res; } }
方法的注意事项:
- 方法不调用就不会执行
- 方法与方法之间是平级关系,不能嵌套定义
- 书写顺序与执行书序无关
- 如果你的函数是
viod
返回值,那么你可以不写return
,如果写return
,那么return
后面不能返回任何值
8.3 方法的重载
-
在同一个类中,定义了多个同名的方法,和谐同名的方法具有同种的功能。
-
每个方法具有不同的参数类型或个数,这些同名的方法,就构成了重载
同一个类中,方法名相同,参数不同(参数类型不同,个数不同,顺序不同,满足其一即可)的方法就叫重载与返回值无关
/* * 需求: 使用方法重载的思想设计比较两个整数是否相等的方法 * 要求: 兼容全部整数类型(byte,short,int,long) * */ public class overLoad { public static void main(String[] args) { System.out.println( contrast(2099123,2099123)); } public static boolean contrast(byte a, byte b) { return a == b; } public static boolean contrast(short a, short b) { return a == b; } public static boolean contrast(int a, int b) { return a == b; } public static boolean contrast(long a, long b) { return a == b; } }
8.4 方法的内存
九、面向对象
9.1 设计对象并使用
类和对象:
-
类:是对象共同特征的描述
-
对象:是真实存在的具体东西
java中必须先设计类才能获取对象
9.1.1 定义类
pubilc class 类名 {
1. 成员变量
2.成员方法
3.构造器
4.代码块
5.内部类
}
Javabean类:用来描述一类事物的类,在javabean类中,是不写main方法的
类名首字母建议大些,需要见名知意,大驼峰命名。
一个Java文件中可以定义多个class类,且只能有一个使用
public
修饰的类,且使用pubilc
修饰的类名必须与代码文件名相同实际开发还是建议一个文件只定义一个class类
成员变量的完整定义格式是:修饰符 数据类型 变量名称 = 初始化值,一般无需制定初始化值,存在默认值
测试类:需要写main方法,的类,我们可以在测试类中创建javabean类的对象并进行赋值,调用等操作
对象中不同数据类型的默认值
数据类型 | 明细 | 默认值 |
---|---|---|
基本类型 | byte,short,int,long | 0 |
float,double | 0.0 | |
boolean | false | |
引用类型 | 类,接口,数组,String | null |
javaBean类:
public class Phone {
//属性
String brand;
double price;
//方法(行为)
public void call() {
System.out.println("打电话");
}
public void playGame() {
System.out.println("打游戏");
}
}
测试类:
public class PhoneTest {
public static void main(String[] args) {
//创建对象
Phone p1 = new Phone();
p1.brand = "摩托罗拉";
p1.price = 2344.21;
System.out.println(p1.brand);
System.out.println(p1.price);
p1.call();
p1.playGame();
// 摩托罗拉
// 2344.21
// 打电话
// 打游戏
}
}
9.2 封装
面向对象三大特征:
-
封装
对象代表什么,就的封装对应的数据,并提供数据对应的行为
-
继承
-
多态
修饰符
-
private
- 是一个权限修饰符
- 可以修饰成员变量和成员方法
- 被
private
修饰的成员只能在本类中才能访问
为了能在其他类中能使用
private
修饰的成员,我们会在这个类中添加两个pubilc
修饰的方法Set和get分别来对成员赋值和取值 -
public
- 同上一、二条
- 被
public
修饰的成员代表公共的,在所有的类中都能访问
//使用private修饰成员的Javabean类
public class gjz {
private int num;
//set方法
public void setNum(int num) {
//可以在设置值时进行些数据校验
if (num <= 10) {
System.out.println("你的赋值过低请赋值大于10的值");
return;
}
this.num = num;
}
//get
public int getNum() {
return num;
}
}
// gjz的测试类
public class gjzTest {
public static void main(String[] args) {
gjz g1 = new gjz();
g1.setNum(9); //你的赋值过低请赋值大于10的值
g1.setNum(11);
System.out.println(g1.getNum()); //11
}
}
9.3 this关键字
所在方法调用者的地址值
- 就近原则,如上图代码,打印的值会优先选择离自己近的局部变量的
age
9.4 构造函数
构造方法也叫构造器,构造函数
- 作用:在创建对象的时候给成员变量进行初始化的
构造函数的格式:
pubilc class Student{
修饰符 类名 (参数){
方法体
}
}
注意事项
-
方法名与类名必须相同,包括大小写
-
没有返回值类型,连void也不需要要写DD
-
同时没有返回值
-
如果没有定义构造方法,系统将会给一个默认的空参构造器
-
构造器是可以重载的:带参和无参构造器两者方法名相同,但参数不同,是可以同时存在的,甚至可以多个构造器
建议无论是否使用,都手动将无参构造器和带全部参数的构造器定义
执行
- 创建对象的时候由虚拟机调用,不能手动调用
- 每创建一次对象,就会自动调用一次构造器
带参构造和空参构造
public class Student {
private String name;
private int age;
public Student() {
System.out.println("我是空参构造器触发");
//空参构造
}
public Student(String name, int age) {
this.name = name;
this.age = age;
//带参构造
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
}
调用空参构造器:
public class StudentTest {
public static void main(String[] args) {
Student s1 =new Student(); //我是空参构造器触发
}
}
调用带参构造器:
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student("hhh", 14); //我是空参构造器触发
System.out.print(s1.getAge()+" "+ s1.getName()); //14 hhh
}
}
- 无参构造器:初始化对象时,成员变量的数据均采用默认值
- 有参构造器:在初始化的时候,同时可以为对象成员赋值
9.5 标准JavaBean
9.6 对象内存图
-
一个对象的内存图
-
多个对象的内存图
-
两个变量之乡同一个对象内存图
-
this的内存原理
-
基本数据类型和引用数据类型的区别
-
局部变量和成员变量的区别
9.7 补充知识:变量成员,局部变量区别
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 类中、方法外 | 方法内、方法申明上 |
初始化值不同 | 有默认初始化值 | 没有、使用前需要初始化 |
内存位置不同 | 堆内存的当前类中 | 其值或其地址存于栈内存的当前方法中 |
生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的运行结束而消失 |
作用域 | 整个类中有效 | 当前方法中有效 |
十、String
10.1定义字符串
-
直接赋值
String str = "1234"
-
new
构造方法 说明 public String() 创建空白字符串,不含任何内容 public String(String original) 根据传入的字符串创建字符串对象 Public String (char[] chs) 根据字符数组,创建字符串对象 public String(byte[] chs) 根据自截数组,创建字符串对象
public class Str1 {
public static void main(String[] args) {
//直接赋值
String str1 = "234";
//使用new的方式来创建一个字符串对象
String str2 = new String();
String str3 = new String("1235");
System.out.println(str3); // "1235"
//传递一个字符数组创建字符串
// 应用场景:修改字符串内容的时候,我们可以吧字符串转字符数组,修改后再通过字符数组转回字符串
char[] arr = {'1', '2', '5', '9'};
String str4 = new String(arr);
System.out.println(str4); //"1259"
//传递一个字节数组,根据字节数组创建新的字符串对象
//拿到byte的值后,会根据byte的值区ASCAII表找到对应的字符,然后再创建字符串
//应用场景:在网络中传输的数据其实都是字节,可以把字节进行转换成字符串,需要这个构造方法
byte[] arr1 = {97,98,99};
String str5 = new String(arr1);
System.out.println(str5); //"abc"
}
}
10.2 两种创建方式的区别
-
直接赋值的方式
在堆中,还有一块特殊的内存(String Table)串池,专门用于存储字符串的值。但只有直接赋值的字符串的值,才会存储到这个串池中,通过new构造出来的字符串对象不会
-
通过直接赋值的字符串的值,在串池中会进行存储,赋值时,会去串池中检索,有没有相同的值,如果有,那么将会复用这个值。否则会重新创建一个值。
public class Str2 { public static void main(String[] args) { String str = "1234"; String str1 = "1234"; String str2 = '222' //这两个字符串引用的是串池中同一个变量 } }
-
-
使用new创建的方式
- 使用
new
出来的字符串对象,即使是相同的内容,也不会再对中进行复用。 - 每
new
一次,就会在堆中重新开辟一块空间用来存储字符串对象
- 使用
10.3 字符串的比较
-
==
比较- 基本数据类型比较的是具体的值
- 引用数据类型对比的是数据的地址值
public class test { public static void main(String[] args) { //基本数据类型的比较 int num1 = 1; int num2 = 1; System.out.println(num1 == num2); //true //直接赋值的方式的字符串 String str1 = "abc"; String str2 = "abc"; System.out.println(str1 == str2); //true // 直接赋值和new出来的相同内容的字符串相比较 String str3 = "cde"; char[] arr = {'c', 'd', 'e'}; String str4 = new String(arr); System.out.println(str3 == str4); //false // 两个new出来的内容相同的字符串相比较 char[] arr1 = {'e', 'f', 'g'}; String str5 = new String(arr1); char[] arr2 = {'e', 'f', 'g'}; String str6 = new String(arr2); System.out.println(str5 == str6); //false } }
-
boolean equals(要比较的字符串)
使用
equals
方法,不忽略大小写,内容需要完全一样,结果才能是truepublic class Str4 { public static void main(String[] args) { String str = new String("1234"); String str1 = "1234"; boolean res = str1.equals(str); System.out.println(res); //true String str2 = new String("abc"); String str3 = "Abc"; System.out.println(str2.equals(str3)); //false } }
-
boolean equalsIgnoreCase(要比较的字符串)
使用
equalsIgnoreCase
,忽略大小写,内容一样,返回truepublic class Str4 { public static void main(String[] args) { String str = new String("1234"); String str1 = "1234"; boolean res = str1.equalsIgnoreCase(str); System.out.println(res); //true String str2 = new String("abc"); String str3 = "Abc"; System.out.println(str2.equalsIgnoreCase(str3)); //true } }
10.4 StringBuilder
StringBuilder
可以看作是一个容器,创建之后里面的内容是可变的。
-
构造方法
构造方法 说明 public StringBuilder()
创建一个空的可变字符串对象 public StringBuilder(String str)
以 str
为初始值,构造一个可变字符串对象在
Java
的底层,对StringBuilder
做了一些特殊处理,我们直接打印StringBuilder
实例对象,打印的是对象的属性值,而不是地址值。但是本质还是对象。public class Str5 { public static void main(String[] args) { StringBuilder sb = new StringBuilder("abc"); System.out.println(sb); // abc } }
-
常用API
方法名 说明 public StringBuilder append(任意类型数据)
添加数据,并返回对象本身 pubilc StringBuilder reverse()
反转容器中的内容 public int length()
返回属性值的长度 public String toString()
将 StringBuilder
对象转化成字符串并返回public class Str5 { public static void main(String[] args) { StringBuilder sb = new StringBuilder("abc"); sb.append("sss"); sb.append("113").append(1234).append(true); System.out.println(sb); //abcsss1131234true sb.reverse(); System.out.println(sb); //eurt4321311ssscba int len = sb.length(); System.out.println(len); //17 String res = sb.toString(); System.out.println(res); //eurt4321311ssscba } }
10.5 StringJoiner
是
JDK8
出的一个可变的操作字符串的容器,可以高效,方便的拼接字符串
-
构造方法
方法 说明 public SrtringJoiner(间隔符号)
创建一个 StringJoiner
对象,使用制定的间隔符号连接public StringJoiner(间隔符号,开始符号,结束符号)
创建一个 StringJoiner
对象,使用指定的间隔、开始、结束符号连接import java.util.StringJoiner; public class Str6 { public static void main(String[] args) { StringJoiner sj = new StringJoiner("=="); sj.add("123").add("123.1"); System.out.println(sj); //123==123.1 StringJoiner sj1 = new StringJoiner(",","[","]"); sj1.add("1").add("3").add("6"); System.out.println(sj1); //[1,3,6] } }
-
常用API
方法 说明 public StringJoiner add(添加的内容)
添加内容 public int length
返回字符串对象属性值的长度 public String toString()
将拼接后的结果转换成字符串对象,并返回
10.6 字符串拼接的底层原理
分为两种代码情况:
-
没有变量参与
public class Str7 { public static void main(String[] args) { String s = "a"+"b"+"c"; System.out.println(s); //abc String s1 = "abc"; System.out.println(s1 == s); //true } }
上面的代码,在编译阶段,
java
会判断,字符串s
的生成没有其他变量的参数,直接在编译阶段就直接将拼接操作完成。 -
有其他变量的参数
public class Str7 { public static void main(String[] args) { String s = "a"; String s1 = s+"b"; String s2 = s1 + "c"; System.out.println(s2); //abc } }
在JDK8前,Java底层会使用
StringBuilder
进行操作,
十一、 集合
-
数组和集合的差别
-
长度:
- 组合的长度是固定的,
- 集合的长度不固定,插入一条数据,数据长度就自动加一,删除一条数据就,数据长度就自动减一
-
存储数据类型
- 数组可以存基本数据类型也可以存引用数据类型
- 集合只能存储引用数据类型,存储基础数据类型需要使用基础数据类型对应的包装类
-
11.1 ArrayList
11.1.1创建ArrayList
import java.util.ArrayList;
ArrayList<E> 名称 = new ArrayList<E>()
范型:限定集合中存储数据的类型
-
在
JDK7
前:ArrayList<String> list = new ArrayList<String>();
-
在
JDK7
后,可以省略后面的范型ArrayList<String> list = new ArrayList<>();
(附加)11.1.1 包装类
基本数据类型对应的包装类
基本类型 | 对应包装类 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
11.1.2 ArrayList
的成员方法
操作 | 方法名 | 说明 |
---|---|---|
增 | boolean add(E e) | 添加元素,返回值表示是否添加成功 |
删 | Boolean remove(E e) | 删除指定元素,返回值表示是否删除成功 |
删 | E remove(int index) | 删除指定元素索引的元素,返回被删除元素 |
改 | E set(int index,E e) | 修改制定索引下的元素,返回原来的元素 |
查 | E get(int index) | 获取制定索引的元素 |
查 | int size() | 集合的长度,也就是集合中元素的个数 |
import java.util.ArrayList;
public class list1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
System.out.println(list.add("addSth")); // true
System.out.println(list.add("aaacc")); // true
System.out.println(list.add("aaacc")); // true
System.out.println(list); //[addSth, aaacc, aaacc]
// remove只会操作第一个匹配到的元素,操作成功返回true,操作失败返回false,未匹配到也会返回false
System.out.println(list.remove("aaacc")); // true
System.out.println(list); // [addSth, aaacc]
// 通过index使用remove进行删除
System.out.println(list.remove(0)); // "addSth"
System.out.println(list); // [aaacc]
// set会返回被替换的值
System.out.println(list.set(0, "newSth")); //aaacc
System.out.println(list); // [newSth]
// get获取当前索引的元素
System.out.println(list.get(0)); //newSth
//与Array不通,ArrayList的长度需要借助size()来获取
System.out.println(list.size()); // 1
}
}
11.1.3 ArrayList
练习
练习1
需求:定义一个集合,添加数字,并进行遍历
遍历格式参照:[元素1,元素2,元素3]
public class list2 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
System.out.print("[");
for (int i = 0; i < list.size(); i++) {
if (i == list.size() - 1) {
System.out.print(list.get(i));
} else {
System.out.print(list.get(i) + ",");
}
}
System.out.println("]");
}
}
// [1,2,3,4]
练习2
需求:定义一个集合,添加一些学生对象,并进行遍历
学生类的属性为:姓名,年龄
import java.util.ArrayList;
public class list3 {
public static void main(String[] args) {
// 创建集合
ArrayList<Student> list = new ArrayList<>();
//创建学生对象
Student s1 = new Student(12, "zhang");
Student s2 = new Student(44, "chen");
Student s3 = new Student(21, "wang");
//添加元素
list.add(s1);
list.add(s2);
list.add(s3);
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
System.out.println(stu.getName()+","+stu.getAge());
}
}
}
//zhang,12
//chen,44
//wang,21
练习3
- 需求: main方法中定义一个集合,存入三个用户对象,用户属性为:id,username,password
- 要求:定义一个方法,根据id查找对应的用户信息,如果存在返回索引,否则-1
/*
* 需求: main方法中定义一个集合,存入三个用户对象,用户属性为:id,username,password
* 要求:定义一个方法,根据id查找对应的用户信息,如果存在返回索引,否则-1
* */
package com.study.List;
import java.util.ArrayList;
public class list4 {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<>();
User u1 = new User("1345", "hong", "12356");
User u2 = new User("1346", "zhi", "123554");
User u3 = new User("1347", "guo", "12352");
list.add(u1);
list.add(u2);
list.add(u3);
System.out.println(contains(list, "1345")); // true
}
public static int contains(ArrayList<User> list, String id) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getId().equals(id)) {
return i;
}
}
return -1;
}
}
11.1.4注意事项
-
集合中不能直接存储基本数据类型(
byte
,short
,int
,double
,long
,boolean
,float
,char
),需要使用它们对应的包装类进行存储 -
我们创建的是
ArrayList
的对象,而ArrayList
是Java
已经写好的一个类,在底层做了特殊处理,打印时候不会是地址值,而是集合中存储的数据内容,在展示的时候会拿[]
把所有的数据进行包裹public class list1 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); System.out.println(list); // [] } }
System.exit(int status)这个方法是用来结束当前正在运行中的java虚拟机。
status是非零参数,那么表示是非正常退出。
System.exit(0)是正常退出程序,而System.exit(1)或者说非0表示非正常退出程序。
在一个if-else判断中,如果我们程序是按照我们预想的执行,到最后我们需要停止程序,那么我们使用System.exit(0),而System.exit(1)一般放在catch块中,当捕获到异常,需要停止程序,我们使用System.exit(1)。这个status=1是用来表示这个程序是非正常退出。
十二、面向对象
12.1 static
Static表示静态,是java中的一个修饰符,可以修饰成员方法、成员变量
- 被static修饰的成员变量,叫静态变量
- 被static修饰的成员方法,叫静态方法
12.1.1 静态变量
-
特点:
-
使用static修饰的成员变量、方法,被该类所有对象共享
-
不属于对象,属于类
-
随着类加载而加载,优先于对象存在
package d01.staticDemo1; public class Student { // 姓名,年龄,性别 // 私有变量,只能类内部能进行访问,所以外部访问私有变量,需要在类里创建对应的get和set函数,在类内部访问 private String name; private int age; private String gender; // 公共变量,可以在所有类的实例对象中使用,如: Student s1 = new Student(); s1.t="hhh"; public String t; // 静态变量,不需要书写get set函数,整个类可以共用这个变量的值, - 外部可以直接通过类.变量名的方式进行调用操作如:Student.tAge = 12 static Integer tAge; public Student() { } public Student(int age, String name) { this.age = age; this.name = name; } public Student(String name, int age, String gender) { this.name = name; this.age = age; this.gender = gender; } // 行为 public void study(){ System.out.println(name+"学习"); } public void showInfo(){ System.out.println(name +" "+ age +" "+ gender+"t的数据:"+t); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
// 调用 package d01.staticDemo1; public class StudentTest { public static void main(String[] args) { // 直接调用class中的静态变量 Student.tAge = 34; // 使用无参构造器生成一个对象 Student s1 = new Student(); // 类的对象可以直接对public变量进行直接赋值修改 s1.t = "hhh"; // 对私有变量需要使用class中定义的get和set函数进行取值和赋值 s1.setName("小洪"); s1.setAge(18); s1.setGender("男"); System.out.print(s1.getName() + "++++ "); s1.showInfo(); Student s2 = new Student(18, "zzz"); /* * tAge,是静态变量,在上面赋值过后吗,数据会存在常量池内,所以在其他的对象中调用tAge也是会存在上面赋值的数据的 * t 是公共变量,与s1相同,不需要使用get函数,也可以访问,不需要使用set函数也可以操作 * s2使用的是Student的有参构造器,并根据重载,选择两个参数且类型匹配的构造器,内部对age与name进行赋值 * */ System.out.println(s2.getAge()+" "+s2.getName()+" "+ Student.tAge+" "+s2.t); s2.setGender("女"); System.out.println(s2.t); } }
static
是跟随class的创建而创建的,优于new的对象创建,所以在所有的对象中都能访问到static修饰的变量、方法
-
-
调用方式:
-
类名调用(推荐)
-
对象名调用
// StaticDemo package d01.staticDemo1; public class StaticDemo { public String c_name; // 这个static也是idea生成的?狗屎,肯定是我自己定义的啊那不结了 还不是你卸的doge static Integer c_age; public String getC_name() { return c_name; } public void setC_name(String c_name) { this.c_name = c_name; } }
//调用 package d01.staticDemo1; public class StaticDemoTest { public static void main(String[] args) { // static修饰的变量、方法的吊用方式通过class调用 // 推荐使用class的方式进行调用 StaticDemo.c_age = 18; StaticDemo st1 = new StaticDemo(); System.out.println(StaticDemo.c_age ); st1.c_age = 20; System.out.println(StaticDemo.c_age + "+++"+ st1.c_age); } }
-
总结:
- 静态方法只能访问静态变量和静态方法
- 非静态方法可以访问静态变量和静态方法,也可以访问非静态变量和非静态方法
- 静态方法中没有this关键字
12.1.2 静态方法
-
特点:
- 多用于测试类和工具类中
- Javabean类中很少使用
-
调用方式:
-
类名调用(推荐)
-
对象名调用
可以调用本类的静态方法,也可以调用其他类的静态方法,用类名或者其他类的对象名都可以进项调用
-
12.2 继承
12.2.1 什么是继承?继承有哪些好处?
- 继承是面向对象三大特征之一,可以让类跟类之间产生子父的关系
- 可以把多个子类中重复的代码抽取到父类中,子类可以直接使用,减少代码冗余,提高代码复用性
-
java中提供了一个
extends
关键字,可以让一个类和另一个建立起继承关系public class Student extends Person
-
Student 称为子类(派生类),Person称为父类(基类或超类)
使用继承的好处是:
- 可以把多个子类中重复的代码抽取到父类中,提高代码的复用性
- 子类可以在父类的基础上,增加其他的功能,使子类更强大
- 不能盲目的抽取父类,必须要子类的意义相同,有共同特性,且存在共同成员变量才可以
12.2.2 继承的特点
- 子类可以得到父类的属性和行为,子类可以使用
- 子类可以在父类的基础上进行新增其他功能, 子类变得更加强大
- java中只支持单继承,不支持多继承,但支持多层继承
- 单继承:一个子类只能继承一个父类
- 多层继承:子类A可以继承父类B,父类B还可以继承父类C,以此类推(则C是A的间接父类,B是A的直接父类)
- 每一个类都直接或间接的继承与Object
- 子类只能访问父类中非私有的成员
练习:
四种动物分别有以下行为:
- 布偶猫:吃饭、喝水、抓老鼠
- 狸花猫:吃饭、喝水、抓老鼠
- 哈士奇:吃饭、喝水、看家、拆家
- 泰迪:吃饭、喝水、看家、蹭一蹭
// 动物类
package d01.extendsStudy;
public class Animal {
public void eat() {
System.out.println("吃饭");
}
public void drink() {
System.out.println("喝水");
}
}
// 猫类
package d01.extendsStudy;
public class Cat extends Animal {
public void catchMouse (){
System.out.println("抓老鼠");
}
}
// 狗类
package d01.extendsStudy;
public class Dog extends Animal {
public void lookHome() {
System.out.println("看家");
}
}
//狸花猫
package d01.extendsStudy;
public class LiHua extends Cat{
}
//哈士奇
package d01.extendsStudy;
public class Husky extends Dog{
public void breakHome(){
System.out.println("拆家");
}
}
//测试类
package d01.extendsStudy;
public class Test {
public static void main(String[] args) {
// 创建对象并调用方法
// 创建布偶猫的对象
Ragdoll rd = new Ragdoll();
// 吃饭
rd.eat();
// 喝水
rd.drink();
// 抓老鼠
rd.catchMouse();
}
}
12.2.3 子类能继承父类中的哪些内容
非私有 | private | |
---|---|---|
构造方法 | 不能 | 不能 |
成员变量 | 能 | 能(但无法直接使用,只能通过get,set函数使用) |
成员方法 | 能 | 不能 |
12.2.4 继承中:成员变量的访问特点
-
继承中成员变量访问:就近原则
现在局部找,本类再找,都没有就开始找父级,逐级往上
-
如果出现同名,且还想访问固定未知的变量
package d01.extendsStudy1; public class Variable { public static void main(String[] args) { Zi z = new Zi(); z.test(); } } class Fu { String name = "FuName"; } class Zi extends Fu { String name = "ZiName"; public void test() { String name = "FunName"; System.out.println(name); // FunName System.out.println(this.name); // ZiName System.out.println(super.name); // FuName } }
12.2.5 继承中:成员方法的访问特点
12.2.6 继承中:构造方法的特点
12.2.7 this、super使用总结
12.3 包、final、权限修饰符、代码块
12.4 抽象类
12.5 接口
12.6 多态
12.7 内部类
遗留问题
键盘录入的使用问题
附加:
附1:类的区分
- Javabean类:用于描述一类事物的类。如,Student,Teacher,Dog等,书写Javabean类的时候,要私有化成员变量, 书写孔灿构造方法(可不写),书写全部参数的构造方法,针对每一个私有化的成员变量提供对应的get,set方法,如果有额外的行为,还需要写对应的成员方法。
- 测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的入口
- 工具类:不是用来描述一类事物的,而是帮我们做一些事情的类
- 类名要见名知意
- 私有化构造方法(不允许外界通过工具类new一个对象出来,因为工具类主要提供工具方法,而不是创建对象)
- 方法定义为静态方法(方便外界环境在不能new的情况下依旧调用工具类里的方法)
已经看到p121