Java面向对象基础到深入
Java基础 - 目录
文章目录
一、java定义的数据类型
-
基本数据类型(8种)
-
整型:byte | short | int | long(尾部加L)
-
浮点型:float(尾部加F) | double(通常用double)
-
字符型:char(中英文皆可,但是只能放一个,一般用来放转义字符)
转义字符 说明 \b 退格符 \n 换行符 \r 回车符 \t 制表符 \’’ 双引号 \’ 单引号 \\ 反斜杠 注意:转义字符就是一个字符。
-
布尔型:boolean
-
-
引用数据类型 (*)
- 类(class)
- 接口(interface)
- 字符串(String)
- 数组(Array)
-
自动类型提升
注意:当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。
byte、char、short --> int --> long --> float --> double
-
强制类型转换
注意:强制类型转换,可能导致精度损失。
//double类型转换为int类型,小数部分丢失 double d1 = 12.9; int i1 = (int)d1; //int类型转换为byte类型,导致溢出 int i2 = 128; byte b = (byte)i2; //输出:-128
-
String类型变量(引用数据类型)
注意:String类型可以和8种基本数据类型做运算,且运算只能是连接运算。
int num = 15; String numStr = "编号:"; System.out.println(numStr + num);
二、运算符
-
算术运算符
运算符 名称 备注 + 正号 / 加 / 字符串连接 - 负号 / 减 % 取模(取余) 7%5=2 ++ 自增 a=2;b=a++;(输出:a=3;b=2)
a=2;b=++a;(输出:a=3;b=3)– 自减 (原理同自增) -
赋值运算符
运算符(扩展) 备注 += i+=1;即i=i+1; -= (原理同上) *= (原理同上) /= (原理同上) %= (原理同上) -
比较运算符(关系运算符)
运算符 运算 备注 结果 == 相等于 4==3 false != 不等于 4!=3 true < 小于 4<3 false > 大于 4>3 true <= 小于等于 4<=3 false >= 大于等于 4>=3 true instanceof 检查是否是类的对象 “hello” instanceof String true 注意:"==" 不能写成 “=”。
-
逻辑运算符
注意:只能操作boolean类型。
-
位运算符注意:位运算符是直接对整数的二进制进行运算。(软件开发中不常用) -
三元运算符
//条件表达式为true,执行表达式1;为false,执行表达式2 (条件表达式) ? 表达式1 : 表达式2;
注意:三元运算符可以简化 if-else 语句。
三、程序流程控制
-
顺序结构
说明:从上到下逐行执行,中间没有如何判断和跳转。
-
分支结构
说明:根据条件选择性执行某段代码,有 if-else 和 switch-case 两种。
//if-else 结构 if(条件表达式){ 代码块1; }else if{ 代码块2; }
//switch-case 结构 switch(条件表达式){ case 常量1: 语句1; //break; case 常量2: 语句2; //break; ... case 常量n: 语句n; //break; default: 语句; //break; }
-
循环结构
说明:根据循环条件,重复执行某段代码,有 while、do…while、for、foreach四种。
注意:循环体中的break为跳出循环,continue为结束当次循环。
//for循环结构 for(初始化;条件表达式;末尾循环体){ 代码块; }
//while循环结构(先判断,再执行循环体) 初始化; while(条件表达式){ 代码块; 末尾循环体; //迭代条件 } //while(true)循环 初始化; while(1){ 代码块; if(条件表达式){ break; //达到某个条件时跳出循环 } }
//do...while循环结构(先执行循环体,再判断) 初始化; do{ 代码块; 末尾循环体; //迭代条件 }while(条件表达式);
//foreach循环结构 foreach(){ //TODO }
四、数组(Array)
-
一维数组 (*)
注意:数组长度一旦确定,就不能修改。
//静态初始化 int[] arr1 = new int[]{1,2,3,4}; String[] arr2 = new String[]{Alice,Bob,Candy}; //动态初始化 int[] arr3 = new int[5]; String[] arr4 = new String[3]; //赋值 arr3[0] = 1; //定义int[n] 赋值只能0~(n-1) arr4[0] = "Alice"; //定义String[n] 赋值只能0~(n-1) //获取数组长度 arr.length;
-
二维数组
//静态初始化 int[][] arr1 = new int[][]{{1,2},{3,4,5},{6,7}}; //动态初始化 String[][] arr2 = new String[3][2]; //方式一 String[][] arr2 = new String[3][]; //方式二 //String[][] arr2 = new String[][2]; //这种初始化是错误的 //获取长度 arr.length; arr[n].length;
//遍历二维数组 for(int i = 0;i < arr.length;i++){ for(int j = 0;j < arr[i].length;j++){ System.out.print(arr[i][j] + " "); } System.out.println(); //换行效果 }
注意:N维数组遍历,需要N个for循环。
-
数组中涉及的常见算法
-
数组元素的赋值(杨辉三角、回形数等)
//题目:创建一个长度为6的int型数组,要求数组元素的值再1-30之间,且是随机赋值,同时,要求数组元素的值各不相同。 int[] arr = new int[6]; for(int i = 0;i < arr.length;i++){ arr[i] = (int)(Math.random() * 30)+1; //随机赋值 for(int j = 0;j < i;j++){ if(arr[i] == arr[j]){ i--; //若新建的值与之间的值有相等,则重新新建值 break; } } } for(int i = 0;i < arr.length;i++){ System.out.println(arr[i]); }
注意:Math.random() 返回的是double型的值,范围是[0,1)。
-
求数值型数组中元素的max、min、avg、sum等
//1.输出数组元素的最大值 int maxValue = arr[0]; for(int i = 0;i < arr.length;i++){ if(maxValue < arr[i]){ maxValue = arr[i]; } } System.out.println("最大值为:" + maxValue); //2.输出数组元素的最小值 int minValue = arr[0]; for(int i = 0;i < arr.length;i++){ if(minValue > arr[i]){ minValue = arr[i]; } } System.out.println("最小值为:" + minValue); //3.输出数组元素总和 int sum = 0; for(int i = 0;i < arr.length;i++){ sum += arr[i]; } System.out.println("总和为:" + sum);
-
数组的复制、反转、查找(线性查找、二分法查找)
String[] arr = new String[]{"AA","BB","CC","DD","EE"}; int[] arr1 = new int[]{-2,12,24,28,35,67,85,105}; //1.数组的反转 for(int i = 0;i < arr.length / 2;i++){ String temp = arr[i]; arr[i] = arr[arr.length - i - 1]; arr[arr.length - i - 1] = temp; } //2.查找(线性查找) String dest = "DD"; //需要找到的元素 boolean isFlag = true; for(int i = 0;i < arr.length;i++){ if(dest.equals(arr[i])){ isFlag = false; System.out.println("找到指定元素,位置为:" + i); break; } } if(isFlag){ System.out.println("抱歉,没有找到指定元素!"); } //3.二分法查找(有序数据集合,且不存在重复的数据) int dest1 = 12; int head = 0; //初始的首索引 int end = arr1.length - 1; //初始的末索引 boolean isFlag1 = true; while(head <= end){ int mid = (head + end) / 2; if(dest1 == arr1[mid]){ isFlag1 = false; System.out.println("找到指定元素,位置为:" + mid); break; }else if{ end = mid -1; }else{ head = mid +1; } } if(isFlag1){ System.out.println("抱歉,没有找到指定元素!"); }
注意:使用二分法查找,数组必须是有序的,且不存在重复的数据。
-
数组元素的排序算法
说明:排序的目的,是为了更快速地查找。
-
选择排序
-
直接选择排序
-
堆排序
-
-
交换排序
- 冒泡排序
- 快速排序
-
插入排序
- 直接插入排序
- 折半插入排序
- Shell排序
-
归并排序
-
桶式排序 -
基数排序
-
-
五、面向对象基础
-
概念
- 类:对一类事物的描述,是一个抽象的、概念上的定义,例如:汽车。
- 对象:是实际存在的该类的事物的每个个体,也称为实例(instance),例如:奔驰。
-
权限修饰符
-
Java类及类的成员
说明:包含属性 (*)、方法 (*)、构造器 (*)、代码块、内部类。
//类的声明 [权限修饰符] [关键字] class 类名{ 属性; 方法; } //方法的声明 [权限修饰符] [关键字] 返回值类型 方法名(形参列表){ 方法体; }
//方法的调用 public class Test{ //方式一 Test o = new Test(); o.show(10); //方式二 new Test().show(10); //匿名对象(开发中一般不用这种方法) public void show(int i){} }
//以下是一个完整的例子 public class Person{ //1.属性、或成员变量(field) String name; int age; //2.构造器 //构造器作为一种方法,负责类中成员变量(属性)的初始化 public Person(){} public Person(String name,int age){ name = na; age = ag; } //3.方法,或函数(method) public void sleep(){ System.out.println("人可以睡觉"); } //4.代码块 { name = "Alice"; age = 20; sex = "female"; } //5.内部类 class{ String name; float height; } }
-
面向对象三大特征
封装、继承、多态
-
其他关键字
this,package,import,final(修饰常量),extends、…
六、面向对象深入(上)
-
类的成员之一:方法
-
方法的重写(Override)——体现多态性
定义:在子类中对父类中继承来的方法进行改造,方法名和形参列表应该一样。
注意:
- 子类和父类的返回值类型必须相同。
- 子类不能重写父类中声明为private权限的方法。
- 子类重写的方法的权限修饰符不小于父类被重写方法的权限修饰符。
-
方法的重载(Overload)——不体现多态性
定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
//方法的重载的例子 public class OverLoad{ public static void main(String[] args){ OverLoad o =new OverLoad(); o.show("Alice",10); //调用方法一 o.show(10,"Alice"); //调用方法二 } public void show(String s,int i){ //方法一 } public void show(int i,String s){ //方法二 } }
-
可变形参的方法
定义:允许定义能和多个实参相匹配的形参。
//可变形参的例子 public class MethodArgsTest{ public static void main(String[] args){ MethodArgsTest test =new MethodArgsTest(); test.show(10); //调用方法一 test.show("hello"); //调用方法二(若方法二被注释,则调用方法三) test.show("hello","world"); //调用方法三 test.show(); //调用方法三 } public void show(int i){ //方法一 } public void show(String s){ //方法二 } public void show(String ... strs){ //方法三(可变形参的方法) } }
注意:当调用可变形参的方法时,传入参数的个数可以是0~N个,不过参数类型必须一致。
-
方法参数的值传递机制
形参和实参的定义:
- 形参:方法定义时,声明的小括号内的参数。
- 实参:方法调用时,实际传递给形参的数据。
-
递归方法(recursion)
定义:一个方法体内调用自身。
//递归方法的例子:n个数求和 public class RecursionTest{ public static void main(String[] args){ int sum = 0; RecursionTest test = new RecursionTest(); System.out.println(test.getSum(100)); //输出1+2+3+...+100的和 } public int getSum(int n){ if(n == 1){ return 1; }else{ return n + getSum(n - 1); //返回1+2+3+...+n的和 } } }
-
-
匿名对象
//匿名对象在开发中一般这样使用 public class Mall{ Mall mall = new Mall(); mall.show(new Phone()); //匿名对象 } class PhoneMall{ public void show(Phone phone){ phone.sendEmail(); phone.playGame(); } }
-
OOP特征之一:封装和隐藏
封装的体现:
- 将类的属性私有化(private),同时,提供公共的(public)方法来获取(get)和设置(set)属性的值。
- 不对外暴露私有的方法。
- 单例模式。
程序设计的追求:
-
高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
-
低耦合:仅对外暴露少量的方法用于使用。
//封装类的例子(没有封装的情况) public class AnimalTest{ public static void main(String[] args){ Animal a = new Animal(); a.name = "多多"; a.age = 1; a.legs = 4; a.show(); } } class Animal{ String name; int age; int legs; public void eat(){} public void show(){ System.out.println("name="+name+",age="+age+",legs="+legs); } }
//封装类的例子(封装了后的情况) public class AnimalTest{ public static void main(String[] args){ Animal a = new Animal(); a.name = "多多"; a.age = 1; //a.legs = 4; //legs是Animal类的私有属性,外部不可调用了 a.setLegs(6); a.show(); } } class Animal{ String name; int age; private int legs; //Animal类的私有属性 public void setLegs(int l){ if(l >= 0 && l % 2 == 0){ legs = l; }else{ //抛出异常 } } public void eat(){} public void show(){ System.out.println("name="+name+",age="+age+",legs="+legs); } }
-
类的成员之二:构造器
说明:
- 如果没有显式的定义类的构造器的话,系统默认提供一个空参的构造器。
- 定义构造器的格式:权限修饰符 类名(形参列表){ }。
- 一个类可以定义多个构造器。
- 一个类中定义的多个构造器,彼此构成重载。
- 一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器了。
//构造器的作用: //1.创建类的对象:new + 构造器 例如:Person p = new Person(); //空参的构造器 //2.初始化对象的属性 (*) public class PersonTest{ public static void main(String[] args){ Person p = new Person(); p.name = "Alice"; Person p1 = new Person("Alice"); System.out.println(p1.name); //输出了Alice } } class Person{ String name; int age; //构造器 public Person(){ } public Person(String n){ name = n; //初始化操作 } //方法 public void eat(){} }
-
this关键字
说明:
- this可以理解为当前对象的(当前类的)。
- 一般使用“this.属性”或“this.方法”的方式,调用当前对象的属性或方法,但通常情况下可以省略。
- 在类的构造器中,可以使用“this(形参列表)”的方式,调用本类中的其他构造器,且必须写在首行。
//this关键字,用于属性和形参同名时的区分 //1.this.name代表的是属性 //2.name代表的是形参 //3.this(形参)调用构造器 class Person{ //属性 String name; int age; //构造器 public Person(){ } public Person(String name){ this(); //调用Person()构造器,必须写在行首 this.name = name; } public Person(String name,int age){ this(name); //调用Person(String name)构造器 //this.name = name; //冗余代码 this.age = age; } //方法 public void setName(String name){ this.name = name; //this.属性 = 形参; } public String getName(){ return name; //没有形参时,name代表的就是属性 } }
七、面向对象深入(中)
-
OOP特征之二:继承性
作用:
- 减少了代码的冗余,提高了代码的复用性。
- 便于功能的扩展。
- 为之后多态性的使用,提供了前提。
注意:
- java中的类是单继承的。
- 子类继承父类的属性及方法,父类中有的属性及方法,子类中无需再定义。
- 如果子类中有与父类同名的方法,则系统优先使用子类中的方法(即方法重写)。
- 父类中的private属性或方法,子类中不可直接调用,但可以使用public的get/set方法调用。
//继承使用关键字extends //子类:Student.java public class Student extends Person{ //String name; //String sex; String grade; //子类特有属性(年级) public static void main(String[] args){ Student stu = new Student(); stu.eat(); //使用父类中的eat方法 stu.sleep(); //使用父类中的sleep方法 } } //父类:Person.java public class Person{ String name; String sex; public void sleep(){ System.out.println("人可以睡觉"); } public void eat(){ System.out.println("人可以吃饭"); } }
-
super关键字
说明:
- super可以理解为父类的。
- 用于调用父类的属性、方法、构造器,使用方法与this相似。
- 要想调用父类中被重写的方法,则必须使用关键字super。
-
OOP特征之三:多态性
说明:一个事物的多种形态,父类的引用指向子类的对象(或子类的对象赋给父类的引用)。
//一般情况下 Person p = new person(); //对象的多态性 //父类的引用指向子类的对象 Person p = new Man(); //编译看左边,运行看右边 //只能调用父类自己有的方法,执行的是子类重写的方法(不能调用子类的特有的方法) //父类中有eat()和walk()方法,且子类重写过了 p.eat(); p.walk();
注意:
- 只能调用父类自己有的方法。
- 实际执行的是子类中重写的方法。
- 多态性只适用于方法,不适用于属性。
public class AnimalTest{ public static void main(String[] args){ AnimalTest test = new AnimalTest(); test.func(new Dog()); test.func(new Cat()); } //多态的实际应用 public void func(Animal animal){ animal.eat(); animal.shout(); } //如果没有多态性 // public void func(Dog dog){ // dog.eat(); // dog.shout(); // } // public void func(Cat cat){ // cat.eat(); // cat.shout(); // } } //父类 class Animal{ public void eat(){ System.out.println("动物进食"); } public void shout(){ System.out.println("动物叫"); } } //子类 class Dog{ public void eat(){ System.out.println("狗吃骨头"); } public void shout(){ System.out.println("汪汪汪!"); } } class Cat{ public void eat(){ System.out.println("猫吃鱼"); } public void shout(){ System.out.println("喵喵喵!"); } }
-
instanceof关键字
说明:
- 判断对象a是否是类A的实例,若是,返回true;若不是,返回false。
- 为了对象强制转换时不出现异常,通常用instaceof做判断。
//a instanceof A //a:对象 A:类 if(p inatanceof Student){}
注意:如果a instanceof A返回true,a instanceof B也返回true,则B是A的父类。
//Object是Student的父类 System.out.println(p inatanceof Student); //true System.out.println(p inatanceof Object); //true
八、面向对象深入(下)
-
static关键字
使用场景:
-
如何确定一个属性需要static?
- 属性可以被多个对象所共享,不会随着对象的不同而不同的。
-
如何确定一个方法需要static?
- 操作静态属性的方法,通常设置为static的。
- 工具类中的方法,习惯上声明为static,例如:MathUtil、ArraysUtil等。
说明:
- 用来修饰属性、方法、代码块、内部类。
- static修饰的属性称为静态变量,所有实例化对象共用此属性(即多个对象共享一个静态变量)。
//static修饰变量 public class StaticTest{ public static void main(String[] args){ //可以通过“类.静态变量”调用,所有的对象共享(不需要造对象就可以用) Chinese.nation = "CN"; Chinese c1 = new Chinese(); c1.name = "张三"; c1.sex = "男"; //c1.nation = "CN"; Chinese c2 = new Chinese(); c2.name = "李四"; c2.sex = "男"; System.out.println(c2.nation); //c1.nation赋值为"CN",c2.nation的值也为"CN" } } class Chinese{ String name; String sex; static String nation; //静态属性 }
//static修饰方法 public class StaticTest2 { public static void main(String[] args) { Chinese.show(); //可以通过“类.静态方法”调用 //Chinese c1 = new Chinese(); //c1.show(); } } class Chinese { String name; String sex; public void eat() { System.out.println("中国人吃米饭"); } public static void show() { System.out.println("我是中国人"); } }
注意:
- 在静态方法内,不能使用this、super关键字。
- 静态方法只能调用静态方法,但非静态方法可以调用静态方法。
- 由于类只会加载一次,所以静态变量在内存中也只会存在一份。
-
如何确定一个属性需要static?
-
单例(Singleton)模式
作用:使得某个类只能存在一个对象实例。
使用场景:
//最简式 class 类名{ public static 类名 instance = new 类名(); } //饿汉式 //优点:线程安全。 //缺点:对象加载时间过长,可能导致系统负担。 class 类名{ //1.私有化类的构造器(目的是不让其他类new出这个类的对象) private 类名(){} //2.声明当前类的对象 private static 类名 instance = new 类名(); //3.声明getInstance,调用即返回当前类的对象 public static 类名 getInstance(){ return instance; } } //懒汉式(推荐使用) //优点:线程安全;需要时才创建,减小系统负担。 class 类名{ //1.私有化类的构造器(目的是不让其他类new出这个类的对象) private 类名(){} //2.声明当前类的对象 private static 类名 instance = null; //3.声明getInstance,调用即返回当前类的对象 public static synchronized 类名 getInstance(){ if(instance == null){ instance = new 类名(); } return instance; } }
-
类的成员之三:代码块(初始化块)
作用:用来初始化类、对象。
说明:
-
静态代码块
- 初始化类的信息。
- 随着类的加载而执行(不需要主动调用),只执行一次。
- 只能调用静态的属性、方法。
-
非静态代码块
- 初始化对象的信息。
- 随着对象的创建而执行(不需要主动调用),每创建一个对象执行一次。
//非静态代码块 { } //静态代码块 static{ }
注意:
- 每个类中每种代码块只需要写一次即可。
- 代码块修饰符只能使用static。
-
静态代码块
-
final关键字
说明:
-
用来修饰类、方法、变量。
- 修饰类:则这个类就不能被其他类继承。
- 修饰方法:则子类就不能重写。
- 修饰属性:此属性为常量,不能再被赋值了。
- 一般用static final修饰全局常量。
//final修饰类A,则A不能被任何类继承 final class A{ } //final修饰方法aA,则子类就不能重写 public final void aA(){ }
-
用来修饰类、方法、变量。
-
abstract关键字 (*)
说明:
-
用于修饰类和方法。
- 修饰类:则这个类不可被实例化(不可被new)。
- 修饰方法:则这个方法不可被对象调用(即不需要方法体),只用于提供给子类重写,且子类必须重写。
abstract class A{ public abstract void a(); //抽象方法,提供给子类重写 } class B extends A{ @Override public void a(){} //子类必须重写父类中的abstract方法 }
-
用于修饰类和方法。
-
接口(interface)(*)
作用:Java中的类不支持多继承,接口是为了让Java实现类多重继承的效果(多实现)。
说明:
- 接口不可以被实例化(即不可以new接口)。
- 其他类可以直接通过"接口名.属性"或"接口名.方法"调用。
- 开发中,一般通过让类去实现(implements)的方式来使用。
//接口的声明 interface 接口名{ //1.属性 [ public static final ] 数据类型 属性名 = 初始值; //2.抽象方法 [ public abstract ] void 方法名(); }
//接口的实现 class B implements A{ @Override public void aA(){} //子类重写接口中的抽象方法 } interface A{ public static final int i = 0; void aA(); //抽象方法 }
注意:
- 接口中定义的属性默认为public static final的(接口中的属性外部不能赋值)。
- 接口中属性必须赋初始值。
- 接口与接口之间可以多继承。
//接口多继承 interface A{} interface B{} interface C extends A,B{}
-
代理(Proxy)模式
作用:为其他对象提供一种代理以控制对这个对象的访问。
使用场景:
//调用 public class ProxyTest{ public static void main(String[] args){ Proxy s = new Proxy(new RealStar()); s.signContract(); s.sing(); } } //接口 interface Star{ void signContract(); //签合同 void sing(); //唱歌 } //明星类(被代理类) class RealStar implements Star{ public void signContract(){ } public void sing(){ System.out.println("明星唱歌~"); } } //经纪人类(代理类) class Proxy implements Star{ private Star real; public Proxy(Star real){ //初始化 this.real = real; } public void signContract(){ System.out.println("经纪人签合同"); } public void sing(){ real.sing(); //自己做不了的事,才调用被代理类 } }
-
类的成员之四:内部类
注意:开发中不常用,源码中较多。
说明:
- 内部类分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)。
-
使用方式:
- 可以调用外部类的结构。
- 可以被static、final(此类不能被继承)、abstract修饰。
- 可以被4种不同的权限修饰。
- 可以在内部定义属性、方法、构造器等。
class A{ //成员内部类 class B{ } public void aA(){ //局部内部类 class C{ } } }
九、异常处理
-
异常概述
说明:
-
Error:Java虚拟机无法解决的严重问题,一般不编写针对性的代码进行处理。
- 栈溢出
- 堆溢出
- …
-
Exception:因编程错误或偶然的外在因素导致的一般性问题,可以通过编写针对性的代码进行处理。
- 空指针访问
- 试图读取不存在的文件
- 网络连接中断
- 数组角标越界
- …
-
Error:Java虚拟机无法解决的严重问题,一般不编写针对性的代码进行处理。
-
异常处理 (*)
//方式一:try-catch-finally try{ //可能会出现异常的代码 }catch(异常类型1 变量名1){ //异常处理方法 }catch(异常类型2 变量名2){ //异常处理方法 } ... finally{ //一定会执行的代码 } //方式二:throws public void 方法名() throws 异常类型{ //可能会出现异常的代码 }
注意:throws的方式只是将异常抛给方法的调用者,并没有真正将异常处理掉。
-
手动抛出异常
//抛出异常 throw new 异常类型(message);//message:填写异常描述信息 //例如:throw new RuntimeException("您输入的数据非法!"); //获取异常描述 e.getMessage();
-
用户自定义异常类
注意:必须继承于现有的异常体系。
public class MyException extends 现有的异常类型{ //例如:extends Exception //提供全局常量(序列号) static final long serialVersionUID = -454658879878546L; //可以自定义 //提供重载的构造器 public MyException(){ } public MyException(String msg){ super(msg); } }
class 类名{ public void 方法名() throws MyException{ try{ throw new MyException("发生了一个自定义的异常"); }catch(exception e){ System.out.println(e.getMessage()); } } }
本文地址:https://blog.csdn.net/sergy457/article/details/107899990