面向对象的想法是模拟现实世界。java
把某样东西的状态数据和它的行为封装起来,从而达到易用、重用、隐藏内部状态的目的。安全
通常的变量,如: int a, double b 等,this
咱们定义它以后,它就是一个被动的数据,等特着其它代码来操做它。spa
而对象,不只含有数据,还有在数据上操做的方法,这样,数据自己就可能隐藏起来了。设计
外界只须要调用对象的方法来达到操控对象的目的。指针
这对外界而言,增长了易用性,由于这些专门针对该对象的方法,进行了精心设计,能够避免复杂度,避免一些误用。code
对对象而言,由于不直接操做它的数据,就达到了保护内部数据的目的,增长了安全性。对象
这样看来,相比于普通的变量,对象就比如是更智能化的数据。blog
对象是一种复合类型,或说复杂类型。get
由于对象中,可能会包含多个数据,以刻画对象当前所处的状态,又包含多个方法,描述对象能够作出的行为。
定义一个普通的数据, int a = 100; 就行了,这个类型很简单。
若是还须要第 2 个, int b = ... 也就搞定。
但若是直接定义一个对象,不管怎么设计语法,要给出多个数据,多个方法,都确定会冗长。
刚写好,而后老板又要再定义 10 个这样的对象,那就要悲剧了。
为避免重复与冗长,一个很天然的想法,是先定义一本身的新“类型”,地位至关于 int,
在这个类型中,把对象应该包含的数据、方法一次性描述清楚。
而后用这个新的类型再去定义对象,不就很清晰天然了吗?
这个新类型,就是咱们所说的----类
以下代码定义了平面上的"点",它包含 x, y 坐标,还有方法,好比:到原点的距离, distance。
1 class MyPoint 2 { 3 private double x; 4 private double y; 5 6 public double distance(){ 7 return Math.sqrt(x * x + y * y); 8 } 9 public void set(double x1, double y1){ 10 x = x1; 11 y = y1; 12 } 13 public double getx(){ 14 return x; 15 } 16 public double gety(){ 17 return y; 18 } 19 }
这段代码中对 MyPoint 的描述比较简陋,只有 2 个数据,3 个方法。
数据前边以 private修饰,表示外界不能直接存取这些数据,达到保护的目的。
但这样一来,总得给外界提供某种可以访问 x, y 的方式,不然这些数据就没什么价值了。
因此才有下面的 set, getx, gety 方法,它们负责对 x y 设定新值,以及读取 x y 的值。
下面看看怎样使用 MyPoint 这个新类型。
1 public class A0411 2 { 3 public static void main(String[] args){ 4 MyPoint p1 = new MyPoint(); 5 p1.set(10,20); 6 System.out.println(p1.distance()); 7 System.out.println(p1.getx()); 8 System.out.println(p1.gety()); 9 } 10 }
你可能会以为,这么绕着弯去操做 x, y 到底有什么好处呢,看起来还不如直接定义 x, y 更舒服呢。
的确,面向对象在效率上确实有些陨失,但换来了安全性。当软件变大,变复杂后,安全性、隔离性就很重要了。
对这么个简单状况,固然看不出什么优点来。
若是必定要看优点,这样想吧,好比咱们须要对 x y 的值进行限幅操做,x y 的值被限定在 -1000 到 1000 之间,
超出的,取范围内与设定最接近的值。
此时,咱们只须要对 set 方法进行修改就能够了,不须要更动其它代码,尤为是不须要惊动使用 MyPoint 的代码,这是个很大的优点,
由于在大型项目中,MyPoint 和使用 MyPoint 的代码极可能是两个不一样的人,甚至是两个不一样的团队写出来的。
public void set(double x1, double y1){ if(x1 < -1000) x1 = -1000; if(x1 > 1000) x1 = 1000; if(y1 < -1000) y1 = -1000; if(y1 > 1000) y1 = 1000; x = x1; y = y1; }
这也正是“封装”的含义。
外界只能调用方法,提供必要的参数,而无权干涉对象内部如何处理。
更理论化地说,外界只能向对象发出请求,至于对象如何响应这个请求,外界没法左右。
外界: 求求你,快把你的坐标改成 1200,900 吧。
对象: 才不呢! 1200超范围了,我就设为 1000,900 吧,爱咋地咋地。
不少时候,咱们但愿对象刚刚建立之后就持有正确的状态,而不是每次都很繁琐地去初始化它的状态。
好比,MyPoint,可能因为某种特殊的要求,每次对象默认的初始位置在(100,100)。
这能够由一个特殊的方法---构造方法来实现。
1 class MyPoint 2 { 3 private double x; 4 private double y; 5 6 public MyPoint(){ 7 x = 100; 8 y = 100; 9 } 10 11 public double distance(){ 12 return Math.sqrt(x * x + y * y); 13 } 14 public void set(double x1, double y1){ 15 if(x1 < -1000) x1 = -1000; 16 if(x1 > 1000) x1 = 1000; 17 if(y1 < -1000) y1 = -1000; 18 if(y1 > 1000) y1 = 1000; 19 x = x1; 20 y = y1; 21 } 22 public double getx(){ 23 return x; 24 } 25 public double gety(){ 26 return y; 27 } 28 } 29 30 public class A0416 31 { 32 public static void main(String[] args){ 33 MyPoint p1 = new MyPoint(); 34 System.out.println(p1.getx() + ", " + p1.gety()); 35 System.out.println(p1.distance()); 36 } 37 }
咱们能够注意到构造方法与普通方法的不一样之处。
首先是名字,构造方法与类同名。
而后是调用,构造方法被自动调用了。每次建立对象的时候都会自动地调用构造方法。
还有就是,在对象的整个生存期间,构造方法只会被调用一次。
固然,像普通方法同样,构造方法也能够有参数。这些参数在建立对象的时候传入。
1 class MyPoint 2 { 3 private double x; 4 private double y; 5 6 public MyPoint(){ 7 x = 100; 8 y = 100; 9 } 10 11 public MyPoint(int x1, int y1){ 12 this(); 13 set(x1,y1); 14 } 15 16 public double distance(){ 17 return Math.sqrt(x * x + y * y); 18 } 19 public void set(double x1, double y1){24 if(x>=-1000 && x<=1000) x = x1; 25 if(y>=-1000 && y<=1000) y = y1; 26 } 27 public double getx(){ 28 return x; 29 } 30 public double gety(){ 31 return y; 32 } 33 } 34 35 public class A0416 36 { 37 public static void main(String[] args){ 38 MyPoint p1 = new MyPoint(10,20); 39 System.out.println(p1.getx() + ", " + p1.gety()); 40 System.out.println(p1.distance()); 41 } 42 }
这里,新增长了一个含有参数的构造方法,与原来的没有参数的构造方法并存。
这种不一样的方法具备相同的名字的现象,叫“方法重载”。编译器根据你传入的参数的个数和类型能够很容易区分出你想调用的是哪一个方法,
实际上,在编译器看来,这两个方法与不一样名字的方法根本就没什么大不一样。
还有一个奇怪的语法, this(),这是去调用了不含参数的那个构造方法。
之因此这样作,是由于 set 方法改变了策略,它对不符合要求的参数,直接忽略了。
为了防止对象刚建立的时候传入了很差的参数,咱们先用默认的构造方法保个底,再去试着设置新的值。
那为何不写 MyPoint(); 而是搞这么个怪模样的 this() 呢?
个中苦衷外人不知。
原来系统对构造方法特殊对待,要保证它不会随便被调用,怎么保证?根本不让你写出 MyPoint() 这样的语句来,会直接编译错。
固然在一个构造方法中调用另外一个构造方法应该容许,毕竟这个构造方法自身也保证了不会被调用屡次,
这样一来就须要网开一面,须要弄出个新的语法来。
那为何选个 this,有什么典故不?
有,这是后面要讲的 this 引用,一言难尽,暂按下不表。
类与对象的关系就比如“图纸”与“房屋”的关系。
类描述了对象的构成,对象的行为。但毕竟它只是“描述”,若是不建立对象,还都只是构想。
类是建立对象所遵守的“施工图纸”。
由一个类,咱们能够建立任意多的对象。
最多见的建立对象的手段是 new 关键字。每次new 都建立一个对象。
建立对象后会在这个对象上,当即调用构造方法,来初始化对象的内部状态。
为了更精确地理解对象的行为,仍是要区分两个概念:对象和对它的引用。
在java中,咱们永远都没法直接接触到对象自己,咱们所持有的全部变量,都只多是对象的引用。
引用的本质就是c 语言中的指针概念。但它要更容易使用和管理,固然功能会弱一些。
c 语言中的对指针的许多操做,在 java 中是禁止的。好比: p++ 这样的常见操做。
MyPoint p = new MyPoint();
这句话中,p 实质是引用,并非对象自己。
咱们能够经过p 访问对象的方法,或访问它的数据(若是其数据定义为 public的话)
也能够把p 值赋值给另外一个变量。
MyPoint q = p;
注意,些时,Mypoint 对象只有一个,q 只是个指针,由于赋值,使得p, q 都指向了同一个对象。