封装(Encapsulation)是面向对象中的重要一环
将一个对象(Object)看成一个黑盒,从外部看不到内部是如何工作的,也就说是对外界隐藏的。在对象的外部只能通过调用类暴露出的方法来对其内部的数据进行操作。
利用访问修饰符来实现封装,Java中一共有3个访问修饰符: public、project和private。在public的修饰下的变量和方法在任何情况下都可以被访问,而在private修饰下的变量和方法只能在类的内部访问。如果是没有修饰符修饰的变量和方法,可以在同一个package内访问。
示例程序
public class Book { private double x,y,z; // 构造器 Constructor public Book(double x,double y,double z) { this.x = x; this.y = y; this.z = z; } // 返回体积 public double volume() { return x*y*z; } }
这是一个Book类,其中定义了private变量x,y,z。从外部无法直接访问x,y,z,而是通过构造器进行赋值,通过volume输出它们的乘积。
如果没有修饰符修饰的话,即default visibility,这样的变量和方法只能在同一个package内访问,大致如下所示:
C1在一个package p1下,C2为public类型,C2可以访问C1,而C3在另一个package p2下,因此不能访问C1,但可以访问C2。
在一般情况下,在类中用public修饰变量会破坏其封装性,但实际上用public修饰常量并不会破坏封装性,因为常量是不可修改的。
类须要提供一系列public修饰的方法来向外部提供了一系列服务(一系列功能,操作类中似有的数据),这些方法被称为service methods,仅仅为辅助service methods而创建的方法被称作support method,应该被private修饰。
有一种方法用于返回类中变量的值,称为accessor method,一般是getXXX的形式。有一种方法用于改变类中变量的值,一般是setXXX的形式。
示例代码
public class Book { private double x,y,z; public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void setZ(double z) { this.z = z; } public double getX() { return x; } public double getY() { return y; } public double getZ() { return z; } // 构造器 Constructor public Book(double x,double y,double z) { this.x = x; this.y = y; this.z = z; } public double volume() { return x*y*z; } }
可以将对象作为参数传递给其它对象,使用引用(reference)传参,经常使用的字符串比较便是如此: str1.compare(str2);
public class TestPassObject { public static void main(String [] args) { Circle myCircle = new Circle(5.0); printCircle(myCircle); } public static void printCircle(Circle c) { System.out.println("The area of the circle of radius " + c.getRadius() + " is " + c.getArea()); } }
如上述代码所示printCircle的参数是一个Circle对象,打印其面积。
原生数据类型是诸如byte, short, int, long, float, double, char and Boolean这样被预先定义好的数据类型,它们的大小是固定不变的。对这些变量的复制是创建另外一个副本,对副本的改变对原来的变量没有任何影响。
对象数据类型是用户自定义的,如arrays, strings, classes, interfaces...,对这种变量的副本的修改会反映到原来的变量上。
示例代码
输出
PRIMITIVE DATA TYPES Initally: x = 10, y = 10 After changing y to 30: x = 10, y = 30 **Only value of y is affected here because of Primitive Data Type REFERENCE DATA TYPES Initially Array c: [10, 20, 30, 40] Array d: [10, 20, 30, 40] Modifying the value at index 1 to 50 in array d After modification Array c: [10, 20, 30, 40] Array d: [10, 20, 30, 40] **Here value of c[1] is also affected because of Reference Data Type
可以看到y被x赋值,但是修改y的值不会改变x的值,而c和d都是int数组,修改d会影响到c,两者实际上指向同一内存。
因此原生数据类型作为参数时,是值传递,改变参数的值不会影响到原来的数据。对象数据类型总是引用传递,改变参数的值会影响到原来的数据。