面向对象是一种现在最为流行的程序设计方法,几乎现在的所有应用都以面向对象为主了,最早的面向对象的概念实际上是由IBM提出的,在70年代的Smaltalk语言之中进行了应用,后来根据面向对象的设计思路,才形成C++,而由C++产生了Java这门面向对象的编程语言。
但是在面向对象设计之前,广泛采用的是面向过程,面向过程只是针对于自己来解决问题。面向过程的操作是以程序的基本功能实现为主,实现之后就完成了,也不考虑修改的可能性,面向对象,更多的是要进行子模块化的设计,每一个模块都需要单独存在,并且可以被重复利用,所以,面向对象的开发更像是一个具备标准的开发模式。
在面向对象定义之中,规定了JAVA面向对象的三个基本特征:
(1)封装:保护内部的操作不被破坏;(2)继承:在原本的基础之上继续进行扩充;(3)多态:在一个指定的范围之内进行概念的转换。对于面向对象的开发来讲也分为三个过程:OOA(面向对象分析)、OOD(面向对象设计)、OOP(面向对象编程)。
对象里面最基本的是属性和方法。对象是整个面向对象编程中最基础的组成单元。在java中,万物皆对象。
在之前的章节中,我们建的所有类(class),实际上都是一个个的对象,对象里面有一个main方法,是我们开始程序的地方,如果 类中没有main方法,类就无法单独运行。简单的说类就是对象,但对象不一定是类(如interface)。
对象中,可以有一个或多个属性、方法,也可以没有任何的属性方法,以下定义都是合法的:
public class Person { String name = "张三"; int age = 37; char sex = '男'; } public class School { public void getSchoolName() { System.out.println("河南工业大学"); } public String getFacultyNmae() { return "软件学院"; } }String是一个字符串对象(或者字符串类),用来存储字符串。它跟8种基本类型不一样,它有很多的方法,而8种基本类型没方法没属性,所以基本类型不是对象。
下面是一个简单的例子,定义一个类,调用方法,打印类中的参数:
public class JiSuan { int a = 10; int b = 5; /** * 定义一个计算a+b并打印结果的方法 */ public void jiSuan() { int sum = a + b; System.out.println("a+b=" + sum); } public static void main(String[] args) { JiSuan jiSuan = new JiSuan(); //调用jiSuan方法 jiSuan.jiSuan(); //打印对象中a的值 System.out.println("a=" + jiSuan.a); //修改对象中a的值 jiSuan.a = 666666; System.out.println("a=" + jiSuan.a); } }这里面引入了一个新的关键字:new。在这段代码里,我们新建了一个对象(类)JiSuan。在main方法里面,需要先定义一个“JiSuan”类型的对象(或者称之为对象变量),定义的方法跟定义基本类型相似(int a = 1;),只不过“=”后面我不是直接赋值,而是使用了new。对象中有两个极为重要的概念:堆、栈。
定义一个完整的方法,一般是作用域 返回值类型 方法名(参数){}:
作用域:常用的是public,直译为公共的。意思是该属性或者方法使用范围,public定义的属性、方法,可以在任意地方使用,比如可以被其他类调用。相对的还有private,直译为私有的,只能在定义的类中使用以后章节会详细讲解。
返回值类型 :方法直接结束返回的类型,之前定义的是void,直译为空,意思是不反悔任何值。如果把void改为int或者String,就能通过return返回相应类型的值。
方法名:没特殊要求,一般是驼峰命名法即可,根据java规范,变量名、方法名一般用字母、数字、下划线组成,开头可以是下划线,但一定不能是数字。
参数:上面的代码中,小括号里是没有任何东西的,表示不需要传参,也可以在这里面定义一个或多个变量,用来接收外部调用方法时传入的参数。
当定义好jiSuan后,只需要通过运算符“.”调用就行了,如“.属性”、“.方法”,或者直接修改属性。
定义和使用一个传参并带有返回值的方法:
public class JiSuan { int a = 10; int b = 5; /** * 定义一个计算a+b并返回结果 */ public int jiSuan() { int sum = a + b; return sum; } /** * 传入年龄和名字,返回拼接好的字符串 */ public String getNameAndAge(int age, String name) { return name + "今年" + age + "岁"; } public static void main(String[] args) { JiSuan jiSuan = new JiSuan(); System.out.println("a+b=" + jiSuan.jiSuan()); String str = jiSuan.getNameAndAge(18, "小明"); System.out.println(str); } }上面的代码中,有返回值的方法,最终是通过return把值传(返回)出来的。 下面再写一个复杂一点的对象,演示方法之间相互调用:
public class JiSuan { public int jiSuan(int a, int b) { int sum = a * b; return sum; } public String getNameAndAge(int age, String name, int a, int b) { return name + "今年" + age + "岁,他计算出了" + a + "乘以" + b + "的结果了:" + jiSuan(a, b); } public static void main(String[] args) { JiSuan jiSuan = new JiSuan(); String str = jiSuan.getNameAndAge(5, "小明", 123, 456); System.out.println(str); } }可以看出,同类中方法之间的调用,直接调用就行了,不需要new,在main方法中不可以直接调用getNameAndAge()、jiSuan(),其主要原因是main方法是一个静态关键字定义的方法(static),称为静态方法,相应的还有静态属性。静态方法可以直接调用静态方法或静态属性,非静态方法可以直接调用静态或非静态定义的属性和方法
public class JiSuan { static int a = 0; int b = 1; public static void a() { System.out.println("a()"); } public void b() { System.out.println("b()"); } /** * main方法本身就是一个静态方法 */ public static void main(String[] args) { //mian可以直接调用static定义的方法或属性 a(); JiSuan.a(); System.out.println(a); System.out.println(JiSuan.a); System.out.println("--------------------------------------------"); //mian不能直接调用b(),因为b是非静态 JiSuan js = new JiSuan(); js.b(); System.out.println(js.b); } }但千万不要为了不new,把所有的方法和属性全都定义为静态,觉得直接调用很方便,static不是这样用的!程序在启动的时候,会自动把static定义的属性和方法直接放进内存中,所以你在任何地方都可以直接调用,这种做法只会造成内存不必要的开销!只有定义为非静态,用对象的时候用new申请一个内存空间,才是正确的做法。通常在“工具类”中才会经常定义静态方法。
但千万不要写出如下代码,a()与b()相互调用,造成堆栈溢出。
public class JiSuan { public void a() { System.out.println("进入了a方法"); b(); } public void b() { System.out.println("进入了b方法"); a(); } public static void main(String[] args) { JiSuan jiSuan = new JiSuan(); jiSuan.a(); } }上面说到,new是申请了新的空间,我们可以用代码验证下:
public class JiSuan { int a = 0; int b = 1; public static void main(String[] args) { JiSuan js1 = new JiSuan(); JiSuan js2 = new JiSuan(); //比较js1和js2 System.out.println(js1 == js2); //修改js1的属性 js1.a = 999; //修改js1.a并不会影响js2.a System.out.println(js1.a); System.out.println(js2.a); } } // 执行结果: false 999 0最后打印了false。对象的比较不同于基本类型的比较,基本类型是值比较,只要值相等就是相等的,基本类型没有堆,只有栈,即没有空间(地址)。对象的比较是基于内存地址的比较,js1和js2,都是通过new申请的新的内存地址,所以它俩不相等,修改js1并不会影响到js2。 一个完整的java程序是需要很多类相互协作运行的,就如同一个人,包含眼、口、舌、心、肝、肺、手脚、血液,每一个人体器官都可以看作是一个java中的类(对象),它们有各自的功能,相互协作才能够展现一个活生生的人。所以说在java中,万物皆对象!
更多示例代码: Day11