怎么创建一个类?类是数据和方法的集合,创建类的语法很简单,如下:
class ClassName{
int data; //数据
int method(){ //方法
return data;
}
}
其中数据和方法可以包含多个。 创建类的难点在于给类命名,通常如果类的名字确定了,那么类所包含的数据和方法也基本确定了。怎么给类命名呢?首先类名需要是一个名词,其次这个名词可以在现实世界中找到与之对应的事物或者概念。如汽车、员工等等。确定了类名以后类所表示的事物的特征做为类的数据,事物具备的动作做为方法。如员工的年龄、升高、体重等信息可以做为 员工类的数据,员工的休息、工作、吃饭等动作可以做为员工类的方法。实际应用中只需要关注我们感兴趣的数据和方法并把他们放到类里面。
//员工类示例
class Employee{
//年龄
int age;
//体重
int weight;
//身高
int height;
//工作
void work(){
}
//吃饭
void eat(){
}
//睡觉
void sleep(){
}
}
为什么要使用类?
编程语言发展的早期,由于编程语言自身的限制只能使用面向过程的编程方法,如C语言编程。随着计算机的普及,计算机程序规模越来越大,越来越复杂,使用面向过程的编程方法来编写大型项目变得越发困难,维护和升级也变得越发困难。面向对象编程方法应运而生,面向对象编程方法具有封装、继承、多态三大特性,封装用来实现软件的模块化,继承用来实现软件的复用,多态用来实现抽象编程。
封装
封装是实现软件模块化的基础单元, 模块化可以降低耦合性,低耦合性有利于软件的修改和软件的理解。封装就是把一些数据和对数据的操作方法放到一个类里面,只暴露必要的信息给类使用者,把类的实现细节隐藏起来。在实际应用中类只应该暴露方法不应该暴露数据,数据就是实现细节,数据的可变动性是最大的,如果类暴露了数据,以后对数据改动的同时还会涉及到调用这些数据的类的改动,这样就使修改类的成本变高。
//服务类
class Service{
//服务编号,暴露给类使用者
int no;
int getNo(){
return no;
}
}
//客户类
class Client{
void doSomthing(){
Service srv = new Service();
int srvNo = srv.no;
}
}
上面的示例中Service类把no数据暴露给了外部的使用者Client,Client直接使用暴露出来的no数据。假设某天Service类的no需要通过计算生成且不再需要no变量,要满足这个需求就需要同时改动Service类和Client类。
//服务类
class Service{
int getNo(){
return 10;
}
}
//客户类
class Client{
void doSomthing(){
Service srv = new Service();
int srvNo = srv.getNo();
}
}
改动以后Client类通过调用getNo方法获取服务编号,不管以后Service类的服务编号实现怎么改动,Client类不需要再修改了。由于一开始的Service类没有做好封装,导致了后面修改Service类还会牵扯到Client类的修改。怎么做到好的封装性呢?从目前看来把类数据暴露给外部使用者是一种封装性差的表现,在设计类时如果遇到需要把数据暴露给外部的情况,最好想想有没有其它的办法来代替直接暴露数据给外部使用者,最简单的替代方法是创建一个方法,数据通过这个方法返回,隐藏数据暴露方法给外部使用者。
怎么控制隐藏实现细节暴露方法给类使用者呢?Java有一套外部访问权限机制,在了解这套访问权限机制之前还需要了解Java另一种模块化支持:包。包是类的集合,即一个包里面包含若干类。在实际开发中一个模块通常不是一个类就能实现的,而是需要很多类协同工作来实现模块,包可以把这些类封装在一起提供给外部使用。包可以编译成jar文件提供给使用者,类似Windows和Linux上的动态库。因为包可以生成jar文件所以它比类更易于复用。假设我有一个类要给别人使用,我需要把该类的.java文件发送给使用方,如果我有多个类的话就需要发送很多.java给使用方。使用包的话,只要把这些类放到一个包里面生成jar文件发送给使用方就可以了。包除了有模块化的特性外还有一个功能:解决类名冲突。在一个项目组中,组员A写了一个名为Service的类,组员B也写了一个名Service的类,组员C使用Service类时是使用A写的类还是B写的类?Java编译器不知道该使用哪个类,这就是类名冲突,编译会报错。如果组员A和组员B使用不同的包名,那么组员C在使用时可以显式的指定调用类的包名,这样编译器就知道该使用哪个类,这样就解决了类名冲突。
//组员A写的Service类,使用包名com.shaoshuidashi.a
package com.shaoshuidashi.a;
public class Service{
public void doSomething(){
System.out.println("a.Service");
}
}
//组员B写的Service类,使用包名com.shaoshuidashi.b;
package com.shaoshuidashi.b;
public class Service{
public void doSomething(){
System.out.println("b.Service");
}
}
//组员C使用组员A和组员B的Service类
package com.shaoshuidashi.test;
import com.shaoshuidashi.a.*;
import com.shaoshuidashi.b.*;
public class Test{
public static void main(String[] args) {
//显式的指明使用哪一个Service类
com.shaoshuidashi.a.Service srva = new com.shaoshuidashi.a.Service();
com.shaoshuidashi.b.Service srvb = new com.shaoshuidashi.b.Service();
srva.doSomething();
srvb.doSomething();
}
}
在上面的示例中,每个类的前面都有一个public关键字,方法前面也有一个public关键字,方法前面的public的作用在后面说明,先说类前面的public关键字作用, 类前面的public关键字 表示类的访问权限,即类在包外的访问权限,public关键字表示类可以在包外面访问,如果没有public则表示类只能在包里面访问。 类访问权限用来控制包的封装性,使用public暴露包的接口,非public隐藏实现细节。
package com.shaoshuidashi;
//car 类因为被public修饰,所以可以在包外面访问
public class Car{
}
//person类因为没有被public修饰,所以它只能在当前包内访问
class Person{
}
Java有public、protected、包访问权限(默认访问权限)、private四种外部访问权限修饰符来修饰类的数据和方法,‘‘外部’表示这些修饰符只是控制外部类访问类自身的数据和方法的权限,类可以随意访问自己的的数据和方法,无论他们是被什么修饰符修饰。public表示数据和方法是完全公开的,可以在任何地方访问。使用protected关键字修饰的数据和方法只能在子类里面访问。包访问权限是默认的访问权限,即数据和方法前面没有任何关键字修饰时属于默认访问权限,默认访问权限只能在包内部访问。使用private关键字修饰的数据和方法表示这些数据和方法只能在类内部使用。
package com.shaoshuidashi.hello;
//外部访问权限(内部可以随意访问)
public class Test{
public int data1; // 公开数据,可以在外部任何地方访问。
protected int data2; //保护数据,只能在子类里面访问。
int data3; //默认访问权限,只能在hello包里面访问。
private int data4; //只能在Test类里面访问。
//方法的访问权限同数据一样
}
类数据和方法的访问权限和类访问权限组合在一起后,访问会是什么样的呢?
package com.shaoshuidashi.access;
class Person{
//下面的方法能在包外面访问吗?
public void doSomething(){
}
}
doSomething方法能在包外面被访问吗?答案是不能,因为Person类只能在同一个包内被访问,也就是说Person类不能在包外访问,既然类无法访问那么doSomething方法自然就不能访问了。先确保对类有访问权限才能决定对类的数据和方法是否有访问权限。
Java类的创建、封装及访问权限
本文介绍了Java中类的创建,指出难点在于命名,应选现实对应名词。阐述了使用类的原因,是因面向过程编程在大型项目中存在局限。重点讲解了封装,它是模块化基础,可降低耦合。还介绍了Java的包和外部访问权限机制,包括类和数据方法的访问权限组合。
2148

被折叠的 条评论
为什么被折叠?



