如果说算法+数据结构=程序,那么面向对象程序设计OOP(Object Oriented Programming)实际上就是对于一个问题,先考虑数据的组织形式,再根据问题设计数据的操作(算法)。因此在OOP中,数据是第一位的。
什么是面向对象式编程?
想要明白这个问题就需要了解一个概念——编程范式(Programming Paradigm)
我们知道,程序=算法+数据结构(出自Niklaus Wirth,图灵奖得主,Pascal之父),而又有算法=控制+逻辑(出自Robert.B.Kowalski)。
所以我们可以得出:程序=逻辑+控制+数据结构。其中,数据结构最好理解,即为数据的存储和组织形式,包括逻辑结构和物理结构。而逻辑即为真正操作数据的代码部分,比如:a=a+1。控制即控制代码,表示如何运行逻辑,比如如何流程控制怎么设计、先干什么再干什么、递归还是迭代。那么根据如何组织这三者的方式就产生了不同的编程范式。
显然,逻辑决定了程序真正去做什么,而控制决定了怎么去做。
举几个较为典型的编程范式来说:
命令式编程(Imperative Programming):命令式编程是一种最直接的编程思想,他要求写出一条条的指令来要求计算机如何执行,几乎所有计算机的硬件工作都是命令式的。
命令式编程可以看做带有纸带输入的图灵机求解过程,由全局变量以及为全局变量赋的值的不同可以代表当前程序的状态(可以大概理解成,根据全局变量值的不同发现程序执行到哪了),程序中可以有循环等控制语句。
如果这些概念看起来很普通,那么其实是对的,如果让用你代码解决一个简单问题,不允许构建对象,那么写出来的程序一般都是符合命令式编程思想的。
Connection conn = null; conn = getConnection(); if(conn != null){ do something.. }
函数式编程(Functional Programming):再来看看函数式编程,函数式编程将计算描述为表达式求值。函数是一等公民,他可以在任何地方定义,也可以作为另一个函数的参数和返回值。
一个纯的函数式编程是不允许出现全局变量的,程序中出现的变量也不允许被再次赋值。也就是说一个函数只是作为表达式求解的过程,除了函数的输入外完全不依赖与程序的其余状态和外部环境。是纯粹的将数学函数的思维转换成代码。(可以理解成将f(x)=...编写成代码,毕竟f(x)内部只有关于x计算过程)
函数式编程完全不同于使用了函数的命令式编程,其运行模式与图灵机或指令序列不同,是来自于λ演算的。
/** * 以求解斐波那契数列为例,函数中不会出现变量,没有变量控制自然也不会出现循环。所以只能使用递* 归解决循环问题 */ public void Fibonacci(int n){ if(n == 1 || n == 2){ return 1; } return Fibonacci(n - 2) + Fibonacci(n - 1); }
面向对象式编程(Object-Oriented Programming):面向对象编程即把程序中的逻辑问题考虑成对象的交互。在面向对象变成的世界是生动的由一个个对象和其行为组成的,对象有其自己的属性、行为(方法),将程序设计成这些对象的互动以求得最后的结果。显然,这样的程序更容易被现实世界的人类所理解。
声明式编程(Declarative Programming):你只需要告诉计算机你要做什么而不需要告诉计算机怎么做即可。典型的语言如SQL,你在执行SELECT * FROM Student WHERE Score > 60; 你并不用考虑记录有多少条,怎么进行筛选,只需要按该语言的语法描述出你想要的就可以。
一般来说,一个语言可以支持一种或多种编程范式,那么Java是如何支持范式的呢?
在学习Java时,我们总会听说Java是一门纯面向对象的语言,一切都是为对象服务,变量、方法都是对象的属性。但是随着我们学习的深入,我们是不是会感到困惑:类中有与对象无关的静态变量,基本数据类型也不具备和对象相同的使用原则,那么这还可以叫做纯面向对象的语言吗?下面通过几个方面的例子来说明:
Java虚拟机中的类对象
首先,若我们学过反射,你是否会通过Class.forName("a class Name"); 来获取一个Class对象。其实,Class也是一个Java类,保存的是与之对应Java类的meta信息(元信息),用来描述这个类的结构,比如描述一个类有哪些成员,有哪些方法等。
在我们第一次创建一个Java对象时,实际上不仅创建了一个类的实例对象保存对象属性,还创建了该类的Class对象保存类的元信息。JVM对Class对象只会加载一次,多个实例对象只对应一个Class对象。所以对于静态变量或静态方法,实际上是作为Class对象的属性存在的,当调用他们时,其实就是在调用Class对象的属性。
Java虚拟机中的基本数据类型
在Java中,八种基本数据类型是不能对象一样使用的。比如类型变量调用clone()方法、hashCode()方法。对于使用者来说,基本数据类型确实算不上对象。但是,我们通过查看Class.isPrimitive()方法,可以看到:
即八种基本数据类型和void是由JVM创建好的对象作为原始类型。他们的Class对象等于相应包装类的TYPE常量。
Java8的Lambda表达式
在Java8中Java引入了Lambda表达式,其形式为:
(parameters) -> expression
或
(parameters) ->{ statements; }
Lambda表达式是一种典型的函数式编程特性。不过在编译时,Lambda表达式最终是通过InnerClassLambdaMetafactory类来创建匿名内部类来实现的。最后会转换成Class对象。
综上,Java语言可以支持多种范式编程。但对于底层JVM来说,其逻辑仍然是通过纯面向对象的思路进行处理的