多态?
?? ??? ?概念: ?? ??? ??? ?什么是多态? ?? ??? ??? ??? ?父类的引用指向子类的对象。 ?? ??? ??? ??? ?同类型的对象,执行同一个行为,会表现出不同的行为特征。 ?? ??? ?多态的常见形式 ?? ??? ??? ?父类类型 对象名称 = new 子类构造器; 接口 对象名称 = new 实现类构造器; ?? ??? ??? ??? ? //多态的形式 : ?父类类型 对象名称 = new 子类构造器; ? ? ? ? Animal a = new Dog(); ? ? ? ? a.run();
? ? ? ? Animal a2 = new Tortoise(); ? ? ? ? a2.run(); ?? ??? ?多态中成员访问特点 ?? ??? ??? ?方法调用:编译看左边,运行看右边。 ?? ??? ??? ?变量调用:编译看左边,运行也看左边。(多态测重行为多态,不强调变量) ?? ??? ??? ??? ? //多态的形式 : ?父类类型 对象名称 = new 子类构造器; ? ? ? ? Animal a = new Dog();//父类的引用指向子类的对象 ? ? ? ? a.run();//方法:编译看左边,运行看右边 ? ? ? ? System.out.println(a.name);//对于变量的调用:编译看左边,运行也看左边,结果指向父类 ?? ??? ?多态的前提: ?? ??? ??? ?有继承关系; ?? ??? ??? ?有父类引用指向子类的对象; ?? ??? ??? ?有方法重写。 ?? ?多态的优势: ?? ??? ?在多态形式下,右边对象可以实现解耦合,便于扩展和维护。 ?? ??? ?Animal a = new Tortoise(); a.run();//后续业务的行为随对象而变,后续代码无需修改 ?? ??? ?定义方法的时候,使用父类型作为参数,该方法就可以接收父类的一切子类对象,体现出多态的扩展性与便利。 ?? ??? ?多态下会产生的一个问题:多态下不能使用子类的独有功能。 ?? ?多态引用数据类型的类型转换 ?? ??? ?自动类型转换(从子到父):子类对象赋值给父类类型的变量指向。 ?? ??? ?强制类型转换(从父到子) ?? ??? ??? ?必须进行强制类型转换:子类 对象变量 = (子类)父类类型的变量 ?? ??? ??? ??? ?Animal a1 = new Dog(); ? ? ? ? //a1.loolDoor();//多态下不能访问子类独有功能 ? ? ? ? Dog d = (Dog) a1;//从父类类型到子类类型;必须强制类型转换 ? ? ? ? d.lookDoor(); //调用子类的独有功能 ?? ??? ??? ?作用:可以解决多态下的劣势,可以实现调用子类独有的功能。 ?? ??? ??? ?注意:如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现classCastException ?? ??? ?java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换 ?? ??? ??? ?变量名 ?instanceof 真实类型 ?? ??? ??? ?判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之。
异常
?? ?概念: ?? ??? ?异常是什么? ?? ??? ??? ?异常是代码编译或执行的过程中可能出现的错误 ?? ??? ?异常分为几类? ?? ??? ??? ?编译时异常、运行时异常 ?? ??? ??? ?编译时异常:没有继承RuntimeException的异常,编译阶段就会出错。 ?? ??? ??? ?运行时异常:继承自RuntimeException的异常或其子类,编译阶段不报错,运行可能报错 ?? ??? ?学习异常的目的? ?? ??? ??? ?避免异常的出现,同时处理可能出现的异常,让代码更稳健。 ?? ?运行时异常: ?? ??? ?直接继承自RuntimeException或者其子类,编译阶段不会报错,运行时可能出现的错误。 ?? ?运行时异常示例 ?? ??? ?数组索引越界异常: ?? ??? ??? ?ArrayindexOutOfBoundsException ?? ??? ?空指针异常: ?? ??? ??? ?NullpointerException ?? ??? ?数学操作异常: ?? ??? ??? ?ArithmeticException ?? ??? ?类型转换异常: ?? ??? ??? ?ClassCastException ?? ??? ?数字转换异常: ?? ??? ??? ?NumberFormatException ?? ??? ?注意: ?? ??? ??? ?运行时异常一般是程序员业务没有考虑好或者是编程逻辑不严谨引起的程序错误。 ?? ?编译时异常: ?? ??? ?不是RuntimeException或者其 子类的异常,编译阶段就出错,必须处理。否则代码不通过 ?? ?编译时异常的作用是什么? ?? ??? ?担心程序员的技术不行,在编译阶段就报出一个错误,目的在于提醒不要出错 ?? ??? ?编译时异常是可遇不可求。遇到就遇到呗 ?? ?编译时异常的处理方式有三种: ?? ??? ?出现异常直接抛出去,调用者也继续抛出去 ?? ??? ?出现异常自己捕获处理,不麻烦别人 ?? ??? ?前两者结合,出现异常直接抛出去给调用者,调用者捕获处理 ?? ?异常处理方式1 throws ?? ??? ?throws:在用法上可以将方法内部出现的异常抛出去给本方法的调用者处理。 ?? ??? ?这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡 ?? ??? ?抛出异常格式: ?? ??? ??? ?方法 throws 异常1,异常2,异常3...{ } ?? ??? ?规范做法: ?? ??? ??? ?方法 throws Exception{ } ?? ?异常处理方式2 ?try...catch... ?? ??? ?概念: ?? ??? ??? ?监视捕获异常,用在方法的内部,可以将方法内部出现的异常直接捕获处理。 ?? ??? ??? ?这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行 ?? ??? ?格式: ?? ??? ??? ?try{ //监视可能出现的异常代码 }catch(异常类型1 变量){ //处理异常 }catch(异常类型2 变量){ //处理异常 } ?? ??? ??? ??? ?建议格式: ?? ??? ??? ??? ??? ?try{ //可能出现的异常 }catch(Exception e){ e.printStackTrace();//直接打印异常栈 }
Exception可以捕获处理一切异常类型! ?? ?异常处理方式3—前两者结合 ?? ?异常的总结: ?? ??? ?1.异常 ?? ??? ??? ?(1)Try(存放代码块) ?? ??? ??? ??? ?1.不能单独出现,必须结合catch或者finally使用,用于将可能会出现异常的代码包括起来,不要将过于庞大的代码放在try中,不利于代码的阅读和维护。 ?? ??? ??? ?(2)Catch(用于处理异常) ?? ??? ??? ??? ?1.不能单独出现,必须结合Try使用,用于捕获异常并打印堆栈信息。 ?? ??? ??? ??? ? 2.匹配异常分为三种情况: 1)没有出现异常,程序正常执行 2)出现了异常,并且捕获了,那么将执行catch块 3)出现了异常,但是异常类型不匹配,那么依然将中断程序。 ?? ??? ??? ??? ?3.如果一段代码中可能会出现多种异常,那么我们可以编写多个catch块,这些catch块按照范围从小到大的顺序来书写,先子类后父类。多个catch块按顺序进行匹配,只会匹配成功一个。 ?? ??? ??? ?(3)finally ?? ??? ??? ??? ?1.finally不能单独出现,必须结合try使用,表示不管是否出现异常都执行的代码块。 ?? ??? ??? ??? ?2.通常用于关闭资源等一些必要执行的操作。 ?? ??? ??? ??? ?3.finally中对返回值的操作不会影响try中的返回值,但是finally中的代码是会执行。 ?? ??? ??? ??? ?4.try,catch,finally中都存在return语句的情况,这种方式不推荐,但是如果存在的话,finally中的return将最终决定返回值。 ?? ??? ??? ?(4)Throw(抛出异常) ?? ??? ??? ??? ?1.Throw用于抛出异常,直接书写在方法体的内部,作为一条单独的语句来书写,当我们抛出的属于检查异常的情况下,必须使用Throes来声明,如果属于运行时异常,则不需要必须声明。 ?? ??? ??? ?(5)Throws(声明异常) ?? ??? ??? ??? ?1.用于声明当前方法可能会抛出的异常,直接写在方法小括号后面,可以声明多个异常,多个异常使用逗号隔开即可。 ?? ??? ??? ?(6)(检查)checkedException & RuntimeRxception ?? ??? ??? ??? ?1.检查异常要求我们在调用此方法的时候必须处理,如果不处理,编译不通过;处理方式两种: 1) 直接使用try - catch来处理 2)继续声明,抛给jvm虚拟机,我们自己不处理 ?? ??? ??? ??? ?2.运行时异常,不是必须处理的。 ?? ??? ?2.自定义异常 ?? ??? ??? ?概念: ?? ??? ??? ??? ?因为JDK给我们提供的异常有限,我们在实际开发中往往不能满足我们的需求,此时我们可以自定义异常。 ?? ??? ??? ?方式: ?? ??? ??? ??? ?1.继承父类,可以继承Throwble或者Exception或者RuntimeException都可以实现一个异常类,继承以后编写有参数String类型的构造方法,调用父类的构造方法给我们当前所展示的message属性赋值即可。Message是我们用关于提示信息的属性
内部类
?? ?概念: ?? ??? ?内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。 ?? ??? ??? ?public class People{ ? ? // 内部类 ? ? ? ?public class Heart{
? ? ? ?} } ?? ?内部类使用的场景、作用 ?? ??? ?当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。 ?? ??? ?内部类通常可以方便访问外部类的成员,包括私有成员。 ?? ??? ?内部类提供了更好的封装性,内部类本身就可以用private ?protectecd等修饰,封装性可以做更多控制。 ?? ?静态内部类 ?? ??? ?概念: ?? ??? ??? ?什么是静态内部类? ?? ??? ??? ??? ?有static修饰,属于外部类本身。 ?? ??? ??? ??? ?它的特点和使用与普通类完全一样的,类有的成分它都有,只是位置在别人里面而已。 ?? ??? ??? ??? ??? ?public class Outer{ ? ? // 静态成员内部类 ? ? ? ?public static class Inner{
? ? ? ?} } ?? ??? ?静态内部类创建对象的格式: ?? ??? ??? ?外部类名.内部类名 对象名 ?= new 外部类名.内部类构造器; 范例:Outer.Inner in = new ?Outer.Inner(); ?? ??? ?静态内部类的访问拓展: ?? ??? ??? ?1.静态内部类中是否可以直接访问外部类的静态成员? ?? ??? ??? ??? ?可以,外部类的静态成员只有一份可以被共享访问 ?? ??? ??? ?2.静态内部类中是否可以直接访问外部类的实例成员? ?? ??? ??? ??? ?不可以,外部类的实例成员必须用外部类对象访问;可以通过对象间接访问。 ?? ?成员内部类? ?? ??? ?概念: ?? ??? ??? ?什么是成员内部类? ?? ??? ??? ??? ?无static修饰,属于外部类的对象。 ?? ??? ??? ??? ?JDK16之前,成员内部类中不能定义静态成员。 ?? ??? ?成员内部类创建对象的格式: ?? ??? ??? ?外部类名.内部类名 对象名 = new 外部类构造器.new内部类构造器(); 范例:Outer.Inner in = new Outer().new Inner(); ?? ??? ?成员内部类的访问拓展: ?? ??? ??? ?1.成员内部类中是否可以直接访问外部类的静态成员? ?? ??? ??? ??? ?可以,外部类的静态成员只有一份可以被共享访问 ?? ??? ??? ?2.成员内部类的实例方法中是否可以直接访问外部类的实例成员? ?? ??? ??? ??? ?可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。 ?? ?匿名内部类(重点) ?? ??? ?概念: ?? ??? ??? ?本质上是一个没有名字的局部内部类,定义在方法中、代码块中等 ?? ??? ??? ?作用:方便创建子类对象,最终目的为了简化代码编写。 ?? ??? ?格式: ?? ??? ??? ?new 类|抽象类名|或者接口名(){ ? ? ? 重写方法; }; ?? ??? ??? ??? ?Employee a = new Employee(){ ? ?public void ?work(){
? ? } }; a.work(); ?? ??? ??? ??? ??? ?范例:? ?? ??? ??? ??? ??? ??? ?public class Test { ? ? public static ?void main(String[] args) { ? ? ? ? Animal a = new Animal(){ ? ? ? ? ? ? @Override ? ? ? ? ? ? public ?void run(){ ? ? ? ? ? ? ? ? System.out.println("老虎跑得快"); ? ? ? ? ? ? } ? ? ? ? }; ? ? ? ? a.run(); ? ? }
?/* ? class Tiger extends ?Animal{ ? ? ? ? @Override ? ? ? ? public ?void run(){ ? ? ? ? ? ? System.out.println("老虎跑得快"); ? ? ? ? } ? ? }*/
? ? abstract static class Animal{ ? ? ? ? public ?abstract ?void run(); ? ? } } ?? ??? ?特点: ?? ??? ??? ?匿名内部类是一个没有名字的内部类 ?? ??? ??? ?匿名内部类写出来就会产生一个匿名内部类的对象。 ?? ??? ??? ?匿名内部类的对象类型相当于是当前new的那个的类型的子类类型 ?? ?匿名对象 ?? ??? ?概念: ?? ??? ??? ?一次性的对象。 ?? ??? ?语法: ?? ??? ??? ?创建对象: 匿名对象创建的格式: new 对象名(); 等号左边没有。
|