java语言的环境搭建
JDK:java开发工具包
JRE: java运行环境
JVM: 虚拟机
jdk 是给开发人员使用的, jre和jvm是给普通用户使用
HelloWord
java程序编写-编译-运行过程
编写:我们将编写的java代码保存在以”.java“结尾的源文件中‘
编译:使用javac.exe命令编译我们的java源文件。格式javac 源文件名.java
运行:使用java.exe命令解释运行我们的字节码文件。格式:java类名
在一个源文件中可以声明多个class,但是只能最多有一个类声明public的,而且要求声明为public的类名必须跟源文件名相同
JAVA基础语法
关键字(keyword)
定义:被java语言赋予了特殊意义,用做专门用途的字符串(单词)
1.标识符:凡是自己可以起名字的地方都叫标识符。
比如类名,变量名,方法名,接口名,包名
由26个英文字母大小写,0-9 ,__或 $ 组成
数字不可以开头。
不可以使用关键字和保留字,但能包含关键字和保留字。
Java中严格区分大小写,长度无限制。
标识符不能包含空格。
变量
变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值
该区域的数据可以在同一类型范围内不断变化
变量的分类按数据类型:基本数据类型 引用数据类型
基本数据类型 :byte,short,int,long(整数类型) float,double(浮点类型)boolean(布尔型)char(字符型)
引用数据类型:类**(class),接口(interface),数组([ array])**
byte(一个字节=8bit) -128~127
short(两个字节)
int(四个字节)
long(八个字节)
float(四个字节)
double(八个字节)
char(一个字符) 通常使用一对‘ ’,内部也只能写一个字符
运算符
算术运算符
赋值运算符
比较运算符(关系运算符)
逻辑运算符 & && | || ^
逻辑运算符操作都是boolean类型的变量
&与&&区别
相同点:当符号左边为true时,两者都会执行符号右边的计算
不同点:当符号左边为false时,&继续执行符号右边的计算,&&不在执行右边的计算
位运算符
三元运算符
结构:(条件表达式)?表达式1:表达式2
循环
循环语句的四个组成部分
1.初始化部分
2.循环条件部分
3.循环体部分
4.迭代部分
三种循环结构
1.for循环结构
for(1;2;4){
3
}
执行过程:1-2-3-4-2-3-4…
2.while循环结构
1
while(2){
3;
4;
}
执行过程:1-2-3-4-2-3-4…
3.do-while循环结构
1
do{
3;
4;
}while(2);
执行过程:1-3-4-2-3-4-2…
无限循环结构
while(true)或for(;😉
如何结束一个循环结构?
方式1:当循环条件为flase时候
方式2:在循环体中执行break
数组
数组的常见概念
数组名
下标(或索引)
元素
数组的长度
内存结构
栈(stack:)局部变量
堆(heap)new出来的结构:对象数组
方法区:常量池 静态域
面向对象
1.Java类及类的成员:属性,方法,构造器,代码块,内部类
2.面向对象的三大特征:封装,继承,多态
3.其它关键字:this,super,static,final,abstract,interface,package等
“人把大象装冰箱”
1.面向过程:强调是功能行为,以函数为最小单位,考虑怎么做
把冰箱门打开,抬起大象塞进冰箱,关闭冰箱门
2.面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
面向对象两个对象:
类:对一类事物的描述,是抽象的,概念上的定义
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
面向对象程序设计的重点是类的设计
局部变量与成员变量的区别
/**
类中属性的使用
- @author wangxin
*属性(成员变量) vs 局部变量
*1.相同点 - 1.1定义变量的格式,数据类型 变量名 = 变量值
- 1.2先声明,后使用
- 1.3变量都有其对应的作用域
*2.不同点 - 2.1 在类中声明的位置不同
- 属性:直接定义在类的一对{}内
- 局部变量:声明在方法内,方法形参,代码块内,构造器形参,构造器内部的变量
- 2.2关于权限修饰符不同
- 属性:可以在声明属性时,指明其权限,使用权限修饰符
- 常用的权限修饰符:private public 缺省 protected
- 局部变量不能使用权限修饰符
- 2.3默认初始化值
- 属性:类的属性,根据其类型,都有默认初始化值
- 局部变量没有默认初始化值。意味着,我们在调用局部变量之前,一定要显示赋值
- 特别的:形参在调用时,我们赋值即可
- 2.4在内存中加载的位置
- 属性:加载到堆空间中
- 局部变量:加载到栈空间
- 一.设计类,其实就是设计类的成员
- 属性 = 成员变量 = field = 字段·域
- 方法 = 成员方法 = 函数
方法的分类:按照是否有形参及返回值
无形参 无返回值 void方法名(){}
无形参 有返回值 返回值类型 方法名(){}
有形参无返回值 void方法名(形参列表){}
有形参有返回值 返回值类型 方法名(形参列表){}
面向对象思想编程内容的三条主线分别是什么
1、类及类的成员:属性,方法,构造器,代码块,内部类
2、面向对象的三大特征:继承,封装,多态
3、其他关键字:
面向对象中类和对象的理解,并指出二者的关系?
类:抽象的,概念上的内容。
对象:实实在在存在的一个个体
对象是由类派生出来的
类和对象的创建和执行操作有那三步?
创建类
类的实例化
调用对象的结构"对象.属性" “对象.方法”
JVM规范
虚拟机栈,即为平时提到的栈结构。 我们将局部变量存储在栈结构中
堆,我们将new出来的结构(比如;数组,对象)加载在堆空间中。补充:对象的属性(非static)加载到堆空间中
方法区:类的加载信息,常量池,静态域
*一. “理解万事万物皆对象”
*1.在java语言范畴中,我们都将功能,结构等封装到类中,通过类的实例化,来调用具体的功能结构
*2.涉及到Java语言与前端Html 后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类,对象
匿名对象的使用
1.理解:我们创建的对象,没有显示的赋给一个变量名,即为匿名对象
2.特征:匿名对象只能调用一次
3.使用:
方法的重载
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
重载的特点:
与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别
递归方法
递归方法:一个方法体内调用它自身。
Java方法中的参数传递机制的具体体现?
基本数据类型:数据值
引用数据类型:地址值
封装
封装就是把类的属性和方法使用private修饰,不允许类的调用者直接访问
封装的体现:
1.我们将类的属性私有化(privice),同时,提供公共的方法来获取和设置值
2.不对外暴露的私有的方法
继承(extends)
继承性的好处:
1、减少了代码的沉余,提高代码的复用性
2、便于功能的扩展
3、为多态性的使用,提供了前提
继承性的格式:class A extends B{}
A:子类,派生类 subclass
B:父类 superclass
体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法
特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。
只是因为封装性的影响,使得子类不能直接调用父类的结构而已
重写
在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置,覆盖
重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法
重写的规定:
方法的声明:权限修饰符 返回值类型 方法名(形参列表){//方法体}
约定俗称:子类中的叫重写的方法,父类中叫被重写的方法
子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
特殊情况:子类不能重写父类中声明为private权限的方法
返回值类型
1.父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型也只能是void
Super关键字
1.super理解为:父类的
2.super可以用来调用:属性,方法,构造器
3.super的使用
3.1 我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显示调用父类中声明的属性或方法,但是,通常情况下, 我们习惯省略"super."
3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要在子类中调用父类中声明的属性,则必须显示的使用"super.属性"的方式,表明调用的是父类中声明的属性。
多态性(运行时行为)
理解多态性:可以理解为一个事物的多种形态
何为多态性:
对象的多态性:父类的引用指定子类的对象(子类的对象赋给父类的引用)
Person p = new Man();
//p是变量 Man是Person的子类
多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法—虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法
多态性使用前提:
1.类的继承关系
2.要有方法的重写
对象的多态性,只适用于方法,不适于属性 (编译和运行都看左边)
方法重载跟重写的区别
方法重载:在同一类中 可以定义多个同名的方法,但是它们的形参列表不能相同,构造器也可以实现方法重载
方法重写:在子类继承父类方法之后 可以对父类的方法进行覆盖
Object类
Object类是所有Java类的根父类
Object类中的功能(属性,方法)就具有通用性。
属性:无
方法:equals() / toString() / getClass()/ hashCode/ clone()/…
面试题:==跟equals()的区别
一 回顾==的使用
==:运算符
1.可以使用在基本数据类型变量和引用数据类型变量中
2.如果比较的是基本数据类型,比较两个变量保存的数据是否相等(不一定类型要相同)
如果比较的是引用数据类型变量,比较两个对象的地址值是否相同,即两个引用是否指向同一个地址
二. equals()方法的使用:
1.是一个方法,而非运算符
2.只适用于引用数据类型
3.Object类中equals()的定义:
public boolean equals(Object obj){
return (this == obj)
}
说明:Object类中定义的equals()和==的作用是相同的,比较两个对象的地址值是否相同,即两个引用是否指向同一个地址
4.像String、Date、File、包装类都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相等,而是比较两个对象的"实体内容"是否相等
5.通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容是否相同",那么我们就需要对Object类中的equals()进行重写
Java中的JUnit单元测试(eclipse)
1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步
2.创建Java类 进行单元测试
3.此时的Java类要求 此类是public的 此类提供公共的无参构造器
4.此类中声明单元测试方法
此时的单元测试方法:方法权限是public,没有返回值,没有形参
5.此单元方法上需要声明@Test,并在单元测试中导入
包装类的使用
1.Java提供了8中基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
2.掌握的 :基本数据类型,包装类,String三者之间的相互转换
//基本数据类型转包装类,调用包装类的构造器
@Test
public void test1(){
int num = 10;
Integer in = new Integer(num);
System.out.println(in.toString());
}
//基本数据类型、包装类 ----> String类型
//调用String的valueOf()
@Test
public void test2(){
int num = 10;
String s = String.valueOf(num);
System.out.println("s = " + s);
}
//String类型----> 基本数据类型、包装类
//调用包装类的parseXxx(String s)
@Test
public void test3(){
String s = "123";
int i = Integer.parseInt(s);
System.out.println("i = " + i);
}
向下转型
使用强转符:()
Person p = new Man();
可能ClassCastException异常。
使用instanceof在进行向下转型前判断
if(p instanceof Man){
Man m = (Man)p;
}
static关键字的使用
1.static:静态的(随着类的加载而加载)
2.static可以用来修饰:属性、方法、代码块、内部类
使用static修饰属性:静在变量(或类变量)
3.1属性,按是否使用static修饰,又分为:静态属性vs非静态属性(实例变量)
实例变量,我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
3.2 static修饰属性的其他说明,
静态变量随着类的加载而加载,可以通过类.静态变量的方式进行调用
静态变量加载要早于对象的创建
由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中
类变量 实例变量
类: yes no
对象 yes yes
使用static修饰方法:静态方法
随着类的加载而加载,可以通过类.静态方法的方式进行调用
静态方法 非静态方法
类(Person): yes no
对象 yes yes
静态方法中,即可以调用非静态的方法或属性,也可以调用静态的方法或属性
static注意点:
在静态的方法内,不能使用this关键字,super关键字
关于静态属性和静态方法的使用,大家从生命周期的角度去理解
在开发中 如何确定一个属性是否要声明为static的?
属性是可以被多个对象共享的,不会随着对象的不同而不同的。
在开发中 如何确定一个方法是否要声明为static的?
操作静态属性的方法,通常设置为static的
工具类中的方法,习惯上声明为static的。比如:Math Arrays Collections
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9DVntAh0-1663122007889)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220811095846364.png)]
//static关键字的应用
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
System.out.println("c1 = " + c1.getId());
Circle c2 = new Circle();
System.out.println("c2 = " + c2.getId());
System.out.println("Circle.getTotal() = " + Circle.getTotal());
Circle c3 = new Circle(3.5);
System.out.println("c2 = " + c3.getId());
}
}
class Circle{
private double radius;
private int id;
public Circle(){
id = init++;
total++;
}
public Circle(double radius) {
this();
this.radius = radius;
// id = init++;
// total++;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static int getTotal() {
return total;
}
public static void setTotal(int total) {
Circle.total = total;
}
public static int getInit() {
return init;
}
public static void setInit(int init) {
Circle.init = init;
}
private static int total;//记录园的个数
private static int init = 1001;
//方法
public double findArea(){
return 3.14 * radius * radius;
}
}
单例设计模式(懒汉式 饿汉式)
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
单例的饿汉式
public class Singleton {
public static void main(String[] args) {
Bank bank = Bank.getInstance();
Bank bank2= Bank.getInstance();
System.out.println( bank == bank2);
}
}
class Bank{
//1.私有化类的构造器
private Bank(){
}
//2.内部创建类的对象
//4.要求此对象也必须声明为静态的
private static Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance(){
return instance;
}
}
懒汉式(什么时候用什么时候造)
public class Singleton1 {
public static void main(String[] args) {
Order order = Order.getInstance();
Order order1 = Order.getInstance();
System.out.println(order);
System.out.println(order1);
}
}
class Order{
//1.私有化类的构造器
private Order(){
}
//2.声明当前类对象,没有初始化
//4.此对象也必须声明为static
private static Order instance = null;
//3.声明public、static的返回当前类的对象方法
public static Order getInstance(){
if (instance == null){
instance = new Order();
}
return instance;
}
}
区分饿汉式VS懒汉式
懒汉式:好处:延迟对象创建
饿汉式:坏处:对象加载时间过长
好处:饿汉式是线程安全的
代码块(静态代码块or 非静态代码块)
/**
* 类的成员四 代码块{}
* 1.代码块的作用:用来初始化类、对象
* 2.代码块如果有修饰的话 只能用static修饰
* 3.分类:静态代码块 vs 非静态代码块
*
* 4.静态代码块
* 内部可以有输出语句
* 随着类的加载而执行,而且只执行一次
* 作用:初始化类的信息
* 如果一个类中声明多个静态代码块 执行是按照创建的先后顺序执行
* 5.非静态代码块
* 内部可以有输出语句
* 随着对象的创建而执行
* 每创建一个对象,就执行一次非静态代码块
*
* 对象可以赋值的位置
* 默认初始化值
* 显示初始化
* 构造器中初始化
* 有了对象后,可以通过"对象.属性"或"对象.方法"的方式进行赋值
* 在代码块中赋值
*/
public class BlockTest {
public static void main(String[] args) {
String descs = Person.desc;//descs是变量
String descs1 = Person.desc;
Person person = new Person();
System.out.println(person.age);
System.out.println(person.name);
Person person1 = new Person();
Person.setDesc();
}
}
class Person{
//属性
String name = "信心子";
int age;
static String desc = "我是程序员";
//构造器
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//static代码块
static {
System.out.println("static代码块");
}
//非static代码块
{
System.out.println("非static代码块");
}
//方法
public void eat(){
System.out.println("吃饭");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void setDesc(){
System.out.println("hhaha");
}
final(最终的)关键字
/**
* final:最终的
* 1.final可以修饰的结构:类,方法,变量
* 2.final 用来修饰一个类:此类就不能被其他类所继承
* 比如:String类,System类,StringBuffer类
* 3.final 用来修饰方法:表明此方法不能被重写
* 比如:Object中getClass();
* 4.final 用来修饰变量:此时的“变量”就成为是一个常量
* 4.1 final修饰属性:可以考虑赋值的位置有:显示初始化,代码块中初始化,构造器中初始化
* 4.2 final修饰局部变量:
* 尤其是使用final修饰形参时,表明此形参是一个常量,当我们调用此方法时,给常量形参赋一个实参
* 一旦赋值以后,就只能在方法体内使用此实参,但不能重新赋值
*
* static final 用来修饰属性:全局常量
*/
public class FinalTest {
int width = 10;
public void dowidth(){
width = 20;
}
public static void main(String[] args) {
int num = 10;//num(变量)
num = num + 5;//5(一种常量)
}
}
//final 用来修饰一个类:此类就不能被其他类所继承
final class FinalA{
}
class aa extends FinalA{
}
//final 用来修饰方法:表明此方法不能被重写
class a{
public final void show(){
}
}
class b extends a{
public void show(){
}
}
abstract(抽象)关键字使用
/**
* abstract关键字使用--->抽象使用前提:继承性
* 1.abstract:抽象的
* 2.abstract可以用来修饰的结构:类,方法
* 3.abstract修饰类:抽象类 abstract class Person{}
* >此类不能实例化(造对象new)
* >抽象类中一定有构造器,便于子类实例化调用
* >开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作
* 4.abstract修饰方法:抽象方法 public abstract void eat();
* >抽象方法只有方法的声明,没有方法体
* >包含抽象方法的类,一定是抽象类,反之,抽象类可以没有抽象方法
* >若子类重写了父类中的所有的抽象方法后,此子类方可实例化
* >若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
*/
public class AbstractTest {
public static void main(String[] args) {
//一旦Person类抽象了,就不可实例化
// Person person = new Person();
// person.eat();
}
}
abstract class Person{
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
public void walk(){
System.out.println("人走路");
}
}
接口Interface使用
/**
* 接口的使用
* 1.接口使用interface来定义
* 2.在Java中,接口和类是并列的两个结构
* 3.如何定义接口,定义接口中的成员
* 3.1 jdk7及以前,只能定义全局常量和抽象方法
* >全局常量:public static final的,但是书写时,可以省略不写
* >抽象方法:public abstract的
* 3.2 jdk8:除了定义全局常量和抽象方法之外,还可以定义静态方法,默认方法(略)
* 4.接口中不能定义构造器,意味着接口不能实例化
* 5.Java开发中,接口通过让类去实现(implements)的方式来使用
* 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
* 如果实现类没有覆盖接口中的所有抽象方法,则此实现类仍为一个抽象类
* 6.Java类可以实现多个接口 --->弥补了Java单继承性的局限性
* 格式 class AA extends BB implements CC,DD,EE
* 7.接口与接口之间可以继承,而且可以多继承
* 8.接口的具体使用,体现多态性
* 9.接口,实际上可以看做一种规范
*/
public class Interface {
public static void main(String[] args) {
System.out.println(Flyable.MIN_SPEED);
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 7900;
int MIN_SPEED = 1;//省略了public static final
//抽象方法
public abstract void fly();
void stop();//省略了public abstract
}
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("通过引擎飞");
}
@Override
public void stop() {
System.out.println("驾驶员减速停止");
}
}
内部类
/**
* 内部类
* 1.Java中允许将一个类A声明在另一个类B中,则A就是内部类,类B称为外部类
* 2.内部类的分类:成员内部类 VS 局部内部类(方法内,代码块内,构造器内)
* 3.成员内部类:
* 一方面,做为外部类的成员:
* >调用外部类的结构
* >可以被static修饰
* >可以被4种不同权限修饰
* 另一方面 作为一个类:
* >类内可以定义属性,方法,构造器等
* >可以被final修饰,表示此类不能被继承,言外之意,不使用final,就可以被继承
* >可以被abstract修饰
* 4.关注如下三个问题
* 4.1如何实例化成员内部类的对象
* 4.2如何在成员内部类中区分调用外部类的结构
* 4.3开发中局部内部类中的使用
*/
抽象类和接口有哪些共同点和区别
相同点:不能被实例化,都可以包含抽象方法
不同点:抽象类:有构造器。接口:不能声明构造器
类:单继承 接口:多继承
类与接口:多实现
异常
Error:
Java虚拟机无法解决的严重问题。如:JVM系统内部错误,资源耗尽等严重情况
一.异常体系结构
java.lang.Throwable
java.lang.Error:一般不编写针对性的代码进行管理
java.lang.Exception:可以进行异常处理
编译时异常(checked)
IOException
FileNotFoundException
运行时异常(unchecked)
NullPointerException
ArrayIndexOutOfBoundsException
ClassCastException
NumberFormatException
/**
* 异常的处理:抓抛模型
*
* 过程一:“抛” :程序在正在执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象
* 并将此对象抛出、
* 一旦抛出对象以后,其后的代码不在执行
*
* 过程二:“抓”:可以理解为异常的处理的方式 1.try - catch -finally 2.throws
*
* 二.try - catch -finally的使用
* try {
* //可能出现异常的代码
* }catch (异常类型1 变量名1){
*
* }catch (异常类型1 变量名1){
* *
* * }
*
*finally {
* //一定会执行的代码
* }
* 说明:
* 1、finally是可选的
* 2.使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据对象的类型,去cach中进行匹配
* 3。一旦try中的异常对象匹配到某一个catch时,就进入catch进行异常处理,一旦处理完成,就跳出当前的try -catch结构,继续执行其后面的代码
* 4. catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓
* catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则报错
*/
public class ExceptionTest1 {
public static void main(String[] args) {
String s = "123";
s = "abc";
try {
int num = Integer.parseInt(s);
}catch (NumberFormatException c){
System.out.println("有错误");
}
}
}
/**
* finally的使用
* 1.finally是可选的
* 2.finallu中声明的是一定会执行的代码。即使catch中有异常
* 3.像数据库连接,输入输出流,网络编程Socket等资源,JVM是不能自动的回收的 我们需要自己手动的进行资源的释放,此时
* 的资源释放就在finally中
*/
/**
* 异常处理二:throws + 异常类型
* 1. "throws +异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。
异常代码后续的代码,就不再执行
2.体会:try-catch-finally:真正的将异常给处理掉了
throws的方式只是将异常抛给了方法的调用者。并没有真正将异常处理掉
*/