目录

1. 面向对象的三大特征之封装

1.1 封装的含义

1.2 封装的目的

1.3 封装的优点

1.4 封装的实现过程

1.5 拓展知识:JavaBean

2. 面向对象的三大特征之继承

2.1 继承的概念

2.2 如何实现继承

2.3 继承的作用

2.4 继承的类型

2.5 继承的特点

3. 私有化构造函数和单例模式

3.1 私有化构造函数的常景

3.2 单例模式

3.2.1 单例模式 (饿汉式)

3.2.2 单例模式 (懒汉式)

4. 方法重写 (覆盖)

5. 注解 (annotation)

6. super关键字

7. 对象的创建流程


面向对象的三大特征:封装、继承、多态

1. 面向对象的三大特征之封装

1.1 封装的含义

面向对象的封装有两层含义

  1. 类:属性、方法这些定义在类内部,其实就是一种封装,但并不是这里的三大特征之一

  2. 面向对象的封装是使用访问修饰符private将属性私有化的设计思想。

封装(英语:Encapsulation),是指为了安全考虑,在开发的过程中,会讲属性私有化 (private关键字修饰) ,需要提供对应接口完成设置和访问 (公开的setter和getter方法) 的过程。

1.2 封装的目的

  • 隐藏一个类中不需要对外提供的实现细节;

  • 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑, 限制对属性的不合理操作;

  • 便于修改,增强代码的可维护性

1.3 封装的优点

  1. 良好的封装能够减少耦合。

  2. 类内部的结构可以自由修改。

  3. 可以对成员变量进行更精确的控制。

  4. 隐藏信息,实现细节。

1.4 封装的实现过程

1. 修改属性的可见性来限制对属性的访问(一般限制为private),例如:

public class Person {private String name;private int age;
}

这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。

2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法(公开的setter和getter方法) ,用于对私有属性的访问,例如:

public class Person{private String name;private int age;
​public int getAge(){return age;}
​public String getName(){return name;}
​public void setAge(int age){this.age = age;}
​public void setName(String name){this.name = name;}
}

采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

访问上面这个封装后的属性,通过创建对象,调用对应的get/set方法进行属性的操作

public class PersonTest {public static void main(String[] args) {Person person = new Person();person.setAge(2);System.out.println(person.getAge());  // 2}
}

1.5 拓展知识:JavaBean

POJO对象:(Plain Ordinary Java Object) 标准的Java bean 对象

根据封装来写,私有化属性,提供公开的setter和getter方法,至少两个或者以上的构造方法

JavaBean是一种Java语言写成的可重用组件。符合如下标准的Java类:

  • 类是公共的

  • 有一个无参的公共的构造器

  • 有属性,且有对应的get、set方法

用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以 用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP 页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用 户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关 心任何改变。

案例:博客系统设计

板块:Board、文章:Article、作者:Author、回复:Comment/Reply等类

Board类

//import java.util.Arrays;public class Board {private int id; // 板块idprivate String name; // 板块名称private String intro; // 简介或描述
//  开发中尽量使用单项关联
//  private Article[] articles;@Overridepublic String toString() {return "Board [id=" + id + ", name=" + name + ", intro=" + intro + "]";}public Board() {super();}public Board(int id, String name, String intro) {super();this.id = id;this.name = name;this.intro = intro;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}//   public Article[] getArticles() {
//      return articles;
//  }
//
//  public void setArticles(Article[] articles) {
//      this.articles = articles;
//  }}

Article类

import java.util.Date;//import java.util.Arrays;public class Article {private int id; // 文章idprivate String tittle; // 标题private String content; // 内容private Author blogAuthor; // 作者private Board board; // 所属板块private Date publishTime; // 发布时间private Date modifyTime; // 修改时间@Overridepublic String toString() {return "Article [id=" + id + ", tittle=" + tittle + ", content=" + content + ", blogAuthor=" + blogAuthor+ ", board=" + board + ", publishTime=" + publishTime + ", modifyTime=" + modifyTime + "]";}public Article(int id, String tittle, String content, Author blogAuthor, Board board, Date publishTime,Date modifyTime) {super();this.id = id;this.tittle = tittle;this.content = content;this.blogAuthor = blogAuthor;this.board = board;this.publishTime = publishTime;this.modifyTime = modifyTime;}public Article() {super();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getTittle() {return tittle;}public void setTittle(String tittle) {this.tittle = tittle;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public Author getBlogAuthor() {return blogAuthor;}public void setBlogAuthor(Author blogAuthor) {this.blogAuthor = blogAuthor;}public Board getBoard() {return board;}public void setBoard(Board board) {this.board = board;}public Date getPublishTime() {return publishTime;}public void setPublishTime(Date publishTime) {this.publishTime = publishTime;}public Date getModifyTime() {return modifyTime;}public void setModifyTime(Date modifyTime) {this.modifyTime = modifyTime;}
}

