#JAVASE笔记
面向过程
简单Dos命令
#查看目录下的所有文件 dir
#切换目录 cd change directory
#文件操作
创建文件夹:md 文件名
移除文件:rd 文件名
创建文件:cd> 文件名
删除文件:del 文件名
#查看java安装版本 java -version
Hello Woeld
public class Hello{
public static void main(String[] args){
System.out.print("Hello,World!");
}
}
Dos命令:
D:\java学习\code\javac Hello.java
D:\java学习\code\java Hello
Hello,World!
package com.oop.Demo02;
public class Application {
public static void main(String[] args) {
//类是抽象的需要实例化的;
//类实例化后会返回一个自己的对象;
//Jeremy,baba 对象就是Student类的具体实例。
Student jeremy = new Student();
Student baba = new Student();
jeremy.name="jeremy";
jeremy.age=21;
System.out.println(jeremy.name);
System.out.println(jeremy.age);
baba.name="baba";
baba.age=21;
System.out.println(baba.name);
System.out.println(baba.age);
}
}
注意事项:
**java 大小写敏感 **
文件名和类名必须保持一致
java程序运行机制:(编译型和解释型)
源程序(*.java文件)—>|java编译器|—>字节码( * . class文件)
—>|类装载器|—>|字节码校验器|(检验代码是否有错)—>|解释器|—>|操作系统平台|
java快捷方式
psvm:main()方法
sout:输出
Java学习
IDEA 快捷键
Ctrl +D:复制当前行到下一行
Ctrl +/:行注释
Ctrl +Shift +/:块注释
Ctrl+Alt+L:格式化代码
Tab : 代码整体后移
Alt + Insert : 快捷生成有参无参
Ctrl+H : 树结构
Ctrl +Alt + T:快速选择语句
注释
单行注释:// (两个斜杠)
多行注释:/* 文字 */
文档注释:/*
*(每行前面都要加)
*/
//有趣的代码注释
标识符
关键字
JAVA所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符
命名规范
1.所有标识符以字母、美元符号$、下划线_ 、开始。
2.首字母之后可以是字母、美元符号$、下划线_ 或者数字的任何组合形式。
3.不能使用关键字作为变量名或方法名。
4.标识符大小写敏感。
数据类型
强类型语言:所有变量都必须定以后才能使用。
基本类型
1.整数:byte占1个字节 short占2个字节 int占4个字节 long占8个字节
2.浮点数:float占 4个字节 double 占8个字节(最好完全避免使用浮点数进行比较)
3.字符类型:char占2个字节
4.boolean类型:true 和 false 都占一个位
引用类型
1.类
2.接口
3.数组
拓展
银行业务怎么表示:BigDecimal (数学工具类)
转义字符:\t :空格 \n:换行 等
类型转换
低-------------------------------------------------------->高
byte,short,char–>int–>long->float->double
强制类型转换:(类型)变量名 高—>低
自动类型转换:低---->高
**//注意点:**1.不能对布尔值进行转换
2.不能把对象类型转换为不相干的类型
3.再把高容量转换到低容量的时候,强制转换
4.转换的时候可能存在内存溢出,或者精度问题
eg:
变量
java变量是程序中最基本的存储单位,其要素包括变量名,变量类型和作用域
//数据类型 变量名=值;
注意:
1.每个变量都有类型,类型可以是基本类型和引用类型。
2.变量名必须是合法的标识符
3.变量声明是一条完整的语句,每个声明都必须以分号结束
作用域
1.类变量(static:修饰符不存在先后顺序)
2.实例变量(从属于对象)
3.局部变量(必须声明和初始化值)
常量
初始化后不能再改变的值,一种特殊的变量
final 常量名 = 值;
变量的命名规范
所有变量、方法、类名:见名知意
类成员变量:首字母小写和驼峰原则:除了第一个单词以外,后面的单词首字母大写
局部变量:首字母小写和驼峰原则
常量:大写字母和下划线
类名:首字母大写和驼峰原则
方法名:首字母小写和驼峰原则
运算符
- 算数运算符:+,-,*,/,%(取余),++,–
- 赋值运算符:= (eg:a=10 把10赋值给a)
- 关系运算符:>,<,>=,<=,==(等于),!=(不等于),instanceof
- 逻辑运算符:&&,||,!
- 位运算符(二进制运算):&(全为1则为1,否则为0),|(全为0则为0,否则为1),^(相同为0,不同为1),~(取反), >> (*2),<<(/2),>>>
- 条件运算符:?,:
- 扩展运算符:+=,-=,*=,/=
包机制
一般利用公司域名倒置作为包名
包语句的语法格式为: packge pkg1[1.pkg2[.pkg3…]]
导入包的语法格式为:import package1[.package2…].(classname|*);
JavaDoc
javadoc命令是用来生成自己的API文档
参数信息:
-
@auther 作者号
-
@version 版本信息
-
@since 指明需要最早使用的jdk版本
-
@param 参数名
-
@return 返回值情况
-
@throws 异常抛出情况
Scanner类
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否要有输入的数据
next(): 1.一定要读取到有效字符后才可以结束输入
2.对输入有效字符之前的空白,next()方法会自动将其去掉
3.只有输入有效的字符后才将其后面输入的空白作为分隔符或者结束符
4.next()不能得到带有空格的字符串
nextLine():1.以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符
2.可以获得空白
eg:
选择结构
if单选择
eg:
if双选择
eg:
if 多选择
注意:
- if语句至多有1个else语句,else语句在所有的else if 语句之后。
- if语句可以有若干个else if 语句,它们必须在else语句之前。
- 一旦其中一个else if 语句检测为TRUE,其他的else if 以及 else 语句都将跳过执行
嵌套的if结构
语法:if(布尔表达式1){
/如果布尔表达式1的值为TRUE执行代码
if(布尔表达式2){
/如果布尔表达式2的值为TRUE执行代码
}
}
Switch 多选择结构
Switch(expression){
case value :
//语句
break;//可选
case value :
//语句
break;//可选
//你可以有任意数量的case语句
default ://可选
//语句
}
反编译:java–>class (字节码文件) -----反编译(IDEA)
------>
------------>Show in Explorer ------->将class 文件复制到文件夹下即可
循环结构
while 循环
while(布尔表达式){
// 循环内容
}
- 只要布尔表达式为TRUE,循环就会一直执行下去
- 我们大多数情况下会让循环停止下来的,我们需要一个让表达式失效的方法来结束循环。
- 少部分情况需要循环一直执行,比如服务器的请求响应监听。
- 循环条件 一直为TRUE就会造成无限循环。
do…while循环
与while的区别:先执行再进行判断,总是保证循环体会被至少执行一次。
do{
//代码语句
}while(布尔表达式)
For循环
for(初始化;布尔表达式;更新){
//代码语句
}
快捷方式:100.for
增强的For循环
for(声明语句:表达式)
{
//代码句子
}
eg:
break continue
- break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环 ,不执行循环中剩余的语句。(break语句也在Switch语句中使用)
- continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
打印三角形(菱形):[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rC8tiU1v-1648889224079)(D:\Typora\JavasePicture\三角形.jpg)]
方法
什么是方法?
方法是解决一类问题的步骤的有序组合,包含于类或对象中,在程序中被创建,在其他地方被引用。
方法的定义
修饰符 返回值类型 方法名(参数类型 参数名){
…
方法体
…
return 返回值;
}
方法包含一个方法头和一个方法体。下面是方法的所有部分:
修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型:方法可能会返回值。returnValueType 是返回值的数据类型。有些方法执行所需要的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
实参:调用方法时实际传给方法的数据。
方法体:方法体包含具体的语句,定义该方法的功能
eg:
方法调用
调用方法:对象名.方法名(实参对象)
Java支持两种调用方法的方式,根据方法是否返回值来选择。
当返回一个值的时候,方法调用通常被当做一个值。eg:
int max= max(60,70);
如果方法返回值是void,方法调用一定是一天语句。
Sysout.out.println(“Hello,bb”);
java 是值传递
方法重载
重载就是在一个类中,相同的函数名称,但形参不同的函数。
方法的重载的规则:
方法名称必须相同。
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等。)
方法的返回类型可以相同也可以不同。
仅仅返回类型不同不足以成为方法的重载。
实现理论:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
命令行传参
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
可变参数
在方法声明中,在指定参数类型后加一个省略号(…)。
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
递归
-
递归就是:A方法调用A方法!就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分:
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
递归体:什么时候调用自身方法。**
eg:阶乘算法(!)
缺点:如果调用自身太多则影响机器的性能。
例题:计算器
// 不完美程序待改正
public class Demo04jisuanqi {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个数:");
double num1=scanner.nextDouble();
System.out.println("请输入运算符号:");
String str= scanner.next();
System.out.println("请输入第二个数:");
double num2=scanner.nextDouble();
switch (str){
case "+":
System.out.println("运算结果为:"+num1+"+"+num2+"="+add(num1,num2));
break;
case "-":
System.out.println("运算结果为:"+num1+"-"+num2+"="+minus(num1,num2));
break;
case "*":
System.out.println("运算结果为:"+num1+"*"+num2+"="+multiply(num1,num2));
break;
case "/":
System.out.println("运算结果为:"+num1+"/"+num2+"="+division(num1,num2));
break;
}
scanner.close();
}
public static double add(double a,double b){
return a+b;
}
public static double minus(double a,double b){
return a-b;
}
public static double multiply(double a,double b){
return a*b;
}
public static double division(double a,double b) {
if (b == 0) {
System.out.println("运算错误!");
}
return a/b;
}
}
数组
数组的定义
-
数组是相同类型数据的有序集合。
-
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
-
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组的声明定义
- 首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar;//首选的方法
或
dataType arrayRefVar[] ;//效果相同,但不是首选方法
- Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
- 数组的元素是通过索引访问的,数组索引从0开始。
- 获取数组的长度:arrays.length
eg:
package array;
public class arrayDemo01 {
public static void main(String[] args) {
int[] nums; //1.声明一个数组01
int nums1[];//1.声明一个数组02
nums = new int[10];//2.定义一个数组
int [] nums3= new int[10];//声明+定义一个数组
nums[0]=1;
nums[1]=2;
nums[2]=3;
nums[3]=4;
nums[4]=5;
nums[5]=6;
nums[6]=7;
nums[7]=8;
nums[8]=9;
nums[9]=10;
//求数组的和
int sum = 0;
for (int i = 0; i <nums.length ; i++) {
sum= sum+nums[i];
}
System.out.println("结果为:"+sum); //55
}
}
数组的三种初始化
-
静态初始化
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;
-
数组的默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
eg:
package array;
public class arrayDemo02 {
public static void main(String[] args) {
//1.静态初始化
int [] nums = {1,2,3,4};
System.out.println(nums[2]);// 3
//2.动态初始化, 包含默认初始化
int [] nums1 = new int[3];
nums1[0]=1;
nums1[1]=2;
System.out.println(nums1[2]);// 0
System.out.println(nums1[3]);// 显示错误为:java.lang.ArrayIndexOutOfBoundsException
}
}
数组的内存分析
数组的四个基本特点
- 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组的边界
-
下标的合法区间:[0,length-1],如果越界就会报错;
-
ArrayIndexOutOfBoundsException:数组下标越界异常;
eg:
int [] nums = {1,2,3,4};
for (int i = 0; i <nums.length ; i++) {
System.out.println(nums[i]);//1,2,3,4,
}
如果超出下标:
int [] nums = {1,2,3,4};
for (int i = 0; i <=nums.length ; i++) {
System.out.println(nums[i]);//1,2,3,4,
}
//结果为:
1
2
3
4
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at array.arrayDemo02.main(arrayDemo02.java:8)
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可改变。如果越界,则报:ArrayIndexOutOfBoundsException
数组的使用
-
普通的For循环
-
For-Each循环
//for-Each,没有下标适合打印输出,不适合打印里面的元素。 //数组中每一个元素 //一个数组 int []arrays = {1,2,3,4,5}; for (int array : arrays) { System.out.println(array); } }
-
数组做参数入参
-
数组做返回值
package array;
public class Demo03 {
public static void main(String[] args) {
int []arrays = {1,2,3,4,5};
arraysPrint(arrays);
int[] reverse = reverse(arrays);
arraysPrint(reverse);
}
// 打印数组元素
public static void arraysPrint(int[] arrays){
for (int i = 0; i <arrays.length ; i++) {
System.out.print(arrays[i]+" ");
}
}
//翻转数组元素
public 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;
}
}
多维数组
- 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
- 二维数组: int a[ ] [ ] = new int [2] [ 5] //二维数组a可以看成一个两行五列的数组。
package array;
public class Demo04 {
public static void main(String[] args) {
/*
1,2 array[0]
3,4 array[1]
5,6 array[2]
7,8 array[3]
*/
int[][] arrays = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
arrayPrint(arrays[0]);//打印下标为0的二维数组--------1 2
System.out.println(arrays[0][1]);//打印下标为0的二维数组中的下标为1的数组--2
System.out.println(arrays[2][1]);// ----6
//获取数组的长度
System.out.println(arrays.length);//二维数组长度 -----------4
System.out.println(arrays[2].length);//下标所在数组的长度 ---2
//获取二维数组
for (int i = 0; i <arrays.length ; i++) {
for (int j = 0; j <arrays[i].length ; j++) {
System.out.print(arrays[i][j]+" ");//----1 2 3 4 5 6 7 8
}
}
}
public static void arrayPrint(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i] + " ");
}
}
}
Arrays类
-
数组的工具类Java.util.Arrays
-
由于数组对象本身并没有什么办法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
-
具有以下常用功能:
给数组赋值:通过fill方法。
对数组排序:通过sort方法,按升序。
比较数组:通过equals方法比较数组中元素值是否相等。
查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法排序。
package array;
import java.util.Arrays;
public class Demo05 {
public static void main(String[] args) {
int [] a ={1,2,3,10,9,77,12,31024,12800};
int [] b = {3,4,5,10,44,77,50,1234,78910};
System.out.println(a);//[I@1540e19d
System.out.println(Arrays.toString(a));//[1, 2, 3, 10, 9, 77, 12, 31024, 12800]
arraysPrint(a); //[1 ,2 ,3 ,10 ,9 ,77 ,12 ,31024 ,12800]
Arrays.sort(a);//对数组进行升序排序
System.out.println(Arrays.toString(a));//[1, 2, 3, 9, 10, 12, 77, 12800, 31024]
Arrays.fill(a,7);//将数组元素进行覆盖
System.out.println(Arrays.toString(a));//[7, 7, 7, 7, 7, 7, 7, 7, 7]
Arrays.fill(a,3,6,7);//将下标3到4的数组元素进行覆盖
System.out.println(Arrays.toString(a));//[1, 2, 3, 7, 7, 7, 77, 12800, 31024]
Arrays.binarySearch(a,10);//对排序好的数组进行二分查找法排序
System.out.println(Arrays.toString(a));//[1, 2, 3, 10, 9, 77, 12, 31024, 12800]
}
//打印数组同toString
public static void arraysPrint(int []a ){
for (int i = 0; i < a.length; i++) {
if (i==0){
System.out.print("[");
}
if (i==a.length-1){
System.out.print(a[i] + "]");
}else {
System.out.print(a[i] + " ,");
}
}
}
}
冒泡排序
- 比较数组中,两个相邻的元素,如果第一个比第二个数大,就将位置进行交换;
- 每一次比较都会产生一个最大,或者最小的数字;
- 下一轮则可以少一次排序;
- 依次循环,直到结束;
package array;
import java.util.Arrays;
public class Demo06 {
public static void main(String[] args) {
int [] a={5,10,30,25,40,78,77,66,120,1300};
int[] sort = sort(a);//调用完我们自己写的排序方法
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array) {
//临时变量
int temp = 0;
//外层循环,判断我们要走多少次
for (int i = 0; i < array.length - 1; i++) {
//内层循环,比价判断两个数,如果第一个数,比第二个数大,交换位置
boolean flag = false;//通过flag标识判断数组是否排好了序
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j + 1] < array[j]) {
temp = array[j]; //将a[j]赋值给temp
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if (flag == true) {
break;
}
}
return array;
}
}
稀疏数组
- 当一个数组大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
记录数组一共有几行几列,有多少个不同值
把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
eg:
package array;
import java.util.Arrays;
public class arrayDemo07 {
public static void main(String[] args) {
//1.创建一个二维数组是11*11 0:没有棋子 1:代表黑棋子 2:代表白棋子
int[][] array1 = new int[11][11];
array1[1][2]=1;
array1[2][3]=2;
//输出原始的数组
System.out.println("输出原始数组:");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println( );
}
System.out.println("----------------------------------------------------");
//转换为稀疏数组进行保存
//获取有效值的个数
int sum = 0;
for (int i = 0; i <11 ; i++) {
for (int j = 0; j <11 ; j++) {
if (array1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值的个数为:"+sum);
//2.创建稀疏数组对应的数组
int [][] array2=new int[sum+1][3];
array2[0][0]=11;
array2[0][1]=11;
array2[0][2]=sum;
//遍历二维数组,将非零的值存放到稀疏数组中
int count = 0;
for (int i = 0; i <array1.length ; i++) {
for (int j = 0; j <array1[i].length ; j++) {
if (array1[i][j]!=0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
//输出稀疏数组
System.out.println("稀疏数组");
for (int i = 0; i <array2.length; i++) {
System.out.println(array2[i][0]+"\t"
+array2[i][1]+"\t"
+array2[i][2]+"\t");
}
System.out.println("---------------------------------------");
System.out.println("还原");
//1.读取稀疏数组
int [] [] array3 = new int [array2[0][0]][array2[0][1]];
//2.给其中的元素还原它的值
for (int i = 1 ; i <array2.length ; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
//3.打印
System.out.println("输出还原的数组");
for (int[] ints : array3) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println( );
}
}
}
面向对象编程(OOP)
面向对象编程(Object-Oriented Programming ,OOP)
面向过程 & 面向对象
- 面向过程思想
步骤清晰简单,第一步做什么,第二步做什么…
面向过程适合处理一些较为简单的问题
- 面向对象思想
物以类聚,分类的思维模式,思考问题首先会解决问题需要那些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
- 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,集体到微观操作 ,仍然需要面向过程的思路去处理。
什么是面向对象
- 面向对象编程的本质是:以类的方式组织代码,以对象的组织(封装)数据
- 三大特性:封装、继承、多态
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
回顾方法及加深
- 方法的定义
修饰符
返回类型
break:跳出Switch,结束循环和return:结束方法,返回一个结果的区别
方法名:注意规范,见名知意
参数列表:(参数类型,参数名)…
异常抛出
package com.oop.Demo01;
public class Demo01 {
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名 (。。。){
//方法名
return 返回值;
}
*/
public String sayHello(){
return "Helloworld";
}
public void print(){
return;//返回值为void时,return空
}
public int max (int a,int b ){
return a>b ? a:b; //三元运算符
}
// 数组下标越界 :Arrayindexoutofbounds
public void readFile(String file) throws IOException {
}
}
- 方法的调用
静态方法
非静态方法
package com.oop.Demo01;
public class Demo02 {
public static void main(String[] args) {
//静态方法
Student.say();
//实例化这个类 new
Student student = new Student();
}
}
package com.oop.Demo01;
public class Student {
//静态方法
public static void say(){
System.out.println("HolloWorld");
}
//非静态方法
public void say1(){
System.out.println("HolloWorld");
}
}
形参和实参
package com.oop.Demo01;
public class Demo03 {
public static void main(String[] args) {
//实际参数和形式参数的类型要对应!
int add = Demo03.add(5,6);
System.out.println(add);
}
public static int add(int a,int b){
return a+b;
}
}
值传递和引用传递
package com.oop.Demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a =1;
System.out.println(a);
Demo04.Change(a);
System.out.println(a);
}
//返回值为空
public static void Change(int a ){
a=10;
}
}
package com.oop.Demo01;
//引用传递:对象,本质还是值传递
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null
Demo05.Chenge(person);
System.out.println(person.name);//Jeremy
}
public static void Chenge(Person person){
//person是一个对象:指向——>Person person = new Person();这是一个具体的人,可以改变属性!
person.name="Jeremy";
}
}
//一个类中可以有多个public class ,但是可以有多个class
//定义一个Person类,有一个属性:name
class Person{
String name;//默认为null
}
this关键字
类与对象的关系
package com.oop.Demo02;
public class Student {
//属性:字段
String name;
int age ;
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
package com.oop.Demo02;
public class Application {
public static void main(String[] args) {
//类是抽象的需要实例化的;
//类实例化后会返回一个自己的对象;
//Jeremy,baba 对象就是Student类的具体实例。
Student jeremy = new Student();
Student baba = new Student();
jeremy.name="jeremy";
jeremy.age=21;
System.out.println(jeremy.name);//jeremy
System.out.println(jeremy.age);//21
baba.name="baba";
baba.age=21;
System.out.println(baba.name);//baba
System.out.println(baba.age);//21
}
}
创建与初始化对象
- 使用new关键字创建对象:使用new关键字创建时,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
1.必须和类的名字相同
2.必须没有返回类型,也不能写void
package com.oop.Demo02;
public class Person {
//一个类即使什么都不写也会存在一个方法
String name;
int age;
/*作用:
1.使用new 本质是在调用构造器构造器
2.构造器用来初始化值
注意点:1.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
*/
//无参构造器
//实例初始化
public Person() {
}
//有参构造器:一旦定义了有参构造,无参就必须显示定义
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
package com.oop.Demo02;
//一个项目应该只存一个main方法
public class Application {
public static void main(String[] args) {
// new 实例化一个对象
Person person = new Person("jeremy",21);
System.out.println(person.name);
System.out.println(person.age);
}
}
this.当前类 = 参数传入的值
封装
- 该露的露,该藏的藏
我们程序设计追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合就是仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
记住这句话:属性私有,get/set
package com.oop.Demo03;
/*1.提高程序的安全性,保护数据
2.隐藏代码的现实细节
3.统一接口
4.系统可维护增加了
*/
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("Jeremy");
System.out.println(s1.getName());
s1.setSex('男');
System.out.println(s1.getSex());
s1.setAge(110);
System.out.println(s1.getAge());
}
}
package com.oop.Demo03;
//类 private:私有
public class Student {
private String name;
private int id;
private char sex;
private int age;
//提供一些可以操作这个属性的方法----> public的get、set方法
//get 获得这个数据
public String getName() {
return name;
}
//set 给这个数据设置值
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {//set方法可添加条件
if (sex=='男'|| sex=='女'){
this.sex = sex;
}else{
System.out.println("请输入正确的性别");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>120||age<3){
this.age = age;
}else {
this.age=3;
System.out.println("请输入正确的性别");
}
}
}
继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
-
extends的意思是“扩展”。子类是父类的扩展。
-
JAVA中类只有单继承,没有多继承!一个儿子只能有一个爸爸,一个爸爸可以有多个儿子。
-
继承是类与类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
-
子类和父类之间,从意义上讲应该具有“is a”的关系。
package com.oop.Demo04;
//java中,所有的类都默认直接或者间接的继承Object
//Person 父类
public class Person {
/*
四个修饰符,优先级从高到低:
public----
protected-受保护的;
default---不写的时候默认的;
private---私有的;
*/
private int money =10_0000_0000;
public void say(){
System.out.println("aaaaa");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
package com.oop.Demo04;
//student is 派生类 子类
//子类继承了父类就会拥有父类的全部方法!
public class Student extends Person{
}
package com.oop.Demo04;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}
当修饰符为private时,调用时必须使用get/set方法,set方法是进行限制,比如设定一些特殊的条件符合才可以调用。
Super:
注意点:
- super调用父类的构造方法,必须在构造方法的第一个;
- super必须只能出现在子类的方法或者构造方法中;
- super 和this不能同时调用构造方法!
和this的区别:
-
代表的对象不同
this:本身调用这个对象
super:代表父类对象的应用
-
前提
this:没有继承也可以使用
super:只能在继承条件才可以使用
-
构造方法
this();本类的构造
super();父类的构造
package com.oop.Demo04;
//java中,所有的类都默认直接或者间接的继承Object
//Person 父类
public class Person {
protected String name="jeremy";
}
package com.oop.Demo04;
//student is 派生类 子类
//子类继承了父类就会拥有父类的全部方法!
public class Student extends Person{
private String name ="77";
public void text(String name){
System.out.println(name);//xiaoao
System.out.println(this.name);//77
System.out.println(super.name);//jeremy
}
}
package com.oop.Demo04;
public class Application {
//私有的东西无法被继承
public static void main(String[] args) {
Student student = new Student();
student.text("xiaoao");
}
}
方法重写
方法重写:需要有继承关系,子类重写父类的方法.
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小;public>Protected>Default>private
- 抛出的异常范围可以被缩小,但不能扩大;eg:ClassNotFoundException—>Exception(范围大)
方法重写:子类的方法和父类必要一致;方法体不同。
为什么需要重写:
- 父类的功能,子类不一定需要,或者不一定满足。
- Alt+Insert—>override
package com.oop.Demo05;
//重写都是方法的重写和属性无关
public class B {
public void text(){
System.out.println("B=>text()");
}
}
package com.oop.Demo05;
public class A extends B {
@Override
public void text() {
System.out.println("A=>text()");
}
}
package com.oop.Demo05;
public class Application {
public static void main(String[] args) {
//静态方法:方法的调用只和左边(定义的数据类型)有关
//非静态方法:进行重写,只能说public,不能是私有
A a = new A();
a.text();
//父类的引用指向子类
B b = new A();//子类重写了父类的方法
b.text();
}
}
多态
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
- 多态存在的条件:
有继承关系
子类重写父类方法
父类引用指向子类对象
- 多态注意事项:
- 多态是方法的多态,属性没有多态;
- 父类和子类,有联系 不然就会类型转换异常 ClassCastException
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象。 eg:Father f1 = new Son();
- 不存在多态的条件:
- static 方法,属于类不属于实例;
- final 常量;
- pribate方法;
package com.oop.Demo06;
public class Father {
public void run(){
System.out.println("aaa");
}
}
package com.oop.Demo06;
public class son extends Father{
@Override
public void run() {
System.out.println("bbb");
}
public void fun(){
System.out.println("ccc");
}
}
package com.oop.Demo06;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new son();
//new Father();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Son 能调用的方法都是自己的或者继承父类的
son s1 = new son();
//Father 父类型,可以指向子类,但是不能调用子类独有的方法
Father s2 = new son();
Object s3 = new son();
s1.run();
s2.run();
s1.fun();
//对象能执行哪些方法,主要看对象左边的类型,和右边的关系不大
//s2.fun();需进行类型强制转换
((son)s2).fun();
}
}
instanceof :(类型转换)引用类型 判断一个对象是什么类型
package com.oop.Demo06;
import com.oop.Demo01.Student;
public class Application {
public static void main(String[] args) {
//Object > String
//Object > Father > Son01
//Object > Father > son
Object object = new son();
//System.out.println(X instanceof Y);能不能编译通过
System.out.println(object instanceof son);//true
System.out.println(object instanceof Father);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Son01);//false
System.out.println(object instanceof String);//false
Father father = new son();
System.out.println(father instanceof son);//true
System.out.println(father instanceof Father);//true
System.out.println(father instanceof Object);//true
System.out.println(father instanceof Son01);//false
//System.out.println(father instanceof String);//编译报错
son son = new son();
System.out.println(son instanceof son);//true
System.out.println(son instanceof Father);//true
System.out.println(son instanceof Object);//true
//System.out.println(son instanceof Son01);//编译报错
//System.out.println(son instanceof String);//编译报错
}
}
- 父类引用指向子类对象;
- 向下转型,高类型转低类型需要进行强制转换,则父类型转子类型需要进行强制转换;
- 向上转型,子类转化为父类可能会丢失自己本来的一些方法 ;
- 方便方法的调用,较少重复的代码,简洁。
Static 补充
static 静态变量
package com.oop.Demo07;
public class Student {
private static int age;//静态的变量
private double name;//非静态的变量
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
//System.out.println(Student.name);非静态不能用 类名.变量
System.out.println(s1.age);
System.out.println(s1.name);
}
}
static 静态方法
package com.oop.Demo07;
public class Student {
private static int age;//静态的变量
private double name;//非静态的变量
//静态方法、非静态方法可以直接调用静态方法,静态方法、非静态方法调用非静态方法是需要先new。
public void run(){
go();
}
public static void go(){
}
public static void main(String[] args) {
new Student().run();
Student.go();
go();
}
}
代码块
package com.oop.Demo07;
public class Person {
//匿名代码块-----2;赋初始值
{
System.out.println("匿名代码块");
}
//静态代码块----1;只执行一次
static{
System.out.println("静态代码块");
}
//构造器-------3
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("===================");
Person person2 = new Person();
}
}
结果:静态代码块
匿名代码块
构造方法
===================
匿名代码块
构造方法
stati 静态导入包
package com.oop.Demo07;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(Math.PI);
System.out.println(random());//静态导入以后
}
}
- public 被 final 修饰就不可以被继承
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该方法就是抽象类;
- 抽象类中可以没有抽象方法,但是抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
约束:1.抽象类不可以实例化即不可以new这个抽象类,只能靠子类去实现;
2.抽象类中可以写抽象方法,抽象方法必须在抽象类中;
package com.oop.Demo08;
//抽象类
public abstract class Action {
// 抽象方法可以不实现,只有方法名,没有方法实现
public abstract void doSomething();
}
package com.oop.Demo08;
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法;
//子类如果也是抽象类则由子子类或者其他子类实现他的方法。
public class A extends Action {
@Override
public void doSomething() {
}
}
接口
-
普通类:只有具体实现;
-
抽象类:具体实现和规范(抽象方法)都有;
-
接口:只有规范。
-
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人。
-
接口的本质是契约,就像我们人间的法律一样,制定好大家都遵守。
-
oop的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
声明类的关键字是class,声明接口的关键字是interface
作用:
- 是一些约束;
-
定义一些方法,让不同的人实现
- 默认的方法public abstract
- 所有的常量 public static final
- 接口不能直接被实例化,因为接口中没有构造方法
- implements可以实现多个接口
- 必须要实现接口中的方法
package com.oop.Demo09;
public interface UserService {
//接口中所有定义的方法其实都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package com.oop.Demo09;
public interface TimeService {
void timer();
}
package com.oop.Demo09;
//类可以实现接口,通过implements关键词
//抽象类通过extends关键词只能单继承,接口可以的
//实现了接口的类,就需要重接接口中的所有方法
//利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
内部类
- 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个类B,那么B类相对A类来说就称为内部类,而A类相对于B类来说就是外部类了。
1.成员内部类
package com.oop.Demo10;
public class Outer {
private int id = 77;
public void out(){
System.out.println("这是外部类的方法");
}
class Inner{
public void in() {
System.out.println("这是内部类的方法");
}
//可以获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
package com.oop.Demo10;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
2.静态内部类
package com.oop.Demo10;
public class Outer {
}
//一个java类中可以有多个class类,但是只有一个public class
class A{
}
3.局部内部类
package com.oop.Demo10;
public class Outer {
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
4.匿名内部类(重点)
package com.oop.Demo10;
public class Text {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new Apple().eat();
UserService userService = new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("a");
}
}
interface UserService{
void hello();
}
异常机制
什么是异常
-
实际工作中,遇到的情况不可能是完美。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序在跑着内存或者硬盘就满了等情况。
-
软件程序运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
-
异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
-
异常发生在程序运行期间,它影响了正常的程序执行流程。
简单分类
-
要理解Java异常处理是如何工作的,需要掌握以下三种类型的异常:
-
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如:打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
-
运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以编译时被忽略。
-
错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈出时,一个错误就发生了,它们在编译也检查不到的。
异常体系结构
-
Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
-
在JavaAPI中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
Error
-
Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
-
Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
-
还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误 (LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大数是程序运行时不允许出现的状况。
Exception
-
在Exception分支中有一个重要的子类RuntimeException(运行时异常)
ArrayIndexOutOfBoundsException(数组下标越界)
NullPointerException(空指针异常)
ArithmeticException(算数异常)
MissingResourceException(丢失资源)
ClassNotFountException(找不到类)等异常,这些异常是不检查异常,程序中选择捕获处理,也可以不处理。
-
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
-
Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应尽可能去处理这些异常。
异常处理机制
- 抛出异常
- 捕获异常
- 常用的关键字:try、catch、finally、throw、throws
try、catch、finally
package com.Exception;
public class Demo01 {
public static void main(String[] args) {
int a = 1;
int b = 1 ;
//如果要捕获多个异常:要从小到大进行排序。
try { //try 监控区域
System.out.println(a/b);
}catch ( ArithmeticException e){//catch(想要不捕获的异常类型,最高的是Throwable) 捕获异常
System.out.println("程序出现异常,变量b不能为0!");
}finally {//finally 处理善后工作,不论出不出异常都将实现,可以有也可以没有,
//假设IO流一些资源需要关闭可以用到。
System.out.println("final");
}
}
}
try { //try 监控区域
new Demo01().a();
}catch ( Throwable e){//catch(想要不捕获的异常类型,最高的是Throwable) 捕获异常
System.out.println("程序出现异常,变量b不能为0!");
}finally {//finally 处理善后工作,不论出不出异常都将实现,可以有也可以没有,
//假设IO流一些资源需要关闭可以用到。
System.out.println("final");
}
}
public void a(){
b();
}
public void b(){
a();
}
throw
public class Demo01 {
public static void main(String[] args) {
new Demo01().text(1,0);}
//假设在方法中,处理不了这个异常,则方法上抛出异常。
public void text(int x ,int y ){
if(y==0){
throw new ArithmeticException();//主动抛出的异常,一般在方法中使用
}
System.out.println(x/y);
}
}
throws
public class Demo01 {
public static void main(String[] args) {
try {
new Demo01().text(1,0);
} catch (Exception e) {
e.printStackTrace();
}}
public void text(int x ,int y )throws ArithmeticException{
if(y==0){
throw new ArithmeticException();
}
System.out.println(x/y);
}
}
自定义异常(一般情况下不需要)
-
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
-
在程序中使用自定义异常类,大体分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过throw关键字抛出异常对象。
3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。 - 在出现异常方法的调用者中捕获并处理异常。
package com.Exception;
//自定义的异常类
public class MyException extends Exception {
//假设传递数字>10的时候抛出异常
private int detail;
public MyException(int a) {
this.detail=a;
}
//toString
@Override
public String toString() {
return "MyException{" + detail+'}';
}
}
```java
package com.Exception;
public class Text {
//可能会存在异常的方法
static void text(int a ) throws MyException {
System.out.println("传递的参数为:"+a);
if (a>10){
throw new MyException(a);//抛出
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
text(11);
} catch (MyException e) {
System.out.println("MyException=>"+e);
}
}
}
传递的参数为:11
MyException=>MyException{11}
```
实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch(Excaption)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源
JavaSE总结
o01 {
public static void main(String[] args) {
new Demo01().text(1,0);}
//假设在方法中,处理不了这个异常,则方法上抛出异常。
public void text(int x ,int y ){
if(y==0){
throw new ArithmeticException();//主动抛出的异常,一般在方法中使用
}
System.out.println(x/y);
}
}
**throws**
```java
public class Demo01 {
public static void main(String[] args) {
try {
new Demo01().text(1,0);
} catch (Exception e) {
e.printStackTrace();
}}
public void text(int x ,int y )throws ArithmeticException{
if(y==0){
throw new ArithmeticException();
}
System.out.println(x/y);
}
}
自定义异常(一般情况下不需要)
-
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
-
在程序中使用自定义异常类,大体分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过throw关键字抛出异常对象。
3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。 - 在出现异常方法的调用者中捕获并处理异常。
package com.Exception;
//自定义的异常类
public class MyException extends Exception {
//假设传递数字>10的时候抛出异常
private int detail;
public MyException(int a) {
this.detail=a;
}
//toString
@Override
public String toString() {
return "MyException{" + detail+'}';
}
}
```java
package com.Exception;
public class Text {
//可能会存在异常的方法
static void text(int a ) throws MyException {
System.out.println("传递的参数为:"+a);
if (a>10){
throw new MyException(a);//抛出
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
text(11);
} catch (MyException e) {
System.out.println("MyException=>"+e);
}
}
}
传递的参数为:11
MyException=>MyException{11}
```
实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch(Excaption)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源