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

一、封装

是指将对象的状态信息都隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。封装的优点:

  • 隐藏类的实现细节
  • 良好的封装能够减少耦合
  • 便于修改,提高代码的可维护性
  • 可进行数据的检查,有利于保证对象的信息完整性

二、继承

继承就是子类继承父类的特征和行为(通过关键字extends),使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。每一个子类只有一个直接的父类。

  • 继承的特性

    1.子类拥有父类非private的属性,方法

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

    3.子类可以用自己的方式实现父类的方法

    4.Java的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类。
  • this 和 super

    this关键字:指向自己的引用。构造器中引用该构造器正在初始化的对象;在方法中引用调用该方法的对象

    super关键字:用来实现对父类成员的访问,引用当前对象的父类。子类定义的实例方法中可通过super来访问父类中被隐藏的实例变量。

    总结:this和super都不能出现在static修饰的方法中;this调用的是同一类中的重载的构造方法,super调用的是其父类的构造方法,且调用时都必须放在第一行。
public class Test003 extends TestAll{
public Test003(){
super("003","me");
System.out.println("Test003 无参构造方法");
}
public static void main(String [] args){
new Test003();
}
}
class TestAll extends Tester{
public TestAll(String date){
System.out.println("TestAll 带一个参数构造方法,date=" +date);
} public TestAll(String date, String who){
this(date);
System.out.println("TestAll 带两个参数构造方法,date="+ date +" who="+who);
}
}
class Tester{
public Tester(){
System.out.println("Tester 无参构造方法");
}
}
// 打印结果为:
/*
Tester 无参构造方法
TestAll 带一个参数构造方法,date=003
TestAll 带两个参数构造方法,date=003 who=me
Test003 无参构造方法
*/

三、多态

多态是同一个行为具有多个不同表现形式或形态的能力。同一个实现接口,使用不同的实例而执行不同的操作。

引用变量的两种类型:编译时类型--由声明该变量时使用的类型决定;运行时类型--由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现多态。

public class SubClass extends BaseClass {
public String book = "READ BOOK";
public void sub(){
System.out.println("子类的普通方法");
}
public void test(){
System.out.println("子类test方法 , 《"+this.book+"》");
} public static void main(String [] args){
BaseClass bc = new BaseClass(); // 编译时类型与运行时类型一样,不存在多态
System.out.println(bc.book); // 10
bc.base(); //父类普通方法
bc.test(); //父类test方法 , book=10
// bc.sub(); 编译报错,父类不可以调用子类的方法 SubClass sc = new SubClass(); // 编译时类型与运行时类型一样,不存在多态
System.out.println(sc.book); //READ BOOK
sc.base(); //父类普通方法 ; 子类可以调用父类的方法
sc.sub(); //子类的普通方法
sc.test(); //子类test方法 , 《READ BOOK》 ; 覆盖了父类的test方法 BaseClass b = new SubClass(); // 编译时类型与运行时类型不一样,多态发生
System.out.println(((SubClass) b).book); // READ BOOK
System.out.println(b.book); // 10
b.base(); //父类普通方法
if(b instanceof BaseClass){
((SubClass) b).sub(); // 子类的普通方法 ; 强制类型转换
}
b.test(); //子类test方法 , 《READ BOOK》
}
}
class BaseClass{
public int book = 10;
public void base(){
System.out.println("父类普通方法");
}
public void test(){
System.out.println("父类test方法 , book=" + this.book);
}
}

该实例中 将子类的对象直接赋值给父类的引用变量b ,无需任何转型(向上转型)【子类是一种特殊的父类】。引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法

四、重载与重写

重写:子类包含与父类同名方法的现象,也称为方法的覆盖,重写发生在子类和父类的同名方法之间。重写遵循的规则:方法名相同、形参列表相同;子类的返回值类型比父类的更小或相等。;子类方法声明抛出的异常比父类的更小或相等;子类方法的访问权限比父类的更大或相等。