Author类

//import java.util.Arrays;public class Author {private int id; // 作者idprivate String name; // 姓名private boolean gender; // 性别private int age; // 年龄private String intro; // 简介或描述
//  private Article[] articles;@Overridepublic String toString() {return "Author [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", intro=" + intro + "]";}public Author(int id, String name, boolean gender, int age, String intro) {super();this.id = id;this.name = name;this.gender = gender;this.age = age;this.intro = intro;}public Author() {super();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public boolean isGender() {return gender;}public void setGender(boolean gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getIntro() {return intro;}public void setIntro(String intro) {this.intro = intro;}
}

Comment类

package com.openlab.day12.blog;import java.util.Date;public class Comment {private int id; // 回复idprivate String content; // 内容private Author blogAuthor; // 作者private Date publishTime; // 发布时间private Date modifyTime; // 修改时间private Article article; // 文章@Overridepublic String toString() {return "Comment [id=" + id + ", content=" + content + ", blogAuthor=" + blogAuthor + ", publishTime="+ publishTime + ", modifyTime=" + modifyTime + ", article=" + article + "]";}public Comment(int id, String content, Author blogAuthor, Date publishTime, Date modifyTime, Article article) {super();this.id = id;this.content = content;this.blogAuthor = blogAuthor;this.publishTime = publishTime;this.modifyTime = modifyTime;this.article = article;}public Comment() {super();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public Author getBlogAuthor() {return blogAuthor;}public void setBlogAuthor(Author blogAuthor) {this.blogAuthor = blogAuthor;}public Date getPublishTime() {return publishTime;}public void setPublishTime(Date publishTime) {this.publishTime = publishTime;}public Date getModifyTime() {return modifyTime;}public void setModifyTime(Date modifyTime) {this.modifyTime = modifyTime;}public Article getArticle() {return article;}public void setArticle(Article article) {this.article = article;}
}

2. 面向对象的三大特征之继承

2.1 继承的概念

在面向对象中,类与类之间可以存在继承关系,继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

生活中的继承:

兔子和羊属于食草动物类,狮子和豹属于食肉动物类。

食草动物和食肉动物又是属于动物类。

所以继承需要符合的关系是:is-a,父类更通用,子类更具体。

虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。

生活中继承的例子还有很多,如财产继承、人的特征等等

2.2 如何实现继承

在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

类的继承格式

class 父类 {
}class 子类 extends 父类 {
}

父类 (超类、基类);子类

案例:RichMan类和他的子类Son类

RichMan类

package com.openlab.day12.inherit;public class RichMan {public String surname = "张";public double money = 1000000;private String honor = "Java";// 仅提供有参的构造方法 不提供无参的public RichMan(String surname, double money, String honor) {super();this.surname = surname;this.money = money;this.honor = honor;}//   public RichMan() {
//      // TODO Auto-generated constructor stub
//  }@Overridepublic String toString() {return "RichMan [surname=" + surname + ", money=" + money + ", honor=" + honor + "]";}public void say() {System.out.println("我的钱留给我的儿子!");}void test1() {System.out.println(this.money);}protected void test2() {System.out.println(this.honor);}
}

