java特性
- 面向对象(oop)
- 健壮,Java的强类型机制、异常处理、垃圾的自动手机等是java程序健壮性的重要保证
- 跨平台 [即:一个编译好的class文件可以在等多个系统下运行,这种特性称为跨平台]
- 解释性
解释性语言:JavaScript,PHP,Java 编译性语言:c/c++
区别是:解释性语言,编译后的代码,不能直接被机器执行,需要解释器来执行,编译性语言,编译后的代码,可以直接被机器执行,c/c++
Java运行机制及运行过程
- Java核心机制-Java虚拟机 [JVM java virtual machine]
基本介绍:
1)JVM是一个虚拟的计算机,具有指令集并使用不同的存储空间。负责执行指令,管理数据、内存、寄存器、包含在JDK中
2)对于不同平台,有不同的虚拟机
3)Java虚拟机制屏蔽了底层运行平台的差别,实现了“一次编译,到处执行”
Test.java -(编译 javac)——> Test.class -(运行 Java)——> JVM for LInux
——> JVM for Windows
——> JVM for Mac
什么是JDK JRE
-
JDK 基本介绍
- JDK的全称是(Java Development Kit Java开发工具包)
JDK = JRE + Java的开发功能工具[java javac javadoc javap等]
2.JDK是提供给Java开发人员使用的,其中包含了Java的开发工具,也包含了JRE
所以安装了JDK,就不用再单独安装JRE了
-
JRE基本介绍
1.JRE(Java Runtime Environment Java 运行环境)
JRE = JVM + Java的核心类库[类]
2.包括Java虚拟机(JVM Java Virtual Machine) 和Java程序所需的核心类库等,
如果想要运行一个开发好的Java程序,计算机只需要安装JRE即可
Java开发细节
- 编译后,每个类都对应一个.class
- 如果原文件包含一个public类,则文件名必须按照该类名命名
- 一个源文件最多只能有一个public类。其他类的个数不限,也可以将main方法写在非public类中,然后指定运行非public类,这样入口就是非public的主方法
Java基础
Java转义字符
-
\t: 一个制表位,实现对其的方法
-
\n: 换行符
-
\\ 一个\
-
\" 一个“sout
-
\’ 一个‘
-
\r 一个回车 System.out.printlin(“hello world”)
基本数据类型和String类型的转换
-
介绍:
在程序开发中,我们经常需要将基本数据类型转成String类型。或者将String类型转成基本数据类型
-
基本类型转String类型:
-
语法:将基本类型的值+ “” 即可
public class Main {
public static void main(String[] args) {
int n1 = 100;
float n2 = 1.1f;
double n3 = 3.4;
boolean b1 = true;
String str1 = n1 + "";
String str2 = n2 + "";
String str3 = n3 + "";
String str4 = b1 + "";
System.out.println(str1 + " " + str2 + " " + str3 + " " + str4);
}
}
-
-
String类型转基本数据类型
语法:通过基本类型的包装类调用parseXX的方法即可
//String -> 对应的基本数据类型
//使用 基本数据类型对应的包装类 的相应方法 得到基本数据类型
String s5 = "123";
int num1 = Integer.parseInt(s5);
//怎么将字符串转成字符 -> 含义时将字符串的第一个字符得到 System.out.println(s5.charAt(0));
三元运算符
- 基本语法:
条件表达式 ? 表达式1:表达式2;
-
运算规则
1.如果条件表达式为true,运算结果是表达式1;
2.如果条件表达式为false,运算结果是表达式2;
public class TernaryOperator { public static void main(String[] args) { //三元运算符使用 int a = 10; int b = 99; int result = a > b ? a++ : b--; System.out.println(b); } }
键盘输入
-
介绍:
在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取,需要一个扫描器,就是Scanner
-
步骤:
1)导入该类的所在包
2)创建该类对象(声明变量)
3)调用里面的功能
public class Input {
public static void main(String[] args) {
// 演示接收用户的输入
//步骤
//Scanner类 表示 简单文本扫描器 在java.util包
//1.引入/导入 Scanner类所在的包
//2.创建 Scanner 对象
Scanner scanner = new Scanner(System.in);
//3.接收用户的输入 使用 相关的方法
System.out.println("请输入用户的名字");
//当程序执行到 next方法时 会等待用户输入
String name = scanner.next(); //接收用户输入字符串
System.out.println("请输入用户的年龄");
int age = scanner.nextInt(); //接收用户输入int
System.out.println("请输入用户的薪水");
double sal = scanner.nextDouble(); //接收用户输入double
System.out.println("人的信息如下:");
System.out.println("name=" + name + " age=" + age + " sal=" + sal);
}
}
控制结构
多重循环控制
-
经典的打印金字塔
使用for循环完成以下案例
请编写一个程序,可以接收一个整数,表示层数(totalLeval),打印出金字塔
[先繁后简,先死后活]
public class Stars {
public static void main(String[] args) {
int totalLevel = 10; //层数
for (int i = 1; i <= totalLevel; i++) { //i 表示层数
//在输出* 前还要添加空格
for (int k = 1; k <= totalLevel - i; k ++) {
System.out.print(" ");
}
for (int j = 1; j <= 2 * i - 1; j++) { //j 表示打印每层*的个数
//当前行的第一个位置时*,最后一个位置也是*,最后一层全部*
if (j == 1 || j == 2 * i - 1 || i == totalLevel){
System.out.print("*");
}else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
- 化繁为简:即将复杂的需求,拆解为简单的需求,逐步完成
- 先死后活:先考虑固定的值,然后转成可以灵活变化的值
数组
数组的使用
-
使用方法1 - 动态初始化
-
数组的定义
- 数据类型[] 数组名 = new 数组类型[大小];
- 数据类型 数组名[] = new 数组类型[大小];
- int a[] = new int[5]
-
数组的引用/使用/获取
- 数组名[下标/索引/index]
- a[2] 数组的下标从0开始
- 数组名[下标/索引/index]
-
-
使用方法2 - 动态初始化
-
先声明数组
-
没分配内存空间 null
- 语法:数据类型 数组名[]; int a[];
- 也可以:数据类型[] 数组名; int[] a;
-
-
创建数组
-> 分配内存空间,可以存放数据
- 语法:数组名 = new 数据类型[大小] a = new int[6];
-
-
使用方法3 - 静态初始化
-
初始化数组
- 语法:数据类型 数组名[] = {元素值,元素值…}
-
数组使用注意事项
- 数组是多个相同类型数据的组合,实现对这些数据的统一管理
- 数组中的元素可以是任意数据类型,包括基本数据类型和引用类型,但是不能混用
- 数组创建后,如果没有赋值,有默认值
- int 0
- short 0
- byte 0
- long 0
- float 0.0
- double 0.0
- char \u0000
- boolean false
- String null
- 使用数组的步骤
- 1.声明数组并开辟空间
- 2.给数组各个元素赋值
- 3.使用数组
- 数组的下标是从0开始的
- 数组下标必须在指定范围内使用,否则报:下标越界异常 ArrayIndexOutOfBoundsException
- 数组属引用类型,数组型数据是对象(object)
数组赋值机制
1.基本数据类型赋值,这个值就是具体的数据,而且相互不影响
2.数组在默认情况下是引用传递,赋的值是地址
public class Eg5_ArrayAssign {
public static void main(String[] args) {
//基本数据类型赋值,赋值方式为值拷贝
//n2的变化,不会影响n1的值
int n1 = 10;
int n2 = n1;
n2 = 80;
System.out.println("n1=" + n1);//10
System.out.println("n2=" + n2);//80
//数组在某人条件下是引用传递,赋的值是地址,赋值方式为引用传递/地址拷贝
//是一个地址
int[] arr1 = {1,2,3};
// 数组的赋值,赋的值是地址
int[] arr2 = arr1; //把arr1赋给 arr2
arr2[0] = 10;
//看看arr1的值
System.out.println("=====arr1的元素=====");
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
} //10 2 3
//看看arr2的值
System.out.println("=====arr2的元素=====");
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
} //10 2 3
}
}
数组拷贝
public class Eg6_ArrayCopy {
public static void main(String[] args) {
//将int[] arr1 = {10,20,30}; 拷贝到arr2数组,要求数据空间是独立的
int[] arr1 = {10,20,30};
//创建一个新的数组,开辟新的数据空间
//大小 arr1.length
int[] arr2 = new int[arr1.length];
//遍历 arr1,把每个元素拷贝到对应的位置
for (int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
//修改 arr2
arr2[0] = 100;
//输出arr1
System.out.println("=====arr1的元素=====");
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
} //10 2 3
//输出arr2
System.out.println("=====arr2的元素=====");
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
} //100 2 3
}
}
数组反转
要求:把数组的元素内容反转
public class Eg7_ArrayReverse {
public static void main(String[] args) {
//定义数组
int[] arr = {11, 22, 33, 44, 55, 66};
//把arr[0] 和 arr[5] 进行交换
//把arr[1] 和 arr[4] 进行交换
//把arr[2] 和 arr[3] 进行交换
//共交换 3次 = arr.length / 2
//每次交换时,对应的下标 是 arr[i] 和 arr[arr.length - 1 -i]
int temp = 0;
for (int i = 0; i < arr.length / 2; i++) {
temp = arr[arr.length - 1 - i];;
arr[arr.length - 1 - i] = arr[i]; //保存
arr[i] = temp;
}
}
}
排序介绍
排序是将多个数据,依指定的顺序进行排列的过程
排序的分类
-
内部排序法:
指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、排除式排序法和插入式排序法)
-
外部排序法:
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)
冒泡排序法
基本思想:
通过对打排序序列从后向前(从下表较大的元素开始),一次比较相邻元素的值,若发现逆序则交换,使值较大的数逐渐从前移向后部,就像水底下的气泡一样逐渐向上冒
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SYJ7gkQJ-1682860783638)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230426181842058.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8x8FOWLa-1682860783639)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230426182342925.png)]
public class Eg9_BubbleSort {
public static void main(String[] args) {
//化繁为简 先死后活
int[] arr = {24, 69, 80, 57, 13, -1, 849};
int temp = 0; //用于辅助交换的变量
//将多轮排序使用外层循环包括起来即可
for (int i = 0; i < arr.length-1; i++) { //外层循环4次
for (int j = 0; j < arr.length - 1 - i; j++) { //4次交换
//如果前面的数 > 后面的数,就交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("===第" + (i + 1) +"轮===");
for (int k : arr) {
System.out.print(k + "\t");
}
System.out.println();
}
}
}
查找
-
介绍
在Java中,常用的查找有两种:
- 顺序查找
import java.util.Scanner; public class SeqSearch { public static void main(String[] args) { /* 思路分析 1.定义一个字符串数组 2.接收用户输入,遍历数组,逐一比较,如果有,则提示信息,并退出 */ //定义一个字符串数组 String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"}; Scanner scanner = new Scanner(System.in); System.out.println("请输入名字"); String findName = scanner.next(); //遍历数组,逐一比较,如果有,则提示信息,并退出 int index = -1; for (int i = 0; i < names.length; i++) { //比较 字符串比价 equals, 如果找到名字就是当前元素 if (findName.equals(names[i])) { System.out.println("恭喜你找到" + findName); System.out.println("下标为" + i); //把i 保存到index index = i; break;//退出 } } if (index == -1) { //没有找到 System.out.println("sorry, 没有找到" + findName); } } }
- 二分查找
二维数组介绍
-
注意点
- 二维数组的元素的个数:arr.length
- 二维数组的每个一维数组的长度:arr[i].length
- 二维数组的每一个元素都是一维数组, 所以如果需要得到每个一维数组的值还需要再次遍历
-
使用方法1:动态初始化
-
语法:类型[][] 数组名 = new 类型[大小][大小]
- int a[][] = new int[2][3]
-
二维数组在内存中的存在形式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cIwjPywd-1682860783640)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230426201116673.png)]
-
-
使用方式2:动态初始化
- 先声明:类型 数组名[][];
-
再定义(开辟空间) 数组名 = new 类型[大小][大小]
- 赋值(有默认值,比如int类型的就是0)
-
使用方法3: 列数不确定
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXLVQ3pC-1682860783640)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230426203133149.png)]
public class Test {
public static void main(String[] args) {
/*
看一个需求:动态创建下面二维数组,并输出
i = 0: 1
i = 1: 2 2
i = 2: 3 3 3
一个有三个一维数组,每一个一维数组的元素是不一样的
*/
int[][] arr = new int[3][]; //创建 二维数组,但是只是确定一维数组的个数,但是每个一维数组还没有开空间 new
for (int i =0; i < arr.length; i++) { //遍历arr的每个一维数组
//给每个一维数组开空间
//如果没有给一维数组 new,那么 arr[i]就是null
arr[i] = new int[i + 1];
//遍历一维数组,并给一维数组的每个元素赋值
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = i + 1;//赋值
}
}
//遍历arr输出
for (int i = 0; i < arr.length; i++) {
//输出arr的每个一维数组
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
- 使用方法4:静态初始化
- 定义 类型 数组名[][] = {{值1,值2 …}, {值1, 值2…}, {值1, 值2…}}
- 使用即可 [固定方式访问]
杨辉三角
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MEcnOfK8-1682860783644)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230426205030168.png)]
public class YangHui {
public static void main(String[] args) {
int[][] yangHui = new int[10][];
for (int i = 0; i < yangHui.length; i++) { //遍历yangHui的每个元素
//给每个一维数组(行) 开空间
yangHui[i] = new int[i+1];
//给每个一维数组(行) 赋值
for (int j = 0; j < yangHui[i].length; j++) {
if (j == 0 || j == yangHui[i].length -1) {
yangHui[i][j] = 1;
} else { //中间的元素
yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
}
}
}
//输出杨辉三角
for (int i = 0; i < yangHui.length; i++) {
for (int j = 0; j < yangHui[i].length; j++) {
System.out.print(yangHui[i][j] + "\t");
}
System.out.println();
}
}
}
二维数组使用细节和注意事项
-
一维数组的声明方式有:
int[] x 或者 int x[]
-
二维数组的声明方式有
int[][] y 或者 int[]y[] 或者 int y[][]
-
三维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。比如:map[][] 是一个二维数组
int map[][] = {{1,2}, {3,4,5}}
由map[0]是一个含有两个元素的一维数组,map[] 是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组
类与对象
-
类是抽象的,概念的,代表一类事物,比如人类、猫类、、
-
对象是具体的,实际的,代表一个具体事物,即 是实例
-
类是对象的模板,对象是类的一个个体,对应一个实例
-
对象在内存中存在形式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zxWcPQq3-1682860783644)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230427120515141.png)]
属性和成员变量
基本介绍
-
从概念或叫法上来看:成员变量 = 属性 = field字段 (即 成员变量是用来表示属性的)
-
属性是类的一个组成部分,一般是基本数据类型,也可以是应用类型 (对象,数组)
注意事项和细节说明
- 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名 ;
- 属性的定义类型可以为任意类型,包含基本类型或引用类型
- 属性如果不赋值,有默认值,规则和数组一致
如何创建对象
-
先声明再创建
Cat cat; //声明对象 cat
cat = new Cat(); //创建
-
直接创建
Cat cat = new Cat();
如何访问属性
- 对象名.属性名;
类与对象的内存分配机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9arAnK6g-1682860783645)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230427131450223.png)]
-
Java内存的结构分析
-
- 栈:一般存放基本数据类型(局部变量)
- 堆:存放对象 (Cat cat,数组等)
- 方法区:常量池(常量,比如字符串),类加载信息
- 示意图
-
-
Java创建对象的流程简单分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGhAmB0m-1682860783645)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230427131929825.png)]
-
- 先加载Person类信息(属性或方法信息,只会加载一次)
- 在堆中分配空间,进行默认初始化(看规则)
- 把地址赋给 p,p就指向对象
- 进行指定初始化
-
成员方法
方法的调用机制原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jQenAayM-1682860783645)(C:\Users\输入你的姓名\AppData\Roaming\Typora\typora-user-images\image-20230427143145616.png)]
方法调用小结:
- 当程序执行到方法时,就会开辟一个独立的空间(栈空间)
- 当方法执行完毕,或者执行到return语句时,就会返回
- 返回到调用方法的地方
- 返回后,继续执行方法后面的代码
- 当main方法(栈)执行完毕,整个程序退出
为什么需要成员方法
-
成员方法的好处
- 提高代码的复用性
- 可以将实现的细节封装起来,然后供其他用户来调用
-
成员方法的定义
访问修饰符 返回数据类型 方法名 (形参列表…) {
语句
return 返回值;
}
- 形参列表:表示成员方法输入 cal(int n), getSum(int num1, int num2)
- 返回数据类型: 表示成员方法输出,void 表示没有返回值
- 方法主体:表示为了实现某一功能代码块
- return语句不是必须的
注意事项
-
方法修饰符
如 果不写默认访问,(public, protected, private, 默认)
-
返回数据类型
- 一个方法最多有一个返回值 [如何返回多个数据?返回数组]
- 返回类型可以为任意类型,包含基本类型(数组、对象)
- 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值; 而且要求返回值类型必须和return的值类型一致或兼容
- 如果方法是void,则方法体中可以没有return语句,或者只写 return
-
方法名
遵循驼峰命名法,最好见名知意,表达出该功能的意思即可
-
方法体
里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能再定义方法,即:方法不能嵌套定义
-
方法调用细节说明
- 同一个类中的方法调用:直接调用即可
- 跨类中方法A类调用方法B类:需要通过对象名调用。
- 跨类的方法调用和方法的访问修饰符相关
-
成员方法传参机制
-
基本数据类型的传参机制
基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参!
-
引用数据类型的传参机制
引用类型传递的地址(传递的也是值,但是值是地址),可以通过形参影响实参
-
方法递归调用
-
基本介绍:
递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂问题,同时可以让代码变得简介
-
递归重要规则
-
执行一个方法时,就创建一个新的受保护的对立空间(栈空间)
-
方法的局部变量是独立的,不会相互影响,比如n变量
-
如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据
-
递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError
-
当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者退出时,该方法也就执行完毕
-