java基础语法
注释
- 单行注释 //
- 多行注释 /* */
- 文档注释 /** */
标识符
- 所有表示符都应该以(A-Z或者a-z),美元符(¥),下划线(_)开始
- 不能使用关键字作为方法名和变量名
- 大小写敏感
数据类型
java为强类型语言:要求变量的使用严格符合规定,所有变量都必须先定义后才可以使用
基本类型:byte 、short、 int、long、float、double、char、boolean
引用类型:类、接口、数组
整数拓展
进制:二进制0b 、十进制、八进制0、十六进制0x
浮点数拓展
float f=0.1f;
double d=1.0/10;
System.out.println(f==d); //false
float数是有限、离散的,有舍入误差, 在银行业务中应使用BigDecimal 数学工具类
字符拓展
所有字符本质还是数字, Unicode表(97=a 65=A)
char c3='\u0061';
System.out.println(c3);// a
转义字符
/t :制表符 /n:换行
String a=new String("hello");
String b=new String("hello");
String c="hello3";
String d="hello";
System.out.println(a==b); //false
System.out.println(c==d); //true
对象不一样,要从内存分析
布尔值扩展
boolean flag=true;
if(flag==ture){}//新手
if(flag){}//老手,
变量类型转换
强制转换:(类型)变量名 高—低
自动转换:低—高
-
不能对布尔值进行转换
-
不能把对象类型转换成不相干的类型
-
在把高容量转换到低容量的时候要强制转换
- 转换的时候可能存在内存溢出,或者精度问题
-
int money=10_0000_0000;//JDK7新特性,数字之间可以用下划线分割
int years=20;
int total1=money*years;
long total2=money*years;
long total3=money*((long)years);
System.out.println(total1);//负数,计算的时候溢出了
System.out.println(total2);//负数,转换之前已经出现问题
System.out.println(total3);//正确,先把一个数转换成long
变量
数据类型 变量名=值;
- 每个变量都有类型
- 变量名必须是合法的标识符
- 变量声明必须以分号结束
变量的作用域
-
局部变量:必须声明和初始化
-
实例变量:从属于对象,如果不自行初始化,除基本类型外其余的默认值都为null,boolean值为false
-
类变量:使用static
常量
初始化后不能再改变值;常量名一般使用大写字符
final double PI=3.14;
变量的命名规范
- 所有变量、方法、类名要见名知意
- 类成员变量、局部变量、方法名:首字母小写和驼峰原则:monthSalary,runRun()
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则: Man,GoodMan
运算符
算术运算符:+,-,*,/,%,++,–
++,-- ,自增,自减是个一元运算符
a++:先赋值,再自增
++a:先自增,在赋值
赋值运算符:=
关系运算符:>,<,>=,<=,==,!=
逻辑运算符:&&,||,!
A&&B:两个变量都为真,结果才为真
A||B:两个变量全为假,结果才为假
!A:变量为真,结果为假
//短路运算
int c=5;
boolean d=(c<4)&&(c++<4);
System.out.println(d);//false
System.out.println(c);//5 因为&&运算全真才真,c<4为假所以不会执行后面(c++《4)
位运算符:&,|,^,~,>>,<<,>>>
在二进制下进行运算
例:A=0011 1100,B=0000 1101
A&B=0000 1100 运算规则和&&类似
<<运算为*2,>>运算为/2
因为在二进制下运算,效率更高
条件运算符: ?:
X?Y:Z 如果X为true结果为Y,否则为Z
扩展赋值运算符:+=,-=,*=,/=
int a=10;
int b=20;
a+=b;//a=a+b
a-=b;//a=a-b
System.out.println(""+a+b);//1020 字符串在前面进行字符串拼接
System.out.println(a+b+"");//30 进行运算
Math.pow(3,2) 2的3次方计算 为math函数,很多运算我们会用到一些工具类
java流程控制
Scanner对象
通过Scanner类来获取用户的输入
语法: Scanner s=new Scanner(System.in);
通过Scanner类的next()与nextLine()方法获取输入字符串,使用hasNext()与hasNextLine()判断是否还有输入的数据
//创建一个扫描器对象,用于接收键盘数据
Scanner s=new Scanner(System.in);
//判断用户有没有输入字符串
if(scanner.hasNext()){
//用next的方式接收
String str=scanner.next();
System.out.println(str)
}
scanner.close();//凡是属于IO流的类如果不关闭会一直占用资源
next():1. 一定要读取到有效的字符后才可以结束输入
2.对输入有效字符前遇到的空白,会自动将其去掉
3.不能得到带有空格的字符串
nextLine():1.以回车键为结束符
2.可以获得空白
输入多个数字,求其总和与平均数,每输入一个数字用回车确认,通过输入非数字类结束输入并输出执行结果
Scanner scanner=new Scannner(System.in);
double sum=0;
int m=0;
while(scanner.hasNextDouble()){
double x=scanner.nextDouble();
m++;
sum+=x;
System.out.println("你输入了第"+m+"个数据,当前结果为sum="+sum);
}
System.out.println(m+"个数的和为"+sum);
System.out.println(m+"个数的平均值为"+(sum/n));
scanner.close();
顺序结构
java的基本结构就是顺序结构,由上到下的顺序进行,除非特别的声明,它是任何一个算法都离不开的一种基本算法结构
选择结构
if单选泽结构
if(布尔表达式){
//如果布尔表达式为true将执行语句
}
if双选择结构
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if多选择结构
if(布尔表达式1){
//如果布尔表达式1的值为true执行代码
}else if(布尔表达式2){
//如果布尔表达式2的值为true执行代码
}else if(布尔表达式3){
//如果布尔表达式3的值为true执行代码
}else{
//如果以上的布尔表达式都不为true执行代码
}
if语句最多有一个else语句,可以有若干个else if语句,其中一个检测为true后面的都将不执行
嵌套的if结构
if(布尔表达式1){
//如果布尔表达式1的值为true执行代码
if(布尔表达式2){
//如果布尔表达式2的值为true执行代码
}
}
switch多选择结构
switch case语句判断一个变量与一系列值中某个值是否相等,每个值为一个分支
switch语句中的变量类型可以是:byte、short、int、char
- 从javaSE 7开始switch支持字符串String类型了
- 同时使用case标签必须为字符串常量或字面量
switch(表达式){
case value:
//语句
break;
case value:
//语句
break;
default:
//语句
}
case穿透:如果不使用break结束语句,依旧会执行后面的case语句
循环结构
while循环
while(布尔表达式){
//循环内容
}
- 只要布尔表达式为true,循环就一直执行下去
- 会造成死循环,大多数情况需要循环停止,需要一个让表达式失效的方法类结束循环
- 服务器的请求响应监听需要循环一直执行,为少部分情况
计算1+2+3+…+100=?
int i=0;
int sum=0;
while(i<=100){
sum+=i;
i++;
}
System.out.println(sum);
do…while循环
do{
//执行代码
}while(布尔表达式);
do…while和while的区别
- while先判断后执行。do…while是先执行后判断
- do…while总能保证循环体会至少执行一次
for 循环
- for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构
- for循环次数在执行前就确定了
for(int i;i<5;i++){
System.out.println(i);
}
初始化可为一个或多个循环控制变量,也可为空语句,也可声明一种类型
计算0-100之间的奇数和偶数的和
int oddSum=0;
int evenSum=0;
for(int i=0;i<=100;i++){
if(i%2!=0){//奇数
oddSum+=i;
}else{//偶数
evenSum+=i;
}
}
System.out.println("奇数的和"+oddSum);
System.out.println("偶数的和"+evenSum);
用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
for(int i=0;i<=1000;i++){
if(i%5==0){
System.out.print(i+"\t");
}
if(i%(5*3)==0){//每行
System.out.print();
}
}
打印九九乘法表
//1.先打印第一列
//2.把固定的1再用一个循环包起来
//3.去掉重复项
//4.调整样式
for(int j=1;j<=9;j++){
for(int i=1;i<=j;i++){
System.out.print(j+"*"+i+"="+(j*i)+"\t");
}
System.out.println();
}
增强for循环
java5引入的一种用于数组和集合的增强型for循环
int[] numbers=[10,20,30,40,50];
for(int x:numbers){
System.out.println(x)
}
break continue
break: 用于强行退出循环,不执行循环中剩余的语句
continue:用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
打印三角形
for(int i=1;i<=5;i++){
for(int j=5;j>=i;j++){
System.out.print(" ");
}
for(int j=1;j<=i;j++){
System.out.print("*");
}
for(int j=1;j<i;j++){
System.out.print("*");
}
System.out.println();
}
方法
方法的定义和调用
定义:方法就是用来完成特定功能的代码片段,方法包括一个方法头和一个方法体
调用:对象名.方法名(实参列表)
static方法和类同时加载,非static方法和实例同时加载
- 当方法返回一个值时,方法调用通常被当成一个值
int larger=max(30,40);
- 当返回的是void,方法调用一定是语句
System.out.println("Hello");
方法的重载
重载就在同一个类中,有相同的函数名称,但形参不同的函数
方法重载规则:
-
方法名称必须相同
-
参数列表必须不同(个数不同,类型不同,参数排列顺序不同等)
- 方法的返回类型可以相同也可以不同,但仅仅返回类型不同不是方法的重载
原理:
方法名相同时,编译器会根据调用方法的参数个数、参数类型等逐个匹配,已选择对应的方法
可变参数
在java 1.5开始,java支持传递同类型 的可变参数给一个方法
- 在方法声明中,在指定参数类型后加一个省略号(…)
- 一个方法只能有一个可变参数,也必须在最后面声明,任何普通参数都必须在它之前声明
public static void printMax(double... number){}
递归
递归:就是自己调用自己
利用递归可以用简单的程序解决一下复杂的问题,通常把一个大型复杂的问题层层转化为一个与原来问题相似的规模较小的问题来求解
递归结构包括两部分:
-
递归头:什么时候不调用自身方法。没有头将陷入死循环
-
递归体:什么时候需要调用自身方法
public static int f(int n){//阶乘
if(n==1){
return 1;
}else{
return n*f(n-1);
}
}
数组
数组的声明和创建
- 必须声明数组变量才能在程序中使用数组
dataType[] arrayRefVar;//首选方法
dataType arrayRefVar[];//效果相同
- java语言使用new操作符创建数组
dataType[] arrayRefVar=new dataType[arraySize];
- 数组的元素是通过索引访问的,数组索引从0开始
- 获取数组长度 数组名.length
数组内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uieQONVz-1601718604169)(C:\Users\Administrator\Pictures\Camera Roll\1.png)]
数组三种初始化及边界
- 静态初始化 (创建并赋值)
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异常
数组的使用
for-each循环遍历
int[] arrays={1,2,3,4,5};
for(int array:array){
System.out.println(array);
}
数组作方法入参
int[] arrays={1,2,3,4,5};
printArray(arrays);
public static void printArray(int[] array){
for(int i=0;i<arrays.length;i++){
System.out.print(array[i]+"");
}
}
数组作返回值
int[] arrays={1,2,3,4,5};
int[] reverse=reverse(arrays);
System.out.println(reverse);
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];
}
}
二维数组
多维数组可以看成是数组的数组,数组里面的元素是一个数组
int a[][]=new int[2][5]//可以看成是一个2行5列的数组
多维数组和维数组一样在后面加一个数组
冒泡排序
- 比较数组中两个相邻的元素,如果第一个比第二个数大,交换他们的位置
- 每一次比较都会产生一个最大或者最小的数字
- 下一轮可以少一次排序
- 依次循环,直到结束
int a[]={23,231,11,24,25,14,22};
int[] sort=sort(a);
System.out.println(Arrays.toString(sort));
public int sort(int[] a){
int temp;
for(int i=0;i<a.length-1;i++){
boolean flag=false;
for(int j=0;j<a.length-1-i;j++){
if(a[j]>a[j+1]){
temp=a[j+1];
a[j]=a[j+1];
a[j+1]=temp;
flag=true;
}
}
if(flag==false){
break;
}
}
return a;
}
稀疏数组
- 当一个数组中大部分元素为0,或者为同一值得数组时,可以使用稀疏数组来保存该数组
- 稀疏数组的处理方式
- 记录数组一共几行几列,有多少个不同值
- 把具有不同值的元素行和列及值记录在一个小规模的数组中,从而缩小程序的规模
编写五子棋游戏中,有存盘退出功能
//创建一个二维数组11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array=new int[11][11];
array[1][3]=1;
array[2][4]=2;
System.out.println("输出原始数组");
for(int[] i:array){
for(int j:i){
System.out.print(j+"\t");
}
System.out.println();
}
//计算有效值得个数
int sum=0;
for(int i=0;i<11;i++){
for(int j=0;j<11;j++){
if(array[i][j]!=0){
sum++;
}
}
}
//创建稀疏数组
int count=0;
int[][] array2=new int[sum+1][3];
array2[0][0]=11;
array2[0][1]=11;
array2[0][2]=sum;
for(int i=0;i<11;i++){
for(int j=0;j<11;j++){
if(array[i][j]!=0){
count++;
array2[count][0]=i;
array2[count][1]=j;
array2[count][2]=array[i][j];
}
}
}
for(int[] i:array2){
for(int j:i){
System.out.print(j+"\t");
}
System.out.println();
}
面向对象
面向对象的特性
三大特性:封装、继承、多态
面对对象编程(OOP)(Object-Oriented Programming)
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
- 从认识角度考虑是先有对象后有类,对象:具体的事物 类:是抽象的,对对象的抽象
- 从代码运行角度是先有类后有对象,类是对象的模板
对象的创建和内存分析
必须使用new关键字创建对象
Person p=new Person();
对象的属性 p.name
对象的方法 p.sleep()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zin2T9h8-1601718604174)(C:\Users\Administrator\Pictures\Camera Roll\2.png)]
构造器
一个类即使什么都不写,它也会存在一个无参构造方法
-
名字必须和类名相同
-
没有返回值
-
new对象本质在调用构造方法
-
作用是初始化对象的值
-
定义有参构造之后,如果想使用无参构造,必须显示定义一个无参构造
public class Person{
public Person(){//无参构造
}
}
public class Person{
private String name;
public Person( String name){//有参构造
this.name=name
}
}
封装
-
我们的程序要追求高内聚低耦合,
高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉,
低耦合:仅暴露少量的方法给外部使用
-
通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
封装的好处:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护增加
继承
使用extends关键字,继承就是扩展,子类是父类的扩展,子类(派生类),父类(基类)
-
java中类只有单继承,没有多继承
-
私有的属性和方法无法被继承
-
子类继承父类就会拥有父类全部的方法
-
在java中所有的类默认直接或间接继承Object类
-
继承是类和类之间的一种关系,类和类之间还有依赖、组合和聚合等关系
public Class Application{
public static void main(String[] args){
Student student=new Student();
student.say();
}
}
class Student extends Person{
}
class Person{
public void say(){
System.out.println("说了一句话")
}
}
super注意点:
- super调用父类构造方法必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
super和this的不同点:
- 代表对象不同 this代表本身调用者这个对象 super代表父类对象
- this没有继承也能使用,super只有下继承条件下才能使用
- this():本类的构造 super():父类的构造
重写
需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符范围可以扩大但不能缩小
- 重写都是方法的重写和属性无关
为什么要重写:
父类的功能子类不一定需要,或者不一定满足
不属于重写:
class B{
public static void test(){
System.out.println("B=>test()");
}
}
class A extends B{
public static void test(){
System.out.println("A=>test()");
}
}
public static void main(String[] args){
//静态方法:方法的调用只和左边定义的数据类型有关
A a=new A();
a.test();//A=>test()
B b=new A();//父类的引用指向了子类
b.test();//B=>test()
}
重写:
class B{
public void test(){
System.out.println("B=>test()");
}
}
class A extends B{
@Override //Override 重写的注释
public static void test(){
System.out.println("A=>test()");
}
}
public static void main(String[] args){
A a=new A();
a.test();//A=>test()
B b=new A();//子类重写了父类的方法
b.test();//A=>test()
}
多态
- 同一方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类,有关系的类)
多态存在的条件:
1. 有继承关系
2. 子类重写父类的方法
3. 父类引用指向子类对象
多态是方法的多态,属性没有多态
public static void main(String[] args){
Student s1=new Student();
Person s2=new Student();
s1.run();//能调用的方法都是自己的或者继承父类的
s2.run();//子类重写了父类方法,执行子类 student
//s2.eat();//父类可以指向子类,但不能调用子类独有的方法
}
class Student extends Person{
@Overrid
public void run(){
System.out.println("student");
}
public void eat(){
System.out.println("eat");
}
}
class Person{
public void run(){
System.out.println("person");
}
}
类型转换
-
父类引用指向子类的对象
-
把子类转换为父类,向上转型
Person obj=new Student();
-
把父类转换为子类,向下转型,需强制转换,才能调用Student类的方法
((Student) obj).go();
-
作用是方便方法的调用,减少重复的代码:简洁
static关键字
- 静态变量
public class Studnet{
private static int age;//静态变量 多线程
private double score;//非静态变量
public static void main(String[] args){
student s1=new Student();
System.out.println(Student.age);
System.out.println(Student.score);//不能调用,
System.out.println(s1.age);
System.out.println(s1.score);
}
}
- 静态方法
public class Studnet{
private static int age;//静态变量 多线程
private double score;//非静态变量
public static void main(String[] args){
go();//可以调用,静态方法和类一起加载,所以可以调用
run();//普通方法,不可以调用
}
public static void go(){
}
public void run(){
}
}
- 静态代码块
public class Person{
{
System.out.println("匿名代码块");//2 附初始值
}
static{
System.out.println("静态代码块");//1 但只执行一次
}
public Person(){
System.out.println("构造方法");//3
}
public static void main(String[] args){
Person p1=new Person();
System.out.println("=========");
Person p2=new Person();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h0UTe8Ez-1601718604177)(C:\Users\Administrator\Pictures\Camera Roll\4.png)]
- 静态导入包
import static java.lang.Math.random;
public class Test{
public static void main(String[] args){
System.out.println(random());//静态导入包后可以直接使用方法
}
}
抽象类
抽象的抽象:约束
存在的意义:提高开发效率
类前使用abstract关键字定义就是抽象类,方法前使用abstract关键字定义就是抽象方法
public abstract class Action{
public abstract void doSomething();
}
- 不能new抽象类,只能靠子类去实现它
- 抽象类中可以写普通方法,但如果类中有抽象方法此类必须为抽象类
接口
声明类的关键字是class,声明接口的关键字是interface
-
接口中的所有属性默认都是public static final
-
接口中的所有方法默认都是public static
public interface UserService{
int AGE=10;//一般不在接口中写属性 默认public static final
void add(String name);//默认public static
void delete(String name);
}
- 类只能单继承,接口可以多继承,使用implements实现接口
public class A implements UserService,TimeService{}
- 接口不能被实例化,因为接口中没有构造方法
- 实现接口必须重写接口中的所有方法
public class A implements UserService{
@Override
public void add(String name){
}
@Override
public void delete(String name){
}
}
内部类
-
成员内部类
可以获得外部类的所有属性和方法
public class Outer{
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
class Inner{
public void in(){
System.out.println("这是成员内部类的方法");
}
public void getID(){
System.out.println(id);
}
}
}
-
静态内部类
无法获得非静态属性和非静态方法
public class Outer{
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
static class Inner{
public void in(){
System.out.println("这是静态内部类的方法");
}
}
}
- 局部内部类
public class Outer{
public void method(){
class Inner{
public void in(){
}
}
}
}
- 匿名内部类
public class Test{
public static void main(String[] args){
//没有名字的初始化类,不用将实例保存在变量中
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
public class Test{
public static void main(String[] args){
UserService userService=new UserService(){
@Override
public void hello(){
}
};
}
}
interface UserService{
void hello();
}
异常
异常指在程序运行中出现的不期而至的各种状况
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常
运行时异常:可能被程序员避免的异常,与检查异常相反,可以在编译被忽略
错误:错误不是异常。而是脱离程序员控制的问题,错误在代码中通常被忽略
异常的体系结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QpuUJu1Y-1601718604179)(C:\Users\Administrator\Pictures\Camera Roll\3.png)]
java把异常当做对象处理,并定义了一个基类java.lang.Throwable作为所有异常的超类
Error和Exception
Error:
- Error类对象由java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
- java虚拟机运行错误(Virtual Machine Error),当JVM不再有继续执行操作所需的内存资源时将出现OutOfMemoryError。这些异常发生时,虚拟机一般会选择线程终止。
Exception:
在exception分支中有一个重要的子类RuntimeException(运行时异常)
ArrayIndexOutOfBoundsException(数组下标越界)、NullPointerException(空指针异常)
ArithmeticException(算术异常)、MissingResourceException(丢失资源)
ClassNotFoundException(找不到类)等异常,是不检查异常,在程序中可以选择捕获处理,也可以不处理。
Error和Exception的区别:
Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这些异常时,虚拟机一般选择终止线程
Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
捕获和抛出异常
总共有5个关键字try,catch,finally,throw,throws
- finally可以不要,主要用于io,资源,关闭
public class Test{
public static void main(String[] args){
int a=1;
int b=0;
try{//监控区域
System.out.println(a/b);
}catch(ArithmeticException e){//捕获异常 catch()括号中是想要捕获的异常类型
System.out.println("程序出现异常,变量b不能为0");
}finally{//处理善后工作
System.out.println("finally");
}
}
}
- 可以进行多层异常处理,但异常必须从小到大
try{
}catch(){
}catch(){
}
主动抛出异常 在方法中使用throw,在方法上使用throws
public class Test{
public static void main(String[] args){
int a=1;
int b=0;
}
public void test(int a,int b){
if(b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
System.out.println(a/b);
}
}
如果方法中处理不了这个异常,就要在方法上抛出异常
public void test(int a,int b) throws ArithmeticException{
if(b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
System.out.println(a/b);
}
自定义异常
用户自定义异常只需继承Exception类即可,大体分为下面几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理,否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常
- 在出现异常方法的调用者中捕获并处理异常
//自定义异常类
public class MyException extends Exception{
//传递数字>10
private int detail;
public MyException(int a){
this.detail=a;
}
//toString:异常的打印信息
@Override
public String toString(){
return "MyException{"+"detail="+detail+"}";
}
}
public class Test{
//可能会存在异常的方法
static void test(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{
test(11);
}catch(MyException e){
System.out.println("MyException=>"+e);
}
}
}
- 处理运行时异常时,采用逻辑去合理规范同时辅助try-catch处理
- 在多重catch快后面,可以加catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch处理潜在的异常
- 尽量去处理异常,切记只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源