重载:主要发生在同一个类的多个同名方法之间。重载遵循的规则:参数个数或类型不一样;返回类型、修饰符也可以不一样;无法以返回值类型作为重载的区分标准。(典型的重载--构造器重载)

五、接口与抽象类

共同

  • 接口和抽象类都不能实例化,都位于继承树的顶端,用于被其他类实现和继承
  • 接口和抽象都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

差别

  • 接口里只能包含抽象方法、静态方法和默认方法,不能为普通方法提供方法的实现;抽象类则完全可以包含普通方法。
  • 接口只能定义静态常量,不能定义普通成员变量;抽象类里既可以定义普通成员遍历,也可以定义静态常量。
  • 接口里不包含构造方法;抽象类里可以包含构造方法--构造方法并不是用于创建对象,而是让子类调用这些构造方法来完成属于抽象类的初始化操作。
  • 接口不能包含初始化块;抽象类可以包含初始化块。
  • 一个类最多只能有一个直接的父类,包括抽象类;但一个类可以实现多个接口。一个接口可继承多个接口。

注意:接口里定义的内部类、接口、枚举默认都采用public static两个修饰符,不管定义时是否指定了这俩个修饰符,系统会自动使用public static对它们进行修饰。

public class Test0804 extends Speed implements Transport{
// 抽象类和接口都不能实例化,通过子类的构造方法进行初始化,
public Test0804(){
//super(); //可以隐藏
System.out.println("我是子类的无参构造方法");
}
public Test0804(int i) {
// 调用父类的构造方法初始化
super(i);
System.out.println("我是子类的带参构造方法");
} public static void main(String [] args){
// 接口
Test0804 t = new Test0804();
System.out.println("我是静态变量:"+Transport.HEIGHT);
Transport.tools();
t.run();
t.use(); System.out.println("----------------分割线-----------------");
// 抽象类
Test0804 t1 = new Test0804(2);
Speed.is();
t1.has(); // 通过子类实例对象,调用父类的普通方法
System.out.println("私有变量的值为:" + t1.getCount());
t1.print(); /* 结果为:
我是无参构造方法
我是子类的无参构造方法
我是静态变量:5
我是静态方法
实现了抽象方法 run
实现了默认方法 use
----------------分割线-----------------
我是带参构造方法
我是子类的带参构造方法
抽象类的静态方法
我是普通方法 count=2
私有变量的值为:2
实现了抽象类的抽象方法
*/ } // 重写接口的 run 方法
@Override
public void run() {
System.out.println("实现了抽象方法 run");
}
// 重写接口的 use 方法
@Override
public void use() {
System.out.println("实现了默认方法 use");
}
// 重写抽象类的 print 方法
@Override
public void print() {
System.out.println("实现了抽象类的抽象方法");
}
} interface Transport{
/* 接口里不包含构造方法,不能定义普通成员变量,不能为普通方法提供方法的实现,不能包含初始化块
private int i =0; //编译报错
public Transport(){ // 编译报错
}
public void run1(){ // 编译报错
System.out.println("我是普通方法");
}
// 编译报错
{
System.out.println("初始化块");
}
*/ int HEIGHT = 5; // 系统会自动添加 public static final
static void tools(){ // 系统会自动添加 public
System.out.println("我是静态方法");
}
void run(); // 抽象方法 自动添加 public abstract
default void use() {
System.out.println("我是默认方法");
}
} abstract class Speed{
private int count;
// 显示声明无参构造方法
public Speed(){
System.out.println("我是无参构造方法");
} public Speed(int count){
System.out.println("我是带参构造方法");
this.count = count;
} public abstract void print();
public static void is(){
System.out.println("抽象类的静态方法");
}
public void has(){
System.out.println("我是普通方法 count="+ this.count);
} public int getCount(){
return count;
}
}

六、继承与组合

继承表达式一种“是(is-a)”的关系,而组合表达的是“有(has-a)”的关系。对于继承而言,子类可以直接获得父类的public方法,程序使用子类时,将可以直接访问该子类从父类那里继承的方法;而组合则是把旧类对象作为新类的成员变量组合进来,用以实现新类的功能,用户看到的是新类的方法,而不能看到被组合对象的方法。

