Java面向对象思想的理解

首先,Java中,除了8种基本数据类型。其他皆为对象。

Java的8种基本数据类型:byte  short  int  long  float  double  char  boolean. 
基本数据类型的值,是直接存储在线程的方法栈中的
而对象的值存储在堆(Heap)中,在方法栈的栈帧里,只存了对象的地址引用
PS:详见JVM内存模型

面向对象主要有
三个基本特征:封装继承多态
五个基本原则: SOLID原则,即:

  • 单一职责原则(SRP)
  • 开放封闭原则(OCP)
  • 里氏替换原则(LSP)
  • 接口隔离原则(ISP)
  • 依赖倒置原则(DIP)

三个基本特征

基本特征的体现

封装

主要概念是指:隐藏对象的属性和实现细节,仅对外暴露公共的访问方式。封装是面向对象最基本的特征之一,是类和对象概念的主要特性。

良好的封装所具有的优点:
1,隐藏信息和细节,提高安全性
2,良好的封装可以减少耦合性,提高复用性
3,对类内部结构可以随意修改,只要保证公有接口始终返回正确的结果即可。

在Java中的体现:
public default protected private 等设置访问权限的关键字
例如,类的属性私有化 private修饰,提供公有的 setter getter 方法对值进行获取和修改。
同时,还可以在setter getter函数里进行数据校验和对返回值做限制。这就是提高安全性的体现。



继承

继承是一种联结类的层次模型,Java允许并且鼓励代码的重用,继承提供了一种明确表示共性的方法,来使代码可以进行复用。

继承的出现,让类与类之间产生了关联,提供了多态的前提条件

讲到继承,就要提到三个东西:构造器,protected关键字,向上转型:

1,构造器:我们已经知道,父类中private修饰的属性和方法子类是无法继承的,而还有一个无法继承的就是 构造器。构造器只能调用而不能被继承。
类在实例化的时候会调用自身构造器,而java编译器会默认在子类构造器的第一行用super()先调用父类的无参构造器。如果父类没有无参构造器,则子类在实例化的时候会报错。这个时候就需要显示的在子类构造器第一行(必须在第一行)指定构造器super(args)来指定调用父类哪个构造器。

2,protected关键字:proctected关键字修饰的属性和方法,可以隔绝外部其他类的访问,却可以让子类有权限访问。
但是最好还是把属性都以private修饰,父类中希望子类可以访问到,又不希望公有的方法,可以用protected修饰

3,向上转型:最典型的还是List list = new ArrayList() 将子类的实例声明为父类的类型,提高了通用性,也隐藏了子类的具体实现。因为这是一个由专用向通用的转换,所以总是安全的。唯一缺陷就是专有属性和方法的丢失。

但是继承同时又存在缺陷:
1),继承是一种强耦合关系,子类会由于父类的改变而改变
2),继承破坏了封装的特性,对于父类而言,它的实现和细节对于子类来说都是透明的
所以到底要不要继承:《Thinking in java》提供了一个解决方案:问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承

使用继承的时候,一定要注意,两个类之间是从属关系,父子关系 的。子类应该是基于父类原有的特性,派生出来,并在无需编父类代码的情况下,提供扩展的功能和方法。
不要为了使用某个类的其中一个特性,而去继承该类。



多态

多态,指的就是:
程序中定义的引用变量所指向的具体类型,和通过该引用变量发出的方法调用,在编程期间并不确定,而是在程序运行期间才确定

如何理解多态
因为在程序运行时才确定到具体的类,所以不用修改源码,就能让引用变量绑定到不同的类型实现上,从而导致引用调用的方法发生改变,即不修改具体代码,就可以让程序在运行时改变绑定的具体代码,表现不同的运行状态。这就是多态性。

多态的好处
多态允许不同类对象,对同一个消息作出响应。即同一个消息可以根据发送对象的不同而采用不同的行为方式(发送消息就是函数调用)。
主要好处如下:

1)可替换性。多态对已存在的代码具有可替换性。
2)可扩充性。新增加的子类不影响已经存在的类结构。
3)接口性。多态是父类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的。
4)灵活性。
5)简化性。

Java中多态的体现

  • 重写(覆盖)
  • 动态链接(动态调用)
  • 重载

多态的三个必要条件

  • 继承
  • 重写
  • 向上转型。

多态的作用
我们知道,封装可以隐藏细节,使得代码模块化,继承可以扩展已存在的模块化代码(父类),实现代码的复用。

而多态,则是实现了接口的复用,多态的作用,就是在类的实现和派生的时候,保证使用基类下面,任意一个子类实例的属性和方法,都可以正确调用。

虚拟机如何实现多态
在JVM中,是使用了动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法.

