面向对象回顾(构造函数、覆盖和重载、Query接口的list方法和iterate方法、面向对象的六原则一法则、反射、内部类)
1. 什么是构造函数?什么是构造函数重载?什么是复制构造函数?
当新对象被创建的时候,构造函数会被调用。
每一个类都有构造函数。
在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。
Java中构造函数重载和方法重载很相似。
- 可以为一个类创建多个构造函数。
- 每一个构造函数必须有它自己唯一的参数列表。
Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。
2. 方法覆盖(Overriding)和方法重载(Overloading)是什么意思?
Java中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。
与此相对,方法覆盖是说子类重新定义了父类的方法。
- 方法覆盖必须有相同的方法名,参数列表和返回类型。
- 覆盖者可能不会限制它所覆盖的方法的访问。
2.1 重载(Overload)和重写(Override)的区别
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。
重载的方法能否根据返回类型进行区分?——不能
Overloaded的方法是可以改变返回值的类型。
3. Query接口的list方法和iterate方法有什么区别?
3.1 缓存
- list()方法无法利用一级缓存和二级缓存(对缓存只写不读),它只能在开启查询缓存的前提下使用查询缓存;
- iterate()方法可以充分利用缓存,如果目标数据只读或者读取频繁,使用iterate()方法可以减少性能开销。
3.2 N+1
- list()方法不会引起N+1查询问题;
- 而iterate()方法可能引起N+1查询问题。
4. 面向对象的"六原则一法则"
4.1 单一职责原则
一个类只做它该做的事情。
单一职责原则想表达的就是"高内聚"。
写代码最终极的原则只有六个字"高内聚、低耦合"
- 高内聚就是一个代码模块只完成一项功能。
- 在面向对象中,如果只让一个类完成它该做的事,而不涉及与它无关的领域就是践行了高内聚的原则,这个类就只有单一职责。
- 另一个是模块化。
- 好的自行车是组装车,从减震叉、刹车到变速器,所有的部件都是可以拆卸和重新组装的,好的乒乓球拍也不是成品拍,一定是底板和胶皮可以拆分和自行组装的;
- 一个好的软件系统,它里面的每个功能模块也应该是可以轻易的拿到其他系统中使用的,这样才能实现软件复用的目标。
4.2 开闭原则
软件实体应当对扩展开放,对修改关闭。
在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。
要做到开闭有两个要点:
- 抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;
- 封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱。
如果不清楚如何封装可变性,可以参考《设计模式精解》一书中对桥梁模式的讲解的章节。
4.3 依赖倒转原则
面向接口编程。
该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型。
因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。
里氏替换原则
- 任何时候都可以用子类型替换掉父类型。
- 关于里氏替换原则的描述,Barbara Liskov女士的描述比这个要复杂得多,但简单的说就是能用父类型的地方就一定能使用子类型。
- 里氏替换原则可以检查继承关系是否合理。
- 如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。
- 例如让猫继承狗,或者狗继承猫,又或者让正方形继承长方形都是错误的继承关系,因为你很容易找到违反里氏替换原则的场景。
- 需要注意的是:子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。
4.4 接口隔离原则
接口要小而专,绝不能大而全。
臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。
例如,琴棋书画就应该分别设计为四个接口,而不应设计成一个接口中的四个方法,因为如果设计成一个接口中的四个方法,那么这个接口很难用,毕竟琴棋书画四样都精通的人还是少数,而如果设计成四个接口,会几项就实现几个接口,这样的话每个接口被复用的可能性是很高的。
Java中的接口代表能力、代表约定、代表角色,能否正确的使用接口一定是编程水平高低的重要标识。
4.5 合成聚合复用原则
优先使用聚合或合成关系复用代码。
通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对继承进行了鼓吹从而误导了初学者。
类与类之间简单的说有三种关系:
- Is-A关系——代表继承
- Has-A关系——代表关联
- Use-A关系——代表依赖
其中,关联关系根据其关联的强度又可以进一步划分为:
- 关联;
- 聚合;
- 合成
但说白了都是Has-A关系。
合成聚合复用原则想表达的是优先考虑Has-A关系而不是Is-A关系复用代码
记住:任何时候都不要继承工具类,工具是可以拥有并可以使用的,而不是拿来继承的。
4.6 迪米特法则
迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。
再复杂的系统都可以为用户提供一个简单的门面。
Java Web开发中作为前端控制器的Servlet或Filter不就是一个门面吗,浏览器对服务器的运作方式一无所知,但是通过前端控制器就能够根据你的请求得到相应的服务。
调停者模式也可以举一个简单的例子来说明:
- 例如一台计算机,CPU、内存、硬盘、显卡、声卡各种设备需要相互配合才能很好的工作,
- 但是如果这些东西都直接连接到一起,计算机的布线将异常复杂,
- 在这种情况下,主板作为一个调停者的身份出现,
- 它将各个设备连接在一起而不需要每个设备之间直接交换数据,这样就减小了系统的耦合度和复杂度。
5. 反射
5.1 如何通过反射获取和设置对象私有字段的值?
可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象的setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值了。
下面的代码实现了一个反射的工具类,其中的两个静态方法分别用于获取和设置私有字段的值,字段可以是基本类型也可以是对象类型且支持多级对象操作,例如ReflectionUtil.get(dog, "owner.car.engine.id");可以获得dog对象的主人的汽车的引擎的ID号。
import java.lang.reflect.Method;
class MethodInvokeTest {public static void main(String[] args) throws Exception {String str = "hello";Method m = str.getClass().getMethod("toUpperCase");System.out.println(m.invoke(str)); // HELLO}
}
5.2 如何通过反射创建对象?
- 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
- 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");
6. 内部类可以引用他包含类的成员吗,如果可以,有没有什么限制吗?
一个内部类对象可以访问创建它的外部类对象的内容。
内部类如果不是static的,那么它可以访问创建它的外部类对象的所有属性;
内部类如果是sattic的,即为nested class,那么它只可以访问创建它的外部类对象的所有static属性。
一般普通类只有public或package的访问修饰,而内部类可以实现static,protected,private等访问修饰。
当从外部类继承的时候,内部类是不会被覆盖的,它们是完全独立的实体,每个都在自己的命名空间内,如果从内部类中明确地继承,就可以覆盖原来内部类的方法。
6.1 Static Nested Class 和 Inner Class的不同
Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。
而通常的内部类需要在外部类实例化后才能实例化。
Static-Nested Class 的成员, 既可以定义为静态的(static), 也可以定义为动态的(instance)。
Nested Class的静态成员(Method)只能对Outer Class的静态成员(static memebr)进行操作(ACCESS), 而不能Access Outer Class的动态成员(instance member)。
而 Nested Class的动态成员(instance method) 却可以 Access Outer Class的所有成员。 这个概念很重要,许多人对这个概念模糊.。
有一个普通的原则, 因为静态方法(static method) 总是跟 CLASS 相关联(bind CLASS),而动态方法( (instance method) 总是跟 instance object 相关联。所以,静态方法(static method)永远不可以Access跟 object 相关的动态成员(instance member);反过来就可以, 一个CLASS的 instance object 可以 Access 这个 Class 的任何成员,包括静态成员(static member)。
面向对象回顾(构造函数、覆盖和重载、Query接口的list方法和iterate方法、面向对象的六原则一法则、反射、内部类)相关推荐
- 面向对象的特征与“六原则一法则”
面向对象的特征 主要有抽象.继承.封装和多态四个方面,下面是我们来详细分析它们的含义: - 抽象: 抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属 ...
- Java原理 面向对象的特征与“六原则一法则”
面向对象的特征 主要有抽象.继承.封装和多态四个方面,下面是我们来详细分析它们的含义: - 抽象: 抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属 ...
- 面向对象开发方法,Coad方法、Booch方法和OMT方法及UML
目前,面向对象开发方法的研究已日趋成熟,国际上已有不少面向对象产品出现.面向对象开发方法有Coad方法.Booch方法和OMT方法等. (1).Booch方法 Booch最先描述了面向对象的软件开发方 ...
- 【系统分析师之路】面向对象开发方法,Coad方法、Booch方法和OMT方法及UML
[系统分析师之路]面向对象开发方法,Coad方法.Booch方法和OMT方法及UML 目前,面向对象开发方法的研究已日趋成熟,国际上已有不少面向对象产品出现.面向对象开发方法有Coad方法.Booch ...
- 【设计原则】面向对象的设计原则(六原则一法则)
(一)单一职责原则:一个类只做它该做的事情. 单一职责想表达的就是"高内聚",所谓高内聚就是一个代码模块只完成一项功能,在面向对象中,如果只让一个类完成它该做的事,而不涉及与它无关 ...
- java实现Comparable接口和Comparator接口,并重写compareTo方法和compare方法
原文地址https://segmentfault.com/a/1190000005738975 实体类:java.lang.Comparable(接口) + comareTo(重写方法),业务排序类 ...
- 实现Comparable接口和Comparator接口,并重写compareTo方法和compare方法
实体类:java.lang.Comparable(接口) + comareTo(重写方法),业务排序类 java.util.Comparator(接口) + compare(重写方法). 这两个接口我 ...
- [享学Eureka] 三十一、DiscoveryClient透彻解析(八):接口方法和shutdown()方法详解
成为一个成功者最重要的条件,就是每天精力充沛的努力工作,不虚掷光阴. –> 返回Netflix OSS套件专栏汇总 <– 代码下载地址:https://github.com/f641385 ...
- java写一个外网访问的接口_【JAVA基础】一个案例搞懂类、对象、重载、封装、继承、多态、覆盖、抽象和接口概念及区别(中篇)...
0 前言 初学JAVA时,总会对一些概念一知半解,相互混淆,不明其设计的用意,如类.对象.重载.封装.继承.多态.覆盖.抽象类.接口概念.为便于理解和巩固,本文将基于一个案例及其变形,展现各个概念的定 ...
最新文章
- Grub 修复(文件损坏)有备份
- onclick函数的导包问题
- html5 coverflow,使用FancyCoverFlow实现3D无限循环切换视图
- 0603学术诚信与职业道德
- 【架构师培训课程-技术基础课】
- 关于集合中元素的有序无序的易混淆点
- Javascript Asynchonous Progamming
- 罗马仕php30重量,充电宝多少毫安最好?这3款罗马仕充电宝必须收藏
- 我对python的理解_python高级函数以及我对python的理解
- python中find函数的使用方法_Python教程-String 字符串使用教程
- unity package 包下载不下来
- CHIP-SEQ 芯片分析时,对于来自重复实验的数据,怎样进行MACS peaks calling 分析?
- 【20保研】2019年中科院沈阳计算所大学生暑期夏令营通知
- linux文件扫描并打印,Linux办公一条龙—Linux中扫描、打印的实现
- 华为10误删照片怎么才能恢复回来?
- Java mail 535鉴权失败或启动报错
- (文末福利)如果代码莫名其妙跑起来了,就不要去动它了……吗?
- Softing新版HART多路复用器软件支持西门子控制器
- padding在css中是什么意思,padding
- 在网页中调用iOS客户端