Java笔记
一、数据类型
1.基本数据类型
1.整数类型
- byte
- short
- int
- long 建议使用大写L
2.浮点类型
- float
- 有限、离散、舍入误差、大约、接近但不等于
- double
- 避免用浮点类型比较数值
- BigDecimal 数学工具类
3.字符类型
- char占2个字节 对应Unicode码
- 转义字符
4.布尔类型
- boolean
- 只占一位,而且只有两个值true和false,常用语判断
5.类型转换
-
低-------------->高
- byte, short, char–>int–>long–>float–>double
-
运算中,不同类型的数据先转化为同一类型,然后进行运算。
1.强制类型转换 高 -->低 int i = 128; byte b = (byte) i;//导致内存溢出 2.自动类型转换 低 -->高 int i = 128; double d = i;
-
不能对布尔值进行转换。
-
不能把对象类型转换为不相干的类型。
-
在把高容量转换到低容量的时候,强制转换。
-
转换的时候可能存在内存溢出,或者精度问题。
2.变量类型
- Java时一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
- 注意事项
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束。
- 变量作用域
- 类变量 1.加关键字static;2.从属于类,随着类存在或消亡
- 实例变量 1.从属于对象;2.未初始化值,会给默认值(0、0.0、null、false)
- 局部变量 1.必须声明和初始化值;2.作用域在方法里面
3.常量类型
-
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
-
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
-
常量名一般使用大写字符。
final double PI = 3.14;
4.变量的命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则 ex:monthSalary lastName
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线 ex:MAX_VALUE
- 类名:首字母大写和驼峰原则 ex:Man, GoodMan
- 方法名:首字母小写和驼峰原则 ex:run(), testRun()
5.运算符
-
算术运算符 :+,-,*,/,%,++,–
面试题 int a = 10; int b = 20; System.out.println("" + a + b);//输出1020 System.out.println(a + b + "");//输出30
-
赋值运算符:=
-
关系运算符:>,<,>=,<=,==,!=,instanceof
-
逻辑运算符:&&,||,!
-
位运算符:&,|,^,>>(左移就是 /2),<< (右移就是 *2),>>> (了解)
面试题 计算机最快方式算出2*8=16 System.out.println(2<<3);//输出16
-
条件运算符:? : (一真大师) 必须掌握
-
扩展赋值运算符:+=,-=,*=,/=
-
Math类
-
很多运算我们会使用工具类来操作
6.包机制
- 包的本质就是文件夹。(防止重名)
- 一般利用公司域名倒置作为包名。ex:com.baidu.www
- 为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用 import 语句完成。
7.JavaDoc 生成文档
- 参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
- 在文件执行Dos命令窗口,javadoc -encoding UTF-8 -charset UTF-8 类名.java
- 用IDEA生成JavaDoc文档:选中要生成的包–>Tools–>Generate JavaDoc–>Output directory(路径)–>locale(zh_CN)–>Other command line arguments(-encoding utf-8 -charset utf-8)。
引用数据类型
二、流程控制
1.Scanner对象
-
java.util.Scanner 获取用户的输入。
-
基本语法:
Scanner scanner = new Scanner(System.in)
-
通过Scanner类的Next()和nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()和hasnextLine()判断是否还有输入的数据。
- next()方法一定要读取到有效字符后才可以结束输入;对输入有效字符前遇到的空白,该方法会自动将其去掉;不能等得到带有空格的字符串。
- nextLine()方法以输入回车之前的所有字符,可以获得空白。
-
此外通过Scanner还可以接收到整数nextInt(),浮点数nextDouble,等其他方法。
-
凡是IO流使用完都要关掉。
scanner.close();
2.顺序结构
- Java的基本结构就是顺序结构,除非特别指明,否则按照顺序一句一句执行。
- 顺序结构是最简单的算法结构。
- 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个以此执行的处理步骤组成的,它是任何一个算法都离开的一种基本算法结构。
3.选择结构
-
if单选择结构
过关斩将: if(布尔表达式) { //如果布尔表达式为true将执行语句 }
-
if双选择结构
if(布尔表达式) { //如果布尔表达式为true将执行语句 } else { //如果布尔表达式为false将执行语句 }
-
if多选择结构
if(布尔表达式) { //如果布尔表达式为true将执行语句 } else if() { //如果布尔表达式为true将执行语句 } else if() { //如果布尔表达式为true将执行语句 } else if() { //如果布尔表达式为true将执行语句 } else { //如果布尔表达式为false将执行语句 }
-
嵌套的if结构
if(布尔表达式) { //如果布尔表达式为true将执行语句 if(布尔表达式) { //如果布尔表达式为true将执行语句 } }
-
switch多选择结构
switch(expression) {//int char String case value: //语句 break; case value: //语句 break; //可以有多个case语句 default: //语句 }
4.循环结构
-
while循环
while(布尔表达式) { //循环内容 } while(true) { //死循环,尽量不要使用 }
- 只要布尔表达式为true,循环就会一直执行下去。
- 我们大多数情况会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
-
do…while循环
do { //语句 } while(布尔表达式);
-
while和do…while的区别
- while先判断后执行,do…while是先执行后判断。
- do…while总是爆炸循环体会被至少执行一次!这是主要区别。
-
for循环
-
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
-
for循环执行的次数是在执行前就确定的。
-
for(初始化; 布尔表达式; 迭代) { //代码语句 } for(; ; 迭代) {//死循环 //代码语句 } 练习题:打印九九乘法表 for (int i = 1; i < 9; i++) { for (int j = 1; j < i; j++) { System.out.print(j + "*" + i + "=" + (i * j) + "\t"); } System.out.println();//换行 }
-
-
增强for循环
- 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块中,其值与此时数组元素的值是否相等。
- 表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
- 主要用于数组和集合。
for(声明语句 : 表达式) { //代码句子 }
-
break、continue
- break语句跳出当前循环或选择语句(while和switch),强制退出循环,会继续执行下面语句。
- continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
三、方法
1.何谓方法
- Java方法是语句的集合,它们在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含类或对象中
- 方法在程序中被创建,在其他地方被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。一个方法只完成1个功能,这样利于我们后期的扩展。
- System.out.println(); 类.out对象.println方法
2.方法的定义及调用
- Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含一下语法:
- 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:这是可选的,告诉编译器如何调用该方法,定义了该方法的访问类型。
- 返回值类型:方法可能有返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,关键字是void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:
- 形式参数:在方法被调用时用于接收外接输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:包含具体的语句,定义该方法的功能。
- 方法的调用
- 调用方法:对象名.方法名(实参列表)
- Java支持两种调用方法的方式,根据方法是返回值来选择。
- 当方法返回一个值的时候,方法调用通常被当做一个值。例如:int larger = max(30, 40);
- 如果方法返回值是void,方法调用一定是一条语句。
- System.out.println(“hello,java!”);
3.方法重载
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
- 方法的重载规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
- 实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译报错。
4.命令行传参
- 有时候你希望运行一个程序时候再传递给他消息。这要靠传递命令行参数给main()函数实现。
5.可变参数
- JDK1.5开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(…)。
- 一个方法中只能指定一个可变参数,她必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
6.递归
- A方法调用B方法,我们很容易理解!
- 递归就是:A方法调用A方法!就是自己调用自己
- 递归的能力在于用有限的语句来定义对象的无限集合。
- 递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
四、数组
1.数组概述
- 数组是相同类型数据的有序集合。
- 数组描述的是相同类型的若干数据,按照一定的先后次序排列组合而成。
- 其中,每一个数据乘作一个数组元素,每个数组元素可以通过一个下标来访问他们。下标从0开始。
2.数组声明创建
-
首先声明数组变量,才能在程序中使用数组。
dataType[] arrayRefVar;//首选方法 dataType arrayRefVar[];//不建议使用
-
Java语言使用new操作符来创建数组。
dataType[] arrayRefVar = new dataType[arraySize]
-
数组的元素是通过索引访问的,数组索引从0开始。
arrays.length
-
获取数组长度。
-
静态初始化
int[] a = {1, 2, 3}; Man[] mans = {new Man(1, 1), new Man(2, 2)};//引用类型
-
动态初始化
int[] a = new int[2]; a[0] = 1; a[1] = 2;
-
数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素被按照实例变量同样的方式被隐式初始化。
-
数组的长度是确定的。
-
数组的元素必须是相同类型的,不允许出现混合类型。
-
数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组对象本身是在堆中的。
-
下标的合法区间[0,length-1]。
- ArrayIndexOutOfBoundsException 数组下标越界异常!
3.数组使用
-
For-Each循环 适合打印输出 遍历元素。
-
数组作方法入参
public class ArrayDemo { public static void main(String[] args) { int[] arrays = {1, 2, 3, 4, 5}; int[] reverse = reverse(arrays); //调用方法reverse printArray(reverse); //调用方法printArray } //反转数组方法 pulic static int[] reverse(int[] arrays) { int[] result = new int[arrays.length]; //反转操作 for(int i = 0, j = result.length - 1; i < arrays.length; i++, j--) { result[j] = arrays[i]; } return result; } //打印数组方法 public static void printArray(int[] arrays) { for(int i = 0; i < arrays.length; i++) { System.out.print(arrays[i] + "\t"); } } }
-
数组作返回值
4.多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一位数组,其每一个元素都是一个一维数组。
-
二维数组
int[][] a = new int[2][5]; //可以看成是2行5列的数组 int[][] array = {{1, 2}, {3, 4}, {5, 6}}; array[0][0] = 1; array[0][1] = 2; array[1][0] = 3; array.length = 3; array[0].length = 2; //打印输出数组 for(int i = 0; i < array.length; i++) { for(int j = 0; j < array[i].length; j++) { System.out.println(array[i][j]); } }
5.Arrays类
-
数组的工具类java.util.Arrays
-
可查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用。
Arrays.toString(array);//该方法打印数组 Arrays.sort(array);//该方法升序数组
6.冒泡排序
public static int[] sort(int[] array){
int temp = 0;
for(int i = 0; i< array.length -1; i++) {
for(int j = 0; j<array.length - 1 -i; j++) {
if(array[j + 1] < array[j]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
return array;
}
7.稀疏数组
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 1;
System.out.println("输出原始的数组:")
for(int[] ints : array1) {
for(int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.print();
//转换为稀疏数组
int sum = 0;
for(int i = 0; i < 11; i++) {
for(int j = 0; i < 11; j++) {
if(array[i][j] != 0) {
sum++;
}
}
}
//创建稀疏数组
int[][] array2 = new int[sum+1][3];
array[0][0] = 11;
array[0][1] = 11;
array[0][2] = sum;
//遍历二维数组将值存入到稀疏数组里
int count = 0;
for(int i = 0; i < array1.length; i++) {
for(int j = 0; i < array[i].length; j++) {
if(array[i][j] != 0) {
count++;
array2[count][0] = i;//保存行
array2[count][1] = j;//保存列
array2[count][2] = array[i][j];//保存值
}
}
}
//输出稀疏数组
for(int i = 0; i < array2.length; i++) {
System.out.print(aray2[i][0] + "\t" + aray2[i][1] + "\t" +aray2[i][2]);
}
System.out.print("还原数组");
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for(int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
//打印还原数组
for(int[] ints : array1) {
for(int anInt : ints) {
System.out.print(anInt + "\t");
}
}
五、面向对象(OOP)
1.初识面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么…
- 适合处理一些较为简单的问题
- 面向对象思想
- 物以类聚,分类的思维模式,
- 适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是具体到微观操作,仍然需要面向过程的思路去处理。
- 面向对象(Object-Oriented Programming,OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
- 三大特性:
- 封装
- 继承
- 多态
2.方法回顾和加深
- 方法的定义
- 修饰符
- 返回类型
- break:跳出switch,结束循环和return的区别
- 方法名
- 参数列表
- 异常抛出
- 方法的调用
- 静态方法
- 非静态方法
- 形参和实参
- 值传递和引用传递
- this关键字
3.对象的创建分析
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
- 对象是抽象概念的具体实例。
- 一个项目应该只存在一个main方法。
- 使用new关键字创建对象。
- 类中的构造器也称构造方法,是在进行创建对象的时候必须要调用的。并且构造器有一下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- new 本质在调用构造方法
- 初始化对象的值
- 定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
4.面向对象三大特性
-
封装
- 该露的露,该藏的藏。“高内聚,低耦合”。
- 属性私有,get/set方法。
- 提高程序安全性,保护数据。
- 隐藏代码细节。
- 统一接口。
- 提高系统可维护性。
-
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extands的意思“扩展”,子类是父类的扩展。
- Java中只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承是 is a 的关系。
- super关键字
- super()调用父类的构造方法,必须在构造方法的第一个。
- super必须只能出现在子类的方法或者构造方法中。
- super和this不能同时调用构造方法。
- this关键字
- 表示本身调用者这个对象。
- 没有继承也可以使用。
- 本类的构造方法。
- 方法的重写
- 需要有继承关系,子类重写父类的方法。
- 方法名必须相同,参数列表必须相同,修饰符范围可以扩大不能缩小。(public>protected>default>private)
- 抛出的异常范围可以缩小但不能扩大。
-
多态
- 是方法的多态。
- 父类和子类存在关系,类型转换异常(ClassCastException)
- 继承关系,方法需要重写,父类引用指向子类对象!
- static方法不能重写,final修饰常量;private私有方法也不能重写。
- instanceof关键字。
- 向上转型:把子类转换成父类。
- 向下转型:把父类转换成子类,强制转换。
- final修饰的类就不能被继承。
-
代码块
//静态导入包 import static java.lang.Math.reandom; { System.out.println("匿名代码块");//输出顺序2 } static { System.out.println("匿名代码块");//输出顺序1,只执行一次 } pulic Person() { System.out.println("构造方法");//输出顺序3 }
5.抽象类和接口
- abstract修饰符的类;
- 不能new这个抽象类,只能靠子类去实现它。
- 抽象类可以没有抽象方法,抽象方法必须在抽象类中。
- 抽象类可以提高开发效率。
- 接口就是规范,接口的本质是契约,关键字interface。
- 接口中的所有定义其实都是抽象的public abstract(可不写);
- 一个类可以实现多个接口,关键字implements;
- 实现了接口的类,就必须重写接口中的方法;
- 定义的属性都是常量,public static final;
6.内部类
-
成员内部类
public class Outer { private int id; public void out() { System.out.println("这是外部类的方法"); } public class Inner { public void in() { System.out.println("这是内部类的方法"); } } }
- 内部类可以直接访问外部类方法和属性,不需要创建外部类的对象。
-
静态内部类
public class Outer { private int id; public void out() { System.out.println("这是外部类的方法"); } public static class Inner { public void in() { System.out.println("这是静态内部类的方法"); } } }
-
局部内部类
public class Outer { public void method() { class Inner {//局部内部类 public void in() { } } } }
-
匿名内部类
public class Outer { public static void main(String[] args) { new Apple.eat(); UserServie userService = new UserService() {//匿名内部类 @Override pubblic void hello() { } }; } } class Apple { public void eat() { System.out.println("吃苹果"); } } interface UserService { void hello(); }
六、异常
1.什么是异常
- 软件程序在运行过程中,可能遇到异常问题,Exception;
2.异常体系结构
-
检查性异常。
-
运行时异常。
-
错误error,致命。
-
Java把异常当做对象来处理,并定义一个java.lang.Throwable作为异常的超类。
-
在Java API 中定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Udbt5qs5-1685532296245)(C:\Users\周洪杰\AppData\Roaming\Typora\typora-user-images\image-20230301153541359.png)]
3.Java异常处理机制
-
抛出异常
- throw关键字,在代码块里使用,不管程序是否有异常,执行到throw语句一定会抛出一个异常。
- throws关键字,使用在方法上。
-
捕获异常
int a = 1; int b = 0; //选中捕获代码,快捷键ctrl + alt + t try {//监控区域 System.out.println(a / b); } catch(ArithmeticException e) {//想要捕获的异常类型 System.out.println("程序出现异常"); } finally {//善后工作,始终会运行finally }
4.自定义异常
-
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
-
创建自定义异常类;
-
在方法中通过throw关键字抛出异常对象。
-
如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
-
在出现异常方法的调用者中捕获并处理异常。
public class MyException extands Exception { //传递数字 > 10 就抛出异常 private int detail; public MyException(int a) { this.detail = a; } //打印异常信息 @Override public String toString() { return "MyException"{ + "detail=" + detail + '}'; } } public class Test { static void test(int a) { System.out.println("传递参数为:" + a); if(a > 10) { throw new MyException(a); } System.out.println("OK"); } public static void main(String[] args) { try { test(1); } catch(MyException e) { System.out.println("MyException-->" + e); } } }
5.总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切记只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句去释放占用的资源(IO流、Scanner、)
JDBC API
1.DriverManager 驱动管理类
- getConnection(url,user,pwd) 获取到连接
2.Connection接口
- create Statement 创建Statement 对象
- prepaerdStatement(sql) 生成预处理对象
3. Statement接口
- executeUpdate(sql) 执行dml语句,返回影响的行数
- executeQuery(sql) 执行查询,返回ResultSet对象
- execute(sql) 执行任意的sql,返回布尔值
- Statement存在Sql注入问题
- 输入用户名为 1‘ or
- 输入万能密码为 or ‘1’= '1
- PreparedStatement【预处理】
- 不再使用 + 拼接sql语句,减少语法错误
- 有效地解决了Sql注入问题
- 大大减少了编译次数,效率较高
4.PreparedStatement接口
- executeUpdate() 执行dml语句
- executeQuery() 执行查询,返回ResultSet对象
- execute() 执行任意sql,返回布尔值
- setString(index,value) 解决sql注入
- setObject(index,value)
5.ResultSet(结果集)
- next() 表示向下移动一行,如果没有下一行返回false
- previous() 向上移动一行,如果没有上一行返回false
- getXxx(index or 列名) 可以通过列名得到数据库的数据
- getObject(index or 列名) 返回object对象
反编译
- 可以直接将class文件丢入到IDEA里面
System.out.println(); //会换一行输出
System.out.print(); //不会会换一行输出