第Ⅱ期Android菜鸟饭团#Java学习#第十三课 活动笔记
一.多态和动态绑定 多态就是一种类型表现出多种状态 比如你是一个酒神,对酒情有独钟。某日回家发现桌上有几个杯子里面都装了白酒,从外面看我们是不可能知道这是些什么酒,只有喝了之后才能够猜出来是何种酒。你一喝,这是剑南春、再喝这是五粮液、再喝这是酒鬼酒….在这里我们可以描述成如下: 酒 a = 剑南春 酒 b = 五粮液 酒 c = 酒鬼酒 … 这里所表现的的就是多态。剑南春、五粮液、酒鬼酒都是酒的子类,我们只是通过酒这一个父类就能够引用不同的子类,这就是多态 多态分两种: (1) 编译时多态:编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。 (2) 运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态。(我们平时说得多的是运行时多态,所以多态主要也是指运行时多态) 将一个方法调用同这个方法所属的主体(也就是对象或类)关联起来叫做绑定 动态绑定: 执行期间判断所引用对象的的实际类型(非引用类型),根据实际类型 调用其相应的方 法:内存解析 动态绑定好处: java面向对象的核心。为将来的扩展打下基础,可扩展性好(达到极致), 不用改变代码结构, 不用多次判断,根据对象的变量所引用 的不同类型而调用不同的 运行时多态存在的三个必要条件: 一、要有继承(包括接口的实现); 二、要有重写; 三、父类引用指向子类对象(向上转型)new的是哪一个子类对象的时候,就调用子类对象的方法。 继承就是在一个现有类型的基础上,通过增加新的方法或者重定义已有方法的方式,产生一个新的类型 重写,英文名是overriding,是指在继承情况下,子类中定义了与其基类中方法具有相同型构的新方法,就叫做子类把基类的方法重写了 向上转型:理解多态我们就必须要明白什么是“向上转型”。在上面的喝酒例子中,酒(Win)是父类,剑南春(JNC)、五粮液(WLY)、酒鬼酒(JGJ)是子类。我们定义如下代码: JNC a = new JNC(); 对于这个代码我们非常容易理解无非就是实例化了一个剑南春的对象嘛!但是这样呢? Wine a = new JNC(); 在这里我们这样理解,这里定义了一个Wine 类型的a,它指向JNC对象实例。由于JNC是继承与Wine,所以JNC可以自动向上转型为Wine,所以a是可以指向JNC实例对象的。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在于子类中的方法和属性它就望尘莫及了 从程序的运行结果中我们发现,a.fun1()首先是运行父类Wine中的fun1().然后再运行子类JNC中的fun2()。 分析:在这个程序中子类JNC重载了父类Wine的方法fun1(),重写fun2(),而且重载后的fun1(String a)与 fun1()不是同一个方法,由于父类中没有该方法,向上转型后会丢失该方法,所以执行JNC的Wine类型引用是不能引用fun1(String a)方法。而子类JNC重写了fun2() ,那么指向JNC的Wine引用会调用JNC中fun2()方法。 所以对于多态我们可以总结如下: 指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法. 抽象类与接口是java语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予java强大的 面向对象的能力。他们两者之间对抽象概念的支持有很大的相似,甚至可以互换,但是也有区别。 二.抽象类 我们都知道在面向对象的领域一切都是对象,同时所有的对象都是通过类来描述的,但是并不是所有的类都是来描述对象的。如果一个类没有足够的信息来描述一个具体的对象,而需要其他具体的类来支撑它,那么这样的类我们称它为抽象类。比如new Animal(),我们都知道这个是产生一个动物Animal对象,但是这个Animal具体长成什么样子我们并不知道,它没有一个具体动物的概念,所以他就是一个抽象类,需要一个具体的动物,如狗、猫来对它进行特定的描述,我们才知道它长成啥样。 在面向对象领域由于抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能实例化的。 同时,抽象类体现了数据抽象的思想,是实现多态的一种机制。它定义了一组抽象的方法,至于这组抽象方法的具体表现形式由派生类来实现。同时抽象类提供了继承的概念,它的出发点就是为了继承,否则它没有存在的任何意义。所以说定义的抽象类一定是用来继承的 用abstract关键字来修饰一个类时,这个类叫做抽象类,用abstract来修饰一个方法时,该方法叫做抽象方法。 在使用抽象类时需要注意几点: 1.抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。 2.抽象方法必须由子类来进行重写。子类中一定要重写方法!否则会出现问题!!如果不重写, 再把这个方法定义为抽象方法也可以 3.只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。 4.抽象类中可以包含具体的方法,当然也可以不包含抽象方法。 5.子类中的抽象方法不能与父类的抽象方法同名。 6.abstract不能与final并列修饰同一个类。 7.abstract 不能与private、static、final或native并列修饰同一个方法 8..抽象方法只需声明,而不需要实现。 例如 定义一个抽象动物类Animal,提供抽象方法叫cry(),猫、狗都是动物类的子类,由于cry()为抽象方法,所以Cat、Dog必须要实现cry()方法。如下: 三.接口 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。 除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。 接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在Java中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。 接口与类相似点: - 一个接口可以有多个方法。
- 接口文件保存在.java结尾的文件中,文件名使用接口名。
- 接口的字节码文件保存在.class结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别: - 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了static和final变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多重继承。
接口的声明语法格式如下: 接口有以下特性: - 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
- 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键子。
- 接口中的方法都是公有的。
接口的实现: 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。 类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。 实现一个接口的语法,可以使用这个公式: ... implements 接口名称[, 其他接口, 其他接口..., ...] ... 重写接口中声明的方法时,需要注意以下规则: 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。 在实现接口的时候,也要注意一些规则: 一个类可以同时实现多个接口。 一个类只能继承一个类,但是能实现多个接口。 一个接口能继承另一个接口,这和类之间的继承比较相似。
在使用接口的时候,要注意的问题: 1.一个Interface的所有方法访问权限自动被声明为public。确切的说只能为public,当然你可以显示的声明为protected、private,但是编译会出错! 2.接口中可以定义“成员变量”,或者说是不可变的常量,因为接口中的“成员变量”会自动变为为public static final。可以通过类命名直接访问:ImplementClass.name。 3.接口中不存在实现的方法。 4.实现接口的非抽象类必须要实现该接口的所有方法。抽象类可以不用实现。 5.不能使用new操作符实例化一个接口,但可以声明一个接口变 6.在实现多接口的时候一定要避免方法名的重复。 抽象类与接口的区别: 抽象类方式中,抽象类可以拥有任意范围的成员数据,同时也可以拥有自己的非抽象方法,但是接口方式中,它仅能够有静态、不能修改的成员数据(但是我们一般是不会在接口中使用成员数据),同时它所有的方法都必须是抽象的。在某种程度上来说,接口是抽象类的特殊化。 抽象层次不同。抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。 跨域不同。抽象类所跨域的是具有相似特点的类,而接口却可以跨域不同的类。我们知道抽象类是从子类中发现公共部分,然后泛化成抽象类,子类继承该父类即可,但是接口不同。实现它的子类可以不存在任何关系,共同之处。例如猫、狗可以抽象成一个动物类抽象类,具备叫的方法。鸟、飞机可以实现飞Fly接口,具备飞的行为,这里我们总不能将鸟、飞机共用一个父类吧!所以说抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is-a" 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的, 仅仅是实现了接口定义的契约而已。 设计层次不同。对于抽象类而言,它是自下而上来设计的,我们要先知道子类才能抽象出父类,而接口则不同,它根本就不需要知道子类的存在,只需要定义一个规则即可,至于什么子类、什么时候怎么实现它一概不知。比如我们只有一个猫类在这里,如果你这是就抽象成一个动物类,是不是设计有点儿过度?我们起码要有两个动物类,猫、狗在这里,我们在抽象他们的共同点形成动物抽象类吧!所以说抽象类往往都是通过重构而来的!但是接口就不同,比如说飞,我们根本就不知道会有什么东西来实现这个飞接口,怎么实现也不得而知,我们要做的就是事前定义好飞的行为接口。所以说抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。
四.final关键字 final关键字的含义?final在Java中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误。 什么是final变量?凡是对成员变量或者本地变量(在方法中的或者代码块中的变量称为本地变量)声明为final的都叫作final变量。final变量经常和static关键字一起使用,作为常量。下面是final变量的例子: | public static final String LOAN = "loan"; LOAN = new String("loan") //invalid compilation error |
final变量是只读的。
什么是final方法?final也可以声明方法。方法前面加上final关键字,代表这个方法不可以被子类的方法重写。如果你认为一个方法的功能已经足够完整了,子类中不需要改变的话,你可以声明此方法为final。final方法比非final方法要快,因为在编译的时候已经静态绑定了,不需要在运行时再动态绑定。下面是final方法的例子:
什么是final类?使用final来修饰的类叫作final类。final类通常功能是完整的,它们不能被继承。Java中有许多类是final的,譬如String, Interger以及其他包装类。下面是final类的实例:
每一个技术小白都有一个成为大神的梦想,现在Android菜鸟饭团就给你这个成就梦想的机会。我们提供最新的Android技术教学,只要你又耐心和毅力就一定会在这里有所收获。 Android菜鸟饭团由 南阳GDG组织发起,秉承着开放、分享、创新的原则,希望通过GDG社区的力量能够给更多的想要学习Android开发技术的小白们创造一个学习,交流,分享的环境。同往常的GDG活动一样,我们依然是任性的一个子都不要,并且还在周六的分享中提供盒饭和不定期的惊喜小礼物呦~所以快来加入我们吧,为你的大神梦想迈出第一步。
|