Son(与父类不同包下)

package com.openlab.day12;import com.openlab.day12.inherit.RichMan;public class Son extends RichMan {/**     发现当父类只存在有参构造方法的时候 ,子类去继承会报错*     原因是每一个构造方法都会存在一个隐藏的super()去调用父类的无参构造器*  而这里父类只是显示的声明了有参构造器 并没有声明无参构造器*  在子类的构造方法中,一定会调用父类的某个构造方法*    处理方法:通过super关键字指定调用父类的哪个构造方法 如果未指定就会自动调用父类无参构造* *    简单的说:在子类的构造方法里调用了父类有参的构造方法就行了*/public Son() {super("张", 1, "1");}public static void main(String[] args) {Son son = new Son();System.out.println(son.money);System.out.println(son.surname);
//      System.out.println(son.honor); // 错误:honor is not visible//      son.test1(); // 错误:The method test1() from the type RichMan is not visibleson.test2();son.say();}// 在子类中,重写方法,@Overridepublic void say() {// TODO Auto-generated method stubsuper.say();System.out.println("111111");}//    @Overridepublic void sayHello() {// TODO Auto-generated method stubSystem.out.println("Hello!");}
}

注意:private关键字修饰的属性和方法都是无法被子类继承的

protected关键字修饰的方法,就是用来给子类继承的!!!

2.3 继承的作用

  • 继承的出现减少了代码冗余,提高了代码的复用性。

  • 继承的出现,更有利于功能的扩展。

  • 继承的出现让类与类之间产生了关系,提供了多态的前提。

2.4 继承的类型

在Java中,也存在继承,Java是一种典型的单继承编程语言。需要注意的是 Java 不支持多继承,但支持多重继承。

2.5 继承的特点

  • 子类拥有父类非 private 的属性、方法。

  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

  • 子类可以用自己的方式实现父类的方法。

  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。

  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

3. 私有化构造函数和单例模式

3.1 私有化构造函数的常景

1. 工具类 (静态方法或者静态属性)

一般在一些工具类中,把全都是一些静态属性和方法,不需要修改,只需要调用即可,会把他的构造函数私有化,以不让其他的类创建该类的实例。之间通过类名称访问,不需要创建对象,如Math、Arrays等。

2. 单例模式

将构造函数私有化,使得该类不能以new的方式创建对象,而让该类使用自己创建好的那一个对象,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

3.2 单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁。

何时使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

应用实例:

  • 1、一个班级只有一个班主任。
  • 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
  • 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

优点:

  • 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
  • 2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景:

  • 1、要求生产唯一序列号。
  • 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

3.2.1 单例模式 (饿汉式)

饿汉式,是多线程安全的,实现容易,这种方式比较常用,但容易产生垃圾对象。

public class Singleton {// 饿汉式:单例模式private static Singleton singleton = new Singleton();// 1.私有化构造函数private Singleton() {}// 2.给室友者提供提供创建好的对象public static Singleton newInstance() {return singleton;}public static void main(String[] args) {Singleton s1 = Singleton.newInstance();Singleton s2 = Singleton.newInstance();System.out.println(s1 == s2);  // true}
}

3.2.2 单例模式 (懒汉式)

懒汉式,是线程不安全的,实现容易,这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。这种方式不要求线程安全,在多线程不能正常工作。

public class Singleton2 {// 懒汉式:单例模式private static Singleton2 singleton2 = null;private Singleton2() {}private static Singleton2 newInstance() {if (singleton2 == null) {singleton2 = new Singleton2();}return singleton2;}public static void main(String[] args) {Singleton2 s3 = Singleton2.newInstance();Singleton2 s4 = Singleton2.newInstance();System.out.println(s3 == s4);  // true}
}

4. 方法重写 (覆盖)

重写 (OverWrite)

覆盖 (OverRide)

发生在继承中,指的是,子类继承了父类的方法后,该方法不能满足子类,重写该方法,以达到满足子类使用。

访问修饰符 返回值类型 方法名() {}

注意重写的方法中不可缩小访问权限,尽量不要更改,返回值类型不可改变

方法重载 (OverLoad):

5. 注解 (annotation)

JDK5.0提供的新特性,利用反射技术,可以很轻松使用标准方法、属性、类等,从而扩展功能。

@ 加在属性、方法的上方

@Override :覆盖

@Deprecate :过时警告

6. super关键字

super 在Java中,是一个指针,类似于this关键字

this关键字代表当前对象的引用,用在当前类中。主要有三个用法

  • this(),代表在当前类中调用其他的构造方法,并且只能在构造方法中写,只能调用一次,只能写在第一行。
  • this.date,代表访问当前类中的成员属性。
  • this.func(),代表调用当前类中的其他成员方法。

注意:this并不代表当前对象,而是代表当前对象的引用,因为在当前类的构造方法中就已经可以使用this关键字了,而只有当构造方法完成之后该类的对象才算是被实例化出来。

super关键字代表父类对象的引用,主要有以下三个用法

  • super(),代表在当前类中调用其父类的构造方法,默认是不写的,是调用父类的无参构造。
  • super.data,代表访问父类的成员属性。
  • super.func(),代表访问父类的成员方法。

7. 对象的创建流程

  1. 使用java命令将源码(.java)进行编译,生成字节码文件(.class)

  2. javac命令执行字节码文件

  3. 将字节码文件加载进虚拟机(JVM),静态方法区开始加载静态资源

  4. JVM从静态方法区读取主函数,并加载进栈(执行栈被创建)

  5. main函数开始执行,创建对象的代码,如:Son son = new Son();

  6. 在堆内存中开辟对象的内存空间,并分配地址

  7. 创建成员变量并进行默认初始化

  8. 子类构造函数从非静态方法区加载进栈开始执行

  9. 第一句先执行父类的构造函数

  10. 父类构造函数执行,为子类继承到的成员变量进行初始化(对象内存空间里的父类空间)

  11. 父类构造函数弹栈执行完张

  12. 子类构造函数继续执行,此时先对成员变量进行显式初始化

  13. 再执行子类构造函数的内容,进行针对性初始化

  14. 执行完张,子类构造函数弹栈,将对象的内存空间地址赋予相应的引用变量

文章的结尾给大家普及几个面向对象的专业术语:

  • OO (Oriented Object) :面向对象

  • OOP (Oriented Object Programming):面向对象的编程

  • OOD (Oriented Object Design):面向对象的设计

  • OOA (Oriented Object Analysis):面向对象的分析

  • OOT (Oriented Object Test):面向对象的测试

Java-Day12 面向对象的三大特征之封装、继承,单例模式(饿汉式、懒汉式)、方法重写 (覆盖)、注解 (annotation)、super关键字、对象的创建流程超详细相关推荐

  1. php对象的三大特征,关于php中面向对象的三大特征(封装/继承/多态)

    最近在学习php的过程中发现它其实比java的语言要松散很多,而且很多人说上手比较容易,但是智言我个人并不是很认同这样的观点,因为其实java的整个语法规则都非常的有条有理,虽然函数很多,但是至少经常 ...

  2. 面向对象的三大特征:封装 继承 多态

    封装: 封装的概念: 代码的整合, 封装的层次: 函数的封装: 把一组操作整合在一起 类的封装: 把属性和方法整合在一起 结构的封装:根据操作的性质(模型/控制操作/交互视图)进行结构设计封装 ...

  3. java 单例模式 ---饿汉式懒汉式

    目录 单例设计模式 饿汉式 懒汉式 饿汉式vs懒汉式 结语 单例设计模式 所谓单例设计模式,就是采取一定的方法在整个软件系统中,对某个类只能存在一个对象实例 1.单例类只能有一个实例. 2.单例类必须 ...

  4. Java面向对象的三大特征(封装,继承,多态)

    一.封装 1.概念    封装是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的. 2.封装原则   将类的某些信息隐藏在类内部,不允许外部程序直接访问, ...

  5. 面向对象的三大特征,封装、继承、多态的个人理解以及代码分析

    面向过程:我们以前使用的是面向过程编程,你需要清除每个实现步骤,每个步骤每行代码都要仔仔细细的编写, 不知道过程就找不到结果,找到实现过程就可以得到实现结果. 例如: 我们在外打工租房子,我们需要了解 ...

  6. 面向对象的三大特征(封装、继承、多态)

    Java知识点总结:想看的可以从这里进入 目录 3. 面向对象三大特征 3.1.封装 3.2. 继承 3.3. 多态 3.3.1.对象的多态 1.向上转型 2.向下转型 3.3.2.方法的多态 1.重 ...

  7. 面向对象的三大特征:封装、继承、多态

    面向对象的三大特征 封装:提高程序的安全性 将数据(属性)和行为(方法)包装到类对象中.在方法内部对属性进行操作,在类对象的外部调用方法.这样,无需关心方法内部的具体实现细节,从而隔离了复杂度 cla ...

  8. 面向对象的三大特征:封装、继承和多态的简单概述

    一.封装 封装其实我们可以按照字面意思理解一下,就是将一些东西包装起来成为一个整体.比如:电视机,我们只需要连接制造厂商给我们留的接口,用遥控器来操作它就可以了,没必要去看电视机的内部结构是什么样子, ...

  9. 面向对象基础、面向对象的三大特征(封装、继承、多态)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 面向对象基础 概述 创建对象和类 类的三种定义方式 类的实例化 类的基本结构 面向对象之封装 概念 封装之对象的相关操作 封 ...

最新文章

  1. Error in xy.coords(x, y, xlabel, ylabel, log) : ‘x‘ and ‘y‘ lengths differ
  2. java中所有函数都是虚函数_关于Java:虚拟函数与纯虚函数之间的区别是什么?...
  3. CNN:测试一下YoloV3
  4. Guava ImmutableCollection简介
  5. Atomic原子类和Unsafe魔法类 详解
  6. 51Nod-1050 循环数组最大段和【最大子段和+最小子段和+DP】
  7. 查看kafka的主从状态_Kafka 集群部署
  8. Mybatis逆向工程(代码生成器)及其简单使用——及其报错处理
  9. 从零开始学游戏编程——可视化编程游戏开发工具学习指南
  10. 如何提高计算机打字,如何练电脑打字速度,教你如何科学提高打字速度
  11. LVS的NAT、TUNNEL、Full-NAT模式
  12. python实现次梯度(subgradient)和近端梯度下降法 (proximal gradient descent)方法求解L1正则化
  13. css 横线中间的文字
  14. 物理层的传输介质和设备
  15. log4j不生成log文件
  16. 标准解读系列之六:车联网网络安全标准进展
  17. linux中bash是什么命令,Bash简介 Bash是如何处理命令的
  18. CodeForces - 855B - Marvolo Gaunt's Ring(线段树 or DP)
  19. 人脸检测,关键点识别,人脸对齐
  20. Linux服务器各应用版本信息查看总结

热门文章

  1. JavaScript 的多事之秋
  2. 内核中line discipline的注册流程以及BT hciattach进程的启动
  3. 半监督学习之MixMatch(代码解读 ablation)
  4. python爬虫多线程是什么意思_python爬虫14 | 就这么说吧,如果你不懂多线程和线程池,那就去河边摸鱼!...
  5. 如何用自媒体引流?学会这3招足矣,日引500+精准粉
  6. 编程语言-闭包-浅析
  7. 基本图片格式特点和区别(bmp/tif/png/jpg/gif/webp/ico/svg/raw)
  8. 【绿盟】检测到目标Referrer-Policy响应头缺失
  9. C语言入门之变量、常量、字符串、转义字符
  10. linux用gzip文件怎么打开,linux下怎么解后缀名是gzip的文件?