// ------继承------
public class InheritTest{
public static void main(String [] args){
Bird b = new Bird();
b.breath();
b.fly();
Fish f = new Fish();
f.breath();
f.swim();
}
} class Animal {
private void beat(){
System.out.println("心脏跳动...");
}
public void breath(){
beat();
System.out.println("吸一口气,吐一口气,呼吸中...");
}
}
//继承Animal ,直接复用父类的 breath 方法
class Bird extends Animal{
public void fly(){
System.out.println("我在天空飞翔...");
}
}
//继承Animal ,直接复用父类的 breath 方法
class Fish extends Animal{
public void swim(){
System.out.println("我在水里游动...");
}
}
// ------组合------
public class CompositeTest {
public static void main(String [] args){
Bird1 b1 = new Bird1(new Animal1());
b1.breath();
b1.fly(); Fish1 f1 = new Fish1 (new Animal1());
f1.breath();
f1.swim();
}
} class Animal1 {
private void beat(){
System.out.println("心脏跳动...");
}
public void breath(){
beat();
System.out.println("吸一口气,吐一口气,呼吸中...");
}
}
// 将原来的父类组合到原来的子类,作为子类的一个组合成分
class Bird1{
private Animal1 a;
public Bird1(Animal1 a){
this.a = a;
}
// 直接复用 Animal1提供的 breath 方法来实现 Bird1 的 breath 方法
public void breath(){
a.breath();
}
public void fly(){
System.out.println("我在天空飞翔...");
}
}
// 将原来的父类组合到原来的子类,作为子类的一个组合成分
class Fish1{
private Animal1 a;
public Fish1(Animal1 a){
this.a = a;
}
// 直接复用 Animal1提供的 breath 方法来实现 Fish1 的 breath 方法
public void breath(){
a.breath();
}
public void swim(){
System.out.println("我在水里游动...");
}
}

七、初始化块

Java使用构造器对单个对象进行初始化操作,使用构造器先完成整个java对象的状态初始化,然后将java对象返回给程序。与构造器作用类似的是初始化块,也可以对java对象进行初始化操作。

构造器与初始化块: 从某种程度来看,初始化块是构造器的补充,初始化块总是在构造器执行之前执行。

public class InitBlock {
public static void main(String [] args){
// 类初始化阶段(编译阶段),先执行最顶层父类的静态初始化块,直到执行当前类的静态初始化块
// 对象初始化阶段(执行阶段),先执行最顶层的父类初始化块、构造方法。直到执行到当前类的初始化、构造方法。
new Leaf(); /* 结果为:
Root 的静态初始化块
Mid 的静态初始化块
Leaf 的静态初始化块
Root 的普通初始化块
Root 的无参构造方法
Mid 的普通初始化块
Mid 的无参构造方法
Mid 的带参构造方法, 参数值:This is a test
Leaf 的普通初始化块
执行 Leaf 构造方法
*/
}
} class Root{
static{
System.out.println("Root 的静态初始化块");
}
{
System.out.println("Root 的普通初始化块");
}
public Root(){
System.out.println("Root 的无参构造方法");
}
} class Mid extends Root{
static{
System.out.println("Mid 的静态初始化块");
}
{
System.out.println("Mid 的普通初始化块");
}
public Mid(){
System.out.println("Mid 的无参构造方法");
}
public Mid(String msg){
this();
System.out.println("Mid 的带参构造方法, 参数值:"+msg);
}
} class Leaf extends Mid{
static{
System.out.println("Leaf 的静态初始化块");
}
{
System.out.println("Leaf 的普通初始化块");
}
public Leaf(){
super("This is a test");
System.out.println("执行 Leaf 构造方法");
}
}

注:

当JVM 第一次主动使用某一个类时,系统会在类准备阶段为该类的所有静态成员变量分配内存;初始化阶段则负责初始化这些静态成员变量,初始化静态成员变量就是执行类初始化代码块或声明类成员变量时指定的初始值,它们执行顺序与源代码中的排列顺序相同


