JAVA中的 数据处理
1.接口:
1.接口的基本介绍:
1.接口就是给出一些没有实现的方法,封装到一起,到某个类使用时,再根据具体情况把这些方法给写出来;
接口也是一个类!!!!!!!!!!!!1
接口相当于定义好规范(方法),然后让类来实现它们!!!!!!!@
2.语法:
(1.)接口定义:!!!
.interface 接口名{
属性(都是public static final修饰);
方法;
a:可实现的方法:但必须在最前面加上default
b:可以有静态方法:(不用加default)
c:抽象方法:在接口中抽象方法可以不写abstract,默认为抽象方法;!!
}
(2.)子类实现接口的方法!!!
.class 类名 implements接口{
自己的属性;
自己的方法;
必须实现的接口的抽象方法;!
}
3.如果一个类要实现(implement)接口:需要将该类的所有抽象方法都实现;!!!
4.接口使用:定义一个接口,然后在子类实现接口中的方法!!!
2.演示案例:
package interface2;
//接口的应用场景!!!
//项目经理写的接口!
public interface DBinterface {//项目经理:写了两个方法,要求两个人实现不同的功能;
public void open();
public void close();
}
package interface2;
//A程序员做的工作:实现A功能
public class EmployA implements DBinterface{//实现接口的方法:open,close
public void open(){
System.out.println("实现打开功能A");
}
public void close(){
System.out.println("实现关闭功能A");
}
}
package interface2;
//B程序员:实现B功能
public class EmployeeB implements DBinterface{//实现接口方法
public void open(){
System.out.println("实现打开功能B");
}
public void close() {
System.out.println("实现关闭功能B");
}
}
package interface2;
//接口使用场景!!!!!!!!!!!!!!!!
public class Test {//Class类
public static void main(String[] args) {
//如果想要连接EmployeeA,直接new它的对象,然后传进去对象
EmployA employA=new EmployA();
t(employA);//调用t方法
EmployeeB employeeB=new EmployeeB();
t(employeeB);//调用t方法
}
public static void t(DBinterface dBinterface){////创建方法:使用接口调用来实现)接口的方法
// 将接口类的属性传进去,因为其它类实现接口相当于继承了接口,即可以理解为接口是父类,
// 使用向上转型,将接口(父类)的对象传进去,所以子类对象都可以直接传进去;
//解释:
// 创建静态方法:因为main为静态,
// 静态方法只能调用静态成员!!!!!!!!!!!!
// 使用接口调用(实现)接口的方法,然后传入形参,!!!!!!!!!!!
// 传入的是谁,就自动调用谁的对应方法
dBinterface.open();//调用open方法
dBinterface.close();//调用close方法
}
}
2.内部类:
1.内部类简介·:
内部类基本介绍:
1.a:一个类的内部又完整的(5个成员)嵌套了另一个类结构。被嵌套的类称为内部类(inter class),嵌套其它类的类称为外部类(outer class)
是类的5大成员之一;
b:类的5大成员之一:属性,方法,构造器,代码块,内部类;
c:!!!内部类最大的特点:可以直接!访问外部类所有的成员(包含外部类的私有成员(因为在一个外部类中)),
并且可以体现类与类之间的包含关系;
d:本质仍然是类;可以被继承等
2.基本语法:
class Outer{//外部类(类名)
class Inter{//外部类
}
}
class Other{//(外部)其他类
}
3.演示快速入门:下面的代码
4.内部类的分类(4种):
一:定义在外部类的 局部 位置上 (比如方法内)
1.局部内部类(有类名);
2.匿名内部类(无类名);!!!!!!!!!!!!!!!!!!!!!:用的最多最重要!!!!!!!!!
二:定义在外部类的 成员 位置上 (比如属性,方法的位置)
1.成员内部类(没用static修饰);
2.静态内部类(使用static修饰);
2.局部内部类:
1.局部内部类简介:
!局部内部类(有类名);定义在外部类的 局部 位置上
演示:使用
局部内部类:细节1
.位置说明:局部内部类是定义在外部类的局部位置,比如方法中或者代码块中,并且有类名。!!!
1可以直接访问外部类的所有成员,包括私有!
2.局部内部类不能使用修饰符,但可以使用final修饰(就不可被继承了)
(类本身可以有public m默认修饰,但是局部内部类是一个局部变量,局部变量本身不能被修饰符修饰)
3.局部内部类的作用域:!!!:仅仅可在定义它的方法体,或代码块中使用。(因为局部)
4.a:局部内部类要访问外部类的成员(属性,方法):!!直接访问!!
b:外部类要访问局部内部类的成员:在外部类的!方法中!new内部类的对象,然后调用即可.
5.本质仍然是一个类
细节2:
1.外部其它类不能访问局部类(因为局部内部类地位是一个局部变量);
2. a:如果外部类和局部内部类的成员重名时,默认遵循就近原则
b:但如果仍想要访问外部类的成员:使用 外部类名.this.成员 去访问;
解读:Outer0.this本质就是外部类的对象,哪个对象调用m1方法(内部类在m1方法中)
Outer0.this就是哪个对象;
*/
2.局部内部类演示:
public class InterClass02 {
public static void main(String[] args) {
Outer0 outer0=new Outer0();
outer0.m1();
}
}
class Outer0{
private int n1=10;//外部类私有属性
private void m(){
System.out.println("m()");
}
public void m1() {//外部类方法:在方法中创建外部类!
class Inner {//内部类(也可以拥有完整5大成员):
private int n1 = 15;//内部类属性;
public void m2() {//内部类方法
//内部类可以直接访问外部类所有成员(包括私有!!!)
System.out.println("n1="+n1);//访问内部类私有属性
m();//访问内部类私有方法;
//但如果仍想要在访问到外部类的成员:外部类名.this.成员 去访问
System.out.println("外部类的n1="+Outer0.this.n1);
//解读:Outer0.this本质就是外部类的对象,哪个对象调用m1方法(内部类在m1方法中),
// Outer0.this就是哪个对象;
}
}
//外部类要访问局部内部类:在外部类方法中new内部类的对象
Inner inner=new Inner();
inner.m2();
//class Inner02 extends Inner{}//内部类之间可以继承
}
}
3.匿名内部类:(!!!)
1.匿名内部类简介:
//匿名内部类(Anonymous innerclass)!!!!!!!!!!!重点难点·,使用最多的!!!
//匿名内部类本质!!!!
/*
1.(1.)本质仍是类,(2.)位置:在外部类 局部位置(方法,代码块)上,是内部类,(3.)该类没有名字(看不到)
(4.)匿名内部类同时也是对象!!!!!!!!!!!!!!!
2.匿名内部类基本语法:
new 类/接口(参数列表){---->:参数列表到时候可以和构造器用!!!
类体
};
3.演示:
一.基于接口的匿名内部类
传统方法:写一个类,实现该接口,创建对象;
缺点:Tiger只使用一次,后面不再使用,那样会定义很多类,繁琐且浪费类;
!!既不创建Tiger类,又可以使用cry方法:所以我们可以使用匿名内部类来简化开发
2.匿名内部类案例演示:
public class InterClass03 {
public static void main(String[] args) {
Outer04 outer04=new Outer04();//直接创建外部类的对象
outer04.method();//调用方法即可
/*IA tiger=new Tiger();
tiger.cry();*/
}
}
class Outer04{//外部类
private int n1=10;
public void method(){//方法!
IA tiger=new IA(){//匿名内部类接口!!!!,
//tiger的编译类型:IA,运行类型是:匿名内部类Outer04$1(隐藏)!!!!!!!
public void cry(){//(匿名内部类(接口))重写了cry方法!!!1
System.out.println("老虎叫");
}
};
tiger.cry();//!!!调用接口的方法:因为外部类不能直接访问内部类的方法:需要new对象再调用
//但是已经new对象了,所以直接调用即可!!
//底层代码:
/* 底层代码:会分配一个类,来实现接口;
==eg class Outer04$1 implements IA{
public void cry(){
System.out.println("老虎叫");
}
}*/
//!!!!new:在创建了匿名内部类Outer04$1后,立即就创建了(IA接口)匿名内部类的实例对象
// 并把地址返回给tiger;
//二:演示基于多态参数的匿名内部类
//jack会自动传给Father的构造器
Father father=new Father("jack"){//创建匿名内部(类的)=对象!!:加了“{}”!!! // (原本为创建Father类的对象)
//!!因为有一个new,所以创建一个(匿名内部类Outer04$02)的对象,使用father接收!
//编译类型:Father(父类),运行类型:”=“右边其实是:Outer04$02(隐藏)!!!
public void test(){
System.out.println("匿名内部类重写了test方法");
}
};
father.test();//!!因为返回给了(相当于父类)对象father,所以直接使用father对象调用方法;
/*
==底层代码:分配一个类来继承Father类
class Outer04$02 extends Father{
public void test{
System.out.println("匿名内部类重写了test方法");
}
}
*/
//三:基于抽象类(abstract Animal)的匿名内部类:
Animal animal=new Animal(){//创建匿名内部类Outer04$03(或它的对象)
//!!因为有一个new,所以同时返回了一个对象(匿名内部类Outer04$03)的对象,并返回给animal
//!!!分析:编译类型:Animal,运行类型:Outer04$03(隐藏了)
void eat(){
System.out.println("小狗狗吃骨头");//抽象类方法必须实现
}
};
animal.eat();
/*
==底层代码:分配一个类来继承抽象类:Aniaml;
class Outer04$03 extends Animal{
void eat(){
System.out.println("小狗狗吃骨头");//抽象类方法必须实现
}
}
*/
}
}
interface IA{//接口IA
public void cry();
}
/*class Tiger implements IA{
public void cry(){
System.out.println("tiger叫");
}
}*/
class Father{
private String name;
public Father(String name){//构造器
this.name=name;
}
public void test(){//方法
}
}
abstract class Animal{//三:抽象类
abstract void eat();//抽象方法:需要类的子类的实现;!!!
}
3.匿名内部类注意细节:
//匿名内部类的使用细节及注意事项:
/*
1.匿名内部类的语法
2.匿名内部类:既是类又是对象!!!(因为前面有new)!!!!
因此它 既有定义类的特征( ”{}“ ),又有创建(new)对象的特征。
3.!!!!演示:调用匿名内部类方法的两种方式:1 2
1.Person person=new Person(){// 编译类型:Person,运行类型Outer05$05
public void hi(){
System.out.println("匿名内部类重写了hi方法");//
}
};
person.hi();//+++++++方法1
4.匿名内部类可以直接访问外部类的所有成员(包括私有)。
5.匿名内部类不能添加访问修饰符,因为它的地位是局部变量
6.匿名内部类作用域:只能使用一次,仅在定义它的方法或代码块中/
7.外部其它类 不能访问 匿名内部类(因为匿名内部类的地位:局部变量:只能使用一次)
8.如果外部类和匿名内部类成员重名,!在匿名内部类中!访问时,访问遵循就近原则。
但如果仍想要在在!匿名内部类中!访问外部类的重名成员:则 :外部类类名.this.成员。eg:Outer05.this.n1;
eg:Outer05 outer05=new Outer05
outer.f1();
谁调f1(),Outer05.this就是指的是外部类的对象(哪个对象调用):在这里就是指的outer05!!!!
public class InterClass05 {
public static void main(String[] args) {//main方法
Outer05 outer05=new Outer05();
outer05.f1();
}
}
class Outer05{//外部类
private int n1=99;
public void f1(){//创建一个方法:用于创建一个匿名内部类
//四演示:创建一个基于类(Person)的匿名内部类;!!!
Person person=new Person(){// 编译类型:Person,运行类型Outer05$05。
/* private int n1=88;*/
public void hi(){
System.out.println("匿名内部类重写了hi方法");//
/*System.out.println(n1);//直接访问外部类的私有成员*/
}
};
person.hi();//+++++++++++++方法1
// 动态绑定机制,看运行类型:真实的运行类型:Outer05$05,所以会先从Outer05$05
//类(即上方的匿名内部类)中找hi方法,如果有且可以访问就调用,如果没有就看Person类中
new Person(){//+++++++++++方法2:newPerson就是匿名内部类的对象,所以最后直接调用hi()即可
public void hi(){//重写Person类方法1
System.out.println("匿名内部类重写了hi方法hhhhhh");//
}
@Override
public void ok(String str) {//重写方法2
super.ok(str);
}
}.ok("jack");
//或者.hi();//动态绑定机制
}
}
class Person{//类
public void hi(){//方法
System.out.println("Person hi()");
}
public void ok(String str){//方法
System.out.println("Person ok"+str);
}
}
//还可以有抽象类,接口,和04中的一样,这里不演示!!!!!
4.成员内部类
1.成员内部类简介
二:1.成员内部类:->是成员!!!
(1.快速入门)
1.定义位置:定义在外部类的成员位置上;!!!
2.成员内部类可以被任意修饰符修饰(因为它是成员变量)。
3.成员内部类的作用域:和外部类的其它成员一样,为整个类体(因为定义在外部类中)。
(!!!!!)访问方式:在外部类的方法中创建内部的对象,再调用方法;
4.访问:a:成员内部类-->访问外部类:直接访问所有成员;
b:外部类 --->访问成员内部类:在外部类的方法中创建内部的对象,再调用相关属性方法!!
2.演示:
public class Memberinnerclass {
public static void main(String[] args) {
Outer08 outer08=new Outer08();//创建外部类的对象;
outer08.show();//调用外部类方法show;
//!!!方法1:new Inner08() 相当于把new Inner08()当作outer08的成员?????????
Outer08.Inner08 inner08=outer08.new Inner08();//
inner08.say();
// 用外部类的对象newl一个内部类的实例然后返回给他
//把Outer08去掉就是一个正常对象的实例化,~!!!!~~
//方法2:在外部类中,编写一个方法,可以返回Inner08的对象;
//
/* outer08.getClass()
inner081Instance.say();*/
}
}
class Outer08{//外部类。
private int n1=10;
private String name="kk";
class Inner08{//成员内部类!:在成员位置上
public void say(){//可以直接访问外部类所有成员(包含私有)!
System.out.println("n1="+n1+" "+"name="+name);
}
public Inner08 getInner08Instance(){//方法2.在外部类中,编写一个方法,可以返回Inner08的实例对象;
return new Inner08();//返回Inner08的对象,所以就可以调用它的方法;
}
}
//写方法:用于外部类访问内部类
public void show(){//因为外部类不能直接访问内部类的成员!!!
// 所以定义外部类方法show;使外部类可以访问内部类的成员!!!!!
Inner08 inner08=new Inner08();//创建成员内部类的对象;
inner08.say();//调用成员内部类的方法say;
}
}
5.静态内部类:
1.静态内部类简介:
静态内部类:static Class
1.a:使用static修饰,b:在外部类的成员位置
2.!!静态内部类可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员;
3.可以添加任何访问修饰符(因为在成员位置上)
4.静态内部类的作用域:整个类体(同其它成员一样)
5.访问方式:a:静态内部类---访问--->外部类(比如:静态属性)
访问方式:直接访问所有!静态!成员;(静态只能访问静态)
b:外部类----访问---->静态内部类;
访问方式:创建方法-->创建对象--->调用方法
6.外部其它类 使用静态内部类:
方式1:Outer10.Inner inner10=new Outer10.Inner10();
7.如果外部类和静态内部类的成员重名时,静态内部类访问时:默认遵循就近原则。
如果想要访问外部类的成员:(外部类名.成员)去访问
//因为:静态内部类是静态的,静态的只能访问静态的,所以不用加this~!!
2.演示:
public class StaticClass {
public static void main(String[] args) {
Outer10 outer10=new Outer10();
outer10.m1();
//.外部其它类 使用静态内部类:方式1:
//因为静态内部类是可以通过类名直接访问的!
Outer10.Inner10 inner10=new Outer10.Inner10();
inner10.say();
//方式2:编写一个方法:可以返回静态内部类的实例
Outer10.Inner10 inner101=outer10.getInner10();//使用Outer10.Inner10 inner101接收
System.out.println("=============");
inner101.say();
//方式3
Outer10.Inner10 inner=Outer10.getInner_();
System.out.println("*************");
inner.say();
}
}
class Outer10{//外部类
private int n1=10;
private static String name="张三";
static class Inner10{//静态内部类
// private String name="kk";//重名就近原则
public void say(){
System.out.println(name);//静态内部类可以直接访问外部类的所有静态成员,
//System.out.println(n1);//但不能直接访问非静态成员
//System.out.println("外部类的name="+Outer10.name);// 如果想要访问外部类的成员:(外部类名.成员)去访问
}
}
public void m1(){
Inner10 inner10=new Inner10();
inner10.say();
}
//方式2:编写一个方法:可以返回静态内部类的实例
public Inner10 getInner10(){
return new Inner10();
}
//方式3:编写一个静态方法:科研返回静态内部类的实例
public static Inner10 getInner_(){
return new Inner10();
}
//
}
3.枚举
1.枚举简介:
枚举的引出:
1.枚举是一个类。
2.枚举类:即把具体的对象一个一个的列举出来的类!!!
3.枚举类中所有的成员都是public static final
枚举基本介绍:
1.枚举是一组常量的集合;
2.可以理解为:枚举属于一种特殊的类,里面包含一组有限的特定对象。
3.枚举的两种实现方式:
A:自定义类实现枚举:
1.构造器私有化;(构造器私有化后在外面就不能new对象了)。
2.去掉set方法(防止set方法修改属性等,且因为枚举对象值通常为只读,可以有get)
3.对外暴露对象:在该类(Seasons)内部创建固定的对象(有几个就创建几个),final+static修饰对象
4.优化:加入fianl修饰符对象(属性):final+static修饰不会导致类的加载(final你不可能去修改)
注意:a:枚举对象名通常要全部大写/
b:加入fianl+static共同修饰符对象(属性)/
c:枚举对象根据需求可以有多个对象
d:枚举类中的成员都是static类的,使用可以直接使用类名访问!!!!!!!!!!
B:使用enum关键字实现枚举
演示:
2.演示A:自定义类实现枚举::
public class Enum02 {
public static void main(String[] args) { //main方法·
//new Seasons()//不能再new对象;
//set:也不能修改
System.out.println(Seasons.Spring);//静态可以直接:类名.对象;可以使用toString打印出来!!
System.out.println(Seasons.Summer);
System.out.println(Seasons.Autumn);
System.out.println(Seasons.Winter);
}
}
/*
演示自定义枚举的实现:
1.构造器私有化:(构造器私有化后在外面就不能new对象了)。
2.去掉set方法(防止set方法修改属性等)
3.在该类(Seasons)内部创建固定的对象(有几个就创建几个)
4.优化:加入fianl修饰符对象:final+static修饰不会导致类的加载(final你不可能去修改)
*/
class Seasons{
private String name;
private String desc;//描述
//定义四个固定对象:就不能增加或减少对象了
public static final Seasons Spring=new Seasons("春天","温暖");
public static Seasons Winter=new Seasons("冬天","寒冷");
public static Seasons Autumn=new Seasons("秋天","凉爽");
public static Seasons Summer=new Seasons("夏天","炎热");
private Seasons(String name, String desc) {//构造器私有化
//构造器私有化后在外面就不能new对象了
this.name = name;
this.desc = desc;
}
//get,set
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Seasons{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
3.演示实现枚举的第二种方式:使用enum关键字实现枚举::
//实现枚举的第二种方式:使用enum关键字实现枚举:
/*步骤:
1.使用关键字enum代替class
2.构造器私有化
3.无set
4.public static Seasons Spring=new Seasons("春天","温暖");==改为--->:Spring("春天","温暖"):对象名(实参列表):
实参列表会根据实参和相应构造器相关联;
*/
/*
使用eum关键字实现枚举的注意事项/细节
1.如果有多个对象,使用”,“隔开,最后一个带分号;!!
2.如果使用enum来实现枚举,要求将定义的常量对象,写在类的最前面;
3.当我们使用enum关键字开发一个枚举类时,默认会继承Enum类,而且是一个final类
4.如果我们使用的是无参构造器,创建对象时,则可以省略();eg:WHAT()==WHAT;
*/
//演示:
//enum枚举类1
public class Enum03 {
public static void main(String[] args) {//main
System.out.println(Season2.SPRING);//==public static Seasons Spring=new Seasons("春天","温暖")
System.out.println(Season2.SUMMER);
System.out.println(Season2.AUTUMN);
System.out.println(Season2.WINTER);
}
}
enum Season2{
SPRING("春天","温暖"),SUMMER("夏天","炎热"),AUTUMN("秋天","凉爽"),
WINTER("冬天","寒冷"),/*WHAT()*/;
//解读:对象名(实参列表):实参列表和构造器相关联;
private String name;
private String desc;//描述
Season2() {//无参构造器
}
private Season2(String name, String desc) {//构造器
this.name = name;
this.desc = desc;
}
//get,set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {//toSring方法用来输出信息
return "Seasons{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
4.枚举使用细节:
//枚举使用细节:
/*
1.使用enum关键子后,就不可以有继承(extends):---(因为它已经有一个隐式的继承:Enum,java单继承机制)
2.但是可以实现接口;下面的是演示:!!!
*/
public class EnumDetails {
public static void main(String[] args) {
/* IPlaying iPlaying=new Music();//传统方法
iPlaying.playing();*/
Music.CLASSMUSIC.playing();
//Music.CLASSMUSIC:表示:枚举类的对象!!!!!!!!
}
}
class A{
}
interface IPlaying{//接口
void playing();
}
enum Music implements IPlaying{
CLASSMUSIC();//创建枚举对象:是静态的--->:所以可以直接调用!!!!
public void playing(){//实现接口的方法==重写!!!
System.out.println("播放:只因你太美~~~~");
}
}
4.异常:(!!!)
1.异常简介:
引入:eg:当出现异常(错误),程序就会退出,崩溃了,下面的代码就不会执行,程序就会报异常;
但如果出现了一个不是致命的错误就退出(崩溃),那么健壮性太差。---->:这时候引出了:异常处理机制来解决。
1.出现异常可以使用:try-catch”异常处理机制“来解决
步骤:将该代码块选中-->:使用快捷键:ctrl+alt+t->选中 try-catch
2.如果进行了异常处理。那么即使出现了异常,程序也可以继续执行
2.演示:
*public class Exception01 {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;z
try {
int res = num1 / num2;
} catch (Exception03 e) {
e.printStackTrace();
//System.out.println(e.getMessage());//2.也可以直接把使用这个:就不会报错了,且会将异常信息显示出来
}
//0不可以做除数,所以会报错,为了增强健壮性,可以使用try-catch”异常处理机制“来解决;
System.out.println("程序正常执行........");//1.加上异常处理后遇到 int res = num1 / num2;不会停止,仍会报错但,一直会执行到最后输出这句话!
}*/
//}
3.异常细节
异常:指的是程序执行过程中发生的不正常情况,但语法错误和逻辑错误不算;
执行过程中所发生的异常事件可以分为两大类:
1.Error(错误):是致命严重错误,程序会崩溃,无法通过异常处理机制来实现!!!;
重点:
2.Exception:因编译错误或欧瑞的外在问题导致的一般性问题!!!
分为两大类:
a:运行时异常[程序运行阶段发生的异常];编译器检测不出来,往往是逻辑错误,eg:num/0:
b:编译时异常[编程阶段,编译器检查出的异常]
注意:1.运行时异常可以不做处理;(因为它很普遍,若都处理会会影响代码可读性,运行效率)
2.而编译异常必须处理!!!!!!
3.异常体系图:体现了继承和实现功能。
运行时异常:
*
一:5大运行时异常:
1.空指针异常:当应用程序试图在需要对象的地方使用null时会抛出异常;
2.算数异常:num/0;
3.数组下标越界异常(为负数或超出数组长度)
4.类强制转换异常:当试图将对象强制转换为不是实例的子类时,抛出异常。
5.数字格式不正确异常:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出异常
*/
public class Exception3 {
public static void main(String[] args) {
//1.空指针异常
//String name="kk";
String name=null;
//System.out.println(name.length());//需要name,但是name为null,所以异常;
//2.算数异常:num/0;
//3.数组下标越界异常(为负数或超出数组长度)
int []arr={1,2,3};
/* for(int i=0;i<=arr.length;i++){//arr数组越界
System.out.println(arr[i]);
}*/
//4.类强制转换异常:当试图将对象强制转换为不是实例的子类时,抛出异常。
/*A a=new B();//向上转型ok
B b1=(B) a;//向下转型ok
C c=(C) a;*///C类域B类无继承关系
//5.数字格式不正确异常:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出异常
//eg:将String转为int
String name1="kkkk";
int num=Integer.parseInt(name);
System.out.println(num);
}
}
class A{}
class B extends A{}
class C extends A{}
4.异常处理机制简介:
异常处理机制:!!!!!
如果程序员认为程序可能会有异常时(或抛出异常时):
异常处理的方式(二选一!!):
(1.):try-catch-finally处理机制:
try{
(可能异常的代码)
}catch(Exception e){
(捕获到的异常)---> //当异常发生时,系统将异常封装成Exception的对象e,然后传给catch;
//得到异常对象后,程序员自己处理
//如果try代码块没有发生异常,则catch代码块不执行!!
}finally{ ---> //不管try代码块是否有异常发生,都会执行finally代码块;
//所以通常将释放资源的代码放到finally中;
}
finally可写可不写!
(2.)throws处理机制:
一直往上扔:扔到上一级,之后上一级要么try-catch,要么继续throws到上一级。...若一直没有try,则一直到扔到最顶级的处理者JVM
JVM会a:会输出异常信息,b:然后退出程序
注意:1.try-catch-finall处理机制和throw处理机制只能二选一!!!
2.如果程序员没有显示处理异常,默认使用throws处理异常
1.try-catch方式处理异常说明
package Exception;
/*
try-catch方式处理异常说明:
1.)try块用于包含可能出错的代码,try:尝试执行。catch块用于!捕获!!处理!try块中发生的异常。
可以根据需要在程序中有多个try...catch块;
2.)基本语法:
try{
可疑代码
}catch(异常:Exception e){
对异常进行处理 1.e.printStackTrace();
//2.System.out.println(e.getMessage());
}finally{可不写
}
3.):try-catch细节:+演示:
1.如果发生异常,则异常后面的代码不会执行,直接进入到catch块;
2.如果异常没有发生,则顺序执行try代码块,不会进入catch(因为没异常,不用捕获)
3.如果希望希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等),则使用finally(总会执行!)
4.如果try代码块有多个异常,我们可以使用多个catch语句,来分别捕获不同的异常(进行不同的业务处理),相应的处理。(但前提得先知道异常的类型!)
注意:但要求父类异常在后,子类异常在前;!!!
Exception包含所以的异常-->:所以Exception是父类
其它异常是子类
(都是Exception的子类,如果把E写在前面,就只捕获1个)
eg:
5.try-finally
*/
//演示:
public class TryCatch {
public static void main(String[] args) {
/* try {
String str="kk";//a:
int a=Integer.parseInt(str);////b认为这部分可能出现异常
System.out.println("数字:"+a);//c
} catch (NumberFormatException e) {//d
System.out.println("异常信息:"+e.getMessage());//e
throw new RuntimeException(e);//f
} finally {
System.out.println("finally代码块都会执行....");
}
//解读:因为b出现异常,所以b(异常)之后的代码c不会执行,直接会进入catch块;
*/
//演示第4点b部分:一:使用一个catch时:
try {
Person person=new Person();
//person=null;//空指针//a.
System.out.println(person.getName());//空指针异常b.
int n1=10;
int n2=0;
int res=n1/n2;//算数异常c.
} catch (Exception e) {
System.out.println(e.getMessage());//(1.)当使用一个catch时:
// 只会输出“空指针异常”,因为执行到异常后,下面的代码就不会执行,而是直接到catch代码块中,然后输出异常信息。
//2.)但如果没有a那句话,b会正常执行,然后直到遇到c异常,则跳到catch代码块中输出异常信息。
} finally {
}
//上述代码有两个异常(或者有多个),这时我们可以使用多个catch来捕获异常;
//演示第4点b部分:一:使用多个catch时
try {
Person person=new Person();
person=null;
System.out.println(person.getName());//空指针异常1 //b.
int n1=10;
int n2=0;
int res=n1/n2;//算数异常2 //c.
} catch (NullPointerException e) {//第一个catch捕获:空指针异常
System.out.println("空指针异常:="+e.getMessage());
} catch(ArithmeticException e){//第二个catch捕获算数异常
System.out.println("算数异常:="+e.getMessage());
}
catch(Exception e){
System.out.println(e.getMessage());
}
finally {
}
}
}
//演示第4点a部分:
class Person{
private String name="kunkun";
public String getName(){
return name;
}
}
2.try-catch补充:
细节5.(1):也可以进行 try-finally配合使用,这种用法相当于没有捕获异常(因为没有catch);
因此执行完finally后程序会直接崩掉/退出。
(2).应用场景:就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑(即finally块中的·)
演示
*/
public class TryCatch2 {
public static void main(String[] args) {
try {
int n1=10;
int n2=0;//会出现异常:算数异常
System.out.println(n1/n2); //a
} finally {
System.out.println("执行finally....."); //b
}
System.out.println("程序继续执行..."); //c
//解读:有异常,但是因为没有catch捕获异常,所以在a处发生异常后会直接到finally执行b,然后退出程序(崩掉)
//注意:1.不会执行c语句!!!!!!!!!
//最后输出b,是JVM输出的:因为没有做任何处理的化,默认是throws处理机制,一直到JVM,
// JVM会a:输出错误信息,然后b退出程序(崩掉),所以没有机会执行c就会崩掉;
}
}
3.throws异常处理机制
//异常处理机制二:throws异常处理机制:
//throws入门
/*
1.基本介绍:
1.)如果一个方法可能有异常但不确定如何处理这种异常,则此方法应显示的声明(明确的抛出:即不处理)抛出异常
表示:不对异常进行处理,而由该方法的调用者负责处理。
2.)在该方法中用throws语句可以声明抛出异常的列表,
throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
直接抛给父类:Exception!!!!!!!!!(一般使用这种!!!!!1)
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Throws {
public static void main(String[] args) {
}
public void f1(){
try {//1.使用try-catch
FileInputStream fis=new FileInputStream("\"d://aa.txt\"");//异常!!!
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
/*public void f2() throws FileNotFoundException{//第二种处理机制a::throws
// 使用throws抛出异常:即f2自己不处理,让调用f2方法的调用者处理
FileInputStream fis=new FileInputStream("\"d://aa.txt\"");
}
*/
//直接抛给父类:Exception!!!!!!!!!(一般使用这种!!!!!1)
/* public void f2() throws Exception{//第二种处理机制b::throws
//throws后面的异常类型可以是方法中产生的异常类型(即明确的如FileNotFoundException),也可以是它的父类Exception
FileInputStream fis=new FileInputStream("\"d://aa.txt\"");
}
*/
//c:throws关键字后面也可以是 异常列表,即可以抛出多个异常;
public void f2() throws FileNotFoundException,NullPointerException{//第二种处理机制b::throws
FileInputStream fis=new FileInputStream("\"d://aa.txt\"");
}
}
4.throws使用细节:
throws异常处理机制细节:
1.编译异常必须!显示!处理(运行时异常可以不用处理);
egFileInputStream
2.a:对于运行时异常,程序如果没有显示处理,默认是使用throws处理(即自己可以不用处理)
eg:public void f2()/默认:throws Exception/ {
int n=10/0;
}
b:而编译运行异常没有默认处理,必须显示处理(即使用两种中的一种)!!!!!!!!!!!!!!
3. 子类重写父类方法时,对抛出的异常的规定是:子类重写方法所抛出的异常必须和父类一样,或者为父类异常的子类!
(即子类不能缩小父类的范围,返会类型也是)。
4.catch和throws是两种处理机制:只能选择一种;