重载严格意义上并不属于多态,重载的具体实现是:编译器根据不同的参数表,对同名函数的名称做修饰,然后这些同名函数就变成了不同的函数。对重载函数的调用,在编译期间就已经确定了,是静态的(注意!是静态的),因此,重载和多态无关。
真正和多态相关的是重写,当子类重写了父类中的函数后,父类的 指针,根据赋值给它不同的子类对象指针,动态的调用属于子类的该函数,这样在编译期间是无法确定的,只有在运行期间,才会把动态链接转变为直接引用(称为动态链接,详见JVM内存模型-栈帧)



五个基本原则


  • 单一职责原则(Single-Resposibility Principle SRP)
    对一个而言,应该仅有一个引起它变化的原因

本原则是我们非常熟悉的"高内聚原则"的引申。同时,本原则还揭示了内聚性和耦合性:如果一个类承担的职责过多,那么这些职责就会相互依赖,一个职责的变化可能会影响另一个职责的履行。其实OOP的实质,就是合理进行类的职责分配


  • 开—闭原则(Open-Closed principle OCP)
    软件应该是可以扩展的,但是不可以修改

也就是对扩展开放,对修改封闭。当变化来临时,不需要(或者不允许)修改原来的代码,只需要在原有的基础上扩展(同时原有的代码也要求支持扩展),那么这个软件设计就是满足开闭原则的。
此原则在Java中最典型的体现就是:抽象类 抽象基类接口。通过抽象类,把一些不可变的操作封装起来,而提供抽象接口供子类实现,来实现各自变化的需求。
这个原则应用在类的设计中,要满足该原则就要充分的考虑到接口封装,抽象机制和多态。


  • 里氏替换原则(Liskov-Substituion Principle LSP)
    子类型必须能够替换掉它们的基类型

本原则和开闭原则关系密切,正是基于子类的可替换性,才使得基类可以无需修改,只要子类继承就可以实现扩展特性。这是保证继承复用的基础

在Java中的典型体现就是 基于接口的框架设计,例如JDBC集合类
JDBC只提供了基本的接口,返回的对象类型也是接口,这样就在选择返回对象的时候,有了更大的灵活性:只要是继承了返回接口类型的子类实例,都可以作为结果返回。而服务提供者无需暴露子类的实现,调用者也无需关心子类的实现。而提供者在对实现进行优化升级时,对调用者也是不可见,同时也没有影响的。

集合类提供了一些基本集合的接口,例如 List Map Set。我们可以在声明时用这些接口类型作为声明对象,无需关心具体的实现类型是如何操作的,集合框架可以很好的把实现类型和代码隐藏起来,对调用者透明。例如List可以用来接收ArrayList,也可以用来接收LinkedList。可以用来接收任何实现了List接口的类的实例。
以上两点,充分的利用了里氏替换原则的特性,实现了封装的基本特征。


  • 接口隔离原则(Interface-Segregation Principle ISP)
    多个专用接口优于一个单一的通用接口

本原则是单一职责原则用于接口设计的自然结果。基本思想就是,不要让客户端依赖他们不需要的接口。
一个接口应该保证,实现该接口的实例对象可以只呈现一个单一的角色。这样当接口发生改变时,对其他客户端造成的影响会更小。
把多个不同职责的功能分到不同的接口中去,提高代码的灵活性和稳定性,降低耦合性。


  • 依赖倒置原则(Dependecy-Inversion Principle DIP)
    抽象不应该依赖于细节,细节应该依赖于抽象

具体来说就是,软件设计中,高层不依赖于低层,两者都依赖于抽象。抽象应该依赖于抽象,而不依赖于具体实现细节。即:对接口编程

在Java中的体现还是,接口抽象类
拿最简单的Spring IOC来说,当我们注入的时候,接收参数类型应该是接口,而注入的对象,可以是实现了接口的各种子类,当我们想改变接口表现的特性的时候,无需修改代码,只要修改注入的实现类对象就可以。

RPC框架(例如Dubbo)开放的接口也同样基于这个原则。
上面说的JDBC,集合类框架 都基于这个原则来提供实现。提供接口对象,而把实现类隐藏在内部。



(如果有什么错误或者建议,欢迎留言指出)


参考资料:
面向对象的三个基本特征和五个基本原则
面向对象的五个基本原则
Java面向对象的特征
理解Java的三大特性之多态(这个博主东西很全)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容

  • 单一职责原则 (SRP) 全称 SRP , Single Responsibility Principle 单一职...
    米莉_L阅读 1,765评论 2 5
  • 面向对象的3个基本要素: 封装、继承、多态 面向对象的5个基本设计原则: 单一职责原则(Single-Respos...
    badcyc阅读 859评论 0 4
  • 参考资料:菜鸟教程之设计模式 设计模式概述 设计模式(Design pattern)代表了最佳的实践,通常被有经验...
    Steven1997阅读 1,173评论 1 12
  • 本文出自《Android源码设计模式解析与实战》中的第一章。 1、优化代码的第一步——单一职责原则 单一职责原则的...
    MrSimp1e0阅读 1,770评论 1 13
  • 1、安装virtualenv 当你拥有的项目越多,同时使用不同版本的 Python 工作的可能性也就越大,...
    那夜你很美阅读 323评论 0 0