注:讲解较详细的博客

本文大部分内容来自于《JAVA疯狂讲义》

Java_面向对象的更多相关文章

  1. Java_面向对象三大特征

    面向对象特征 面向对象三大特征: 继承, 封装, 多态 继承 继承: 子类可以从父类继承属性和方法 对外公开某些属性和方法 要点(eclipse中Ctrl+T查看继承结构) 1.父类也称超类, 基类, ...

  2. Java_面向对象的 static 和 abstract

    static:表示静态的 static:可以用来修饰属性.方法.代码块(或初始化块).内部类. 一.static修饰属性(类变量): public class TestStatic { //stati ...

  3. Java_面向对象中的this和super用法

    this: 1.使用在类中,可以用来修饰属性.方法.构造器 2.表示当前对象或者是当前正在创建的对象 3.当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加 this 来表明该变量时类成 ...

  4. ooday04 Java_面向对象_重写_static

    方法的重写(override/overriding):重新写.覆盖 发生在父子类中,方法名相同,参数列表相同 重写方法被调用时,看对象的类型------------这是规定,记住就OK 当派生类觉得超 ...

  5. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  6. 一起学 Java(二)面向对象

    一.方法函数 函数也称为方法,就是定义在类中的具有特定功能的一段独立代码.用于定义功能,提高代码的复用性. 函数的特点1> 定义函数可以将功能代码进行封装,便于对该功能进行复用:2> 函数 ...

  7. js面向对象学习 - 对象概念及创建对象

    原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...

  8. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  9. .NET 基础 一步步 一幕幕[面向对象之对象和类]

    对象和类 本篇正式进入面向对象的知识点简述: 何为对象,佛曰:一花一世界,一木一浮生,一草一天堂,一叶一如来,一砂一极乐,一方一净土,一笑一尘缘,一念一清静.可见"万物皆对象". ...

随机推荐

  1. 【12】Django 中间件

     前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装 ...

  2. [BZOJ 1095] [ZJOI 2007] 捉迷藏

    Description 传送门 Solution 先将原树转化成点分树: 然后维护三个堆: \(c[i]\) 保存点分树中子树 \(i\) 中的黑色节点到 \(fa[i]\) 的距离: \(b[i]\ ...

  3. vscode常用插件

    vscode写JS/html/css是比较适合的,因为轻量级. 只是需要一些插件来完善VSCODE功能,感觉VSCODE就是要靠插件的,不然的话,只是一个高级的代码编辑器.可能比editplus&qu ...

  4. Codeforces 1092C Prefixes and Suffixes(思维)

    题目链接:Prefixes and Suffixes 题意:给定未知字符串长度n,给出2n-2个字符串,其中n-1个为未知字符串的前缀(n-1个字符串长度从1到n-1),另外n-1个为未知字符串的后缀 ...

  5. msyql存储数据时字段被截断

    关于mysql中字段类型为text文本存储json格式数据,字段被截断的问题 背景: 字段类型 MEDIUMTEXT 确定存储内容5548个字符,换算为字节不超过16M 数据库内已经存在更长内容的存储 ...

  6. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

  7. Java基础 -- 持有对象(容器)

    一 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 Class clazz; 也可以通过数组来持有多个对象,如 Class[] ...

  8. 使用Zabbix监控mysql的主从同步

    Zabbix 监控触发器设置 简述 在生产环境中,有一台mysql的备份服务器,上面运行着三个数据库实例的从库,也在做日志的同步工作,为了实现对该备份服务器的监控,当出现从库实例不为3或者日志同步进程 ...

  9. vue(初探预渲染)

    ---恢复内容开始--- 一.前言 1.简介预渲染                     2.案例演示(不配置预渲染)                     3.配置预渲染, 二.主要内容 1.简 ...

  10. 04-oracle中的视图

    1.创建视图 介绍: 视图(View)通过SELECT查询语句定义,它是从一个或多个表(或视图)导出的,用来导出视图的表称为基表(Base Table),导出的视图称为虚表.在数据库中,只存储视图的定 ...