Java核心技术--第四章(2018/10/8完结)

第四章 对象和类

面向对象程序设计 OOP

面向对象的程序是由对象组成,每个对象包含对用户公开特定功能部分隐藏实现部分
对象 可以来自标准库 可以自定义
算法 + 数据结构 = 程序 要先确定如何操作数据,再决定如何组织数据(易于操作数据) 不是OOP
OOP 先考虑数据 再考虑操作数据的算法
适用解决规模较大的问题

类 类的实例化—对象

类 实例域(数据) + (操作数据的)方法
封装 绝不让类中的方法直接访问其他类的实例域 “黑盒“特征-----提高了重用性和可靠性
也就是在同样的处理方法下,只需要改变存储数据的方式就可以,不需要发生大的变化

类 可扩展 扩展后的新类包含原来类的全部属性方法 只需再添加其他新方法和数据域就可以(原来类有的不必添加) ------------------------------- 继承(第五章)

对象

属性 + 方法
行为----------该对象可以做的动作、行为(通过方法调用)
状态----------“已送货“,”已付款“
标识----------标识永远不同

设计类: 类-----分析问题时,找名词即为类 找动词即为方法
例:订单处理系统中,有名词:项目、订单等------类 ,有动词:添加、取消、发送等------方法

类之间的关系

依赖 类A的方法操纵类S的对象 A依赖于S 应尽可能减少依赖(降低耦合度)
聚合 类A的对象包含类S的对象
继承 第五章 类A扩展类B 类A不但包含从类B继承的方法 还可以有一些新的方法、属性

可以用UML绘制关于类之间关系的类图

使用现有类

以Date类为例,学习一下 ,使用现有类,如何构造对象,如何调用类的方法

构造对象------>指定初始状态------>对对象施加方法------->使用对象

Date birthday = new Date();      //Date对象       构造+初始化
String s = new Date().toString();         //String对象

Date deadline;     //构造      构造的,未进行初始化的对象不可以进行操作 .toString()等等
//初始化变量的两种方式:
deadline = new Date();			//用新构造的对象初始化变量
deadline = birthday;            	//引用一个已存在的变量
deadline = null;                       //将对象变量设置为null,表明该对象变量没有引用任何对象
					//deadline.toString() 会运行出错 
					// 因为变量不会自动初始化为null,需调用new或将它们设置为nul进行初始化

:任何对象变量的值都是对存储在另一地方对象的引用 对象变量也是,只是引用一个对象

Java类库中的GregorianCalendar类

有很多方法可参见API使用

Java类库包含:Date类(表示时间点的),GregorianCalendar类(日历表示法)
GregorianCalendar类扩展了一个通用的Calendar类(描述了日历的一般属性)
Date类中before和after方法分别表示一个时间点是否早于或晚于另一个时间点。today.before(birthday)或today.after(birthday)
Date类中的getDay、getMonth以及getYear等方法,不推荐使用

构造:GregorianCalendar gc =
new GregorianCalendar() 新对象
new GregorianCalendar(1999,11,31) 年月日特定日期午夜的日历对象
其中月份从0开始,11为12月;也可用常量Calendar.December
new GregorianCalendar(1999,Calendar.December,31,23,59,59)

更改器方法与访问器方法

日历:提供某个时间点的年、月、日等信息
查询时间点(日历)的信息-----------GregorianCalendar.get()

GregorianCalendar now = new GregorianCalendar();
int month = now.get(Calendar.MONTH);
int weekday = now.get(Calendar.DAY_OF_WEEK);      //其他可参见API

设置时间点信息----------------GregorianCalendar.set()

deadline.set(Calendar.YEAR,2001);		//年
deadline.set(Calendar.MONTH,Calendar.APRIL);		//月
deadline.set(Calemdar.DAY_OF_MONTH,15);		//日
deadline.set(2001,Calendar.APRIL,15);		//年、月、日

//为给定的日期对象添加天数、星期数、月份等等
deadline.add(Calendar.MONTH,3);    //若传递的是负数,日期就向后移

get方法仅查看应返回对象的状态 --------------访问器方法(仅访问)
set、add方法可对对象的状态进行修改 -----------变更器方法(修改了内容)

Date time = calendar.getTime();        //获取日历对象所表示的时间点
calendar.set(Time);        //设置日历对象所表示的时间点

这些方法是在进行GregorianCalendar和Date类之间的转换。

GregorianCalendar calendar = new GregorianCalendar();
GregorianCalendar calendar1 = new GregorianCalendar();
Date hireDay = calendar1.getTime();         //将GregorianCalendar转换为Date
calendar.setTime(hireDay);	//设置calendar中的时间点为Date类型的hireDay
int year = calendar.get(Calendar.YEAR);   //获取calendar中的年份  赋值给year

EmployeeTest.java

import java.util.*;
public class EmployeeTest{ 
	public static void main(String[] args){  
	//构造 Employee类的数组 
	 Employee[] staff =  new Emploee[3];  
	 //对employee类的对象赋值  
	 staff[0] = new Employee("Carl",75000,1987,12,15);  
	 staff[1] = new Employee("Harry",50000,1989,10,1);  
	 staff[2] = new Employee("Tony",40000,1990,3,15); 
	  //用raiseSalary方法提高每个雇员的薪水5%  
	  for(Employee e : staff)   
	  	e.raiseSalary(S);  
	  //打印每个雇员的信息  
	  for(Employee e: satff)   
	  	System.out.println("name = "+e.getName() +",salray = "+e.getSalary()+",hireDay = "+e.gatHireDay()); 
	  	}
	  }
	  class Employee{          
	  //构造Employee类 
	  public Employee(String n, double s; int year, int month, int day){//构造器  
	  name = n;  salary = s;  
	  GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);  	  hireDay = calendar.getTime(); 
	  } 
	  //4个方法   public意味着任何类的任何方法都可以调用这些方法 
	  public String getName(){  
	  	return name; 
	  } 
	  public double getSalary(){  
	  	return salary; 
	  } 
	  public Date getHireDay(){  
	  	return hiraDay; 
	  } 
	  public void raiseSalary(doble byPercent){  
	  	double raise = salary * byPercent/100;  
	  	salary += raise;  
	  } 
	  private String name; private double salary; private Date hireDay;}

构造器

public Employee(String n, double s; int year, int month, int day){//构造器
name = n;
salary = s;
GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);
hireDay = calendar.getTime();
}

  • 构造器与类同名
  • 每个类可以有一个以上的构造器
  • 构造器可以有0个、1个或1个以上的参数
  • 构造器没有返回值
  • 构造器总是伴随着new操作一起调用

隐式参数与显式参数

public void raiseSalary(doble byPercent){
double raise = salary * byPercent/100;
salary += raise;
}
salary为隐式参数 byPercent为显式参数
在每个方法中,关键字this表示隐式参数。因此上面事例可变为:
public void raiseSalary(doble byPercent){
double raise = this.salary * byPercent/100;
this. salary += raise;
}

封装优点

public String getName(){
return name;
}
public double getSalary(){
return salary; }
public Date getHireDay(){
return hiraDay;
}
只返回实例域值,称为域访问器
获取或设置实例域的值:

  • 一个私有的数据域 private
  • 一个公有的域访问器方法 getXXX
  • 一个公有的与更改器方法 setXXX

一个方法可以访问所属类的所有对象的私有数据

私有方法

public -----> private 数据一般都为私有的 方法可以公有,也可以私有

Final实例域

final 基本数据类型域 或 不可变类的域
private final Date hiredate;
意味着存储在hiredate变量中的对象引用在对象构造之后不能被改变。
任何方法都可以对hiredate引用的对象调用setTime更改器。

静态域与静态方法

static

静态域

每个类中只有一个这样的域:假定给每个雇员赋予惟一的标识码

class Employee{	
	......
	private int id;			//实力域id
	private static int nextInt = 1;	//静态域nextId
}

也就是:每个雇员都有自己的id域,但这个类的所有实例将共享一个nextId域。即使没有一个雇员对象,静态域nextId也存在。它属于类,不属于任何独立的对象。

静态常量

Math类中定义一个静态常量:

public class Math{
	......	
	public static final double PI =3.14159265358979323845;     //静态常量PI
	......
}

使用Math.PI获得该常量

静态方法

静态方法不能对对象进行操作。即无隐式参数(无this)。
虽无法访问实力域,但是可访问自身类的静态域。

例:

public static int getnextId(){     //可省略static  因为本身就是访问静态域
	return nextId;    //  访问静态域
}

需通过Employee类对象调用该方法 Employee.getNextId()

Factory方法-----NumberFormat类

产生不同风格的格式对象

NumberFormat currentFormatter =  NumberFormat.getCurrencyInstance();
NumberFormat percentFormatter = NumberFormat.getPercentInstance();
double x = 0.1;
System.out.println(currencyFormatter.format(x));     //打印50.10
System.out,println(percentFormatter.format(x));       //打印  10%

不用构造器而用NumberFormat类的原因:
1、无法命名构造器 实例之间希望采用不同名字达不到要求
2、构造器无法改变所构造的对象类型 Factory方法返回一个NumberFormat子类–DecimalFormat类对象

Main方法 -------静态方法

启动程序时还没有任何一个对象,静态的main方法将执行并创建程序所需要的对象

在一个小的单元中可进行单元测试: 运行Employee
整个项目的测试:运行EmployeeTest

import java.util.*;
public class EmployeeTest{ 
 public static void main(String[] args){  
 
 //构造 Employee类的数组 
  Employee[] staff =  new Emploee[3]; 
   
  //对employee类的对象赋值  
  staff[0] = new Employee("Carl",75000,1987,12,15);  
  staff[1] = new Employee("Harry",50000,1989,10,1);  
  staff[2] = new Employee("Tony",40000,1990,3,15); 
  
   //用raiseSalary方法提高每个雇员的薪水5%  
   for(Employee e : staff)   
    e.raiseSalary(S);  
    
   //打印每个雇员的信息  
   for(Employee e: satff)   
    System.out.println("name = "+e.getName() +",salray = "+e.getSalary()+",hireDay = "+e.gatHireDay()); 
    }
   }


   class Employee{         
   
   //构造Employee类 
   public Employee(String n, double s; int year, int month, int day){//构造器  
   
   name = n;  salary = s;  
   GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);     
   hireDay = calendar.getTime(); 
   } 
   
   //4个方法   public意味着任何类的任何方法都可以调用这些方法 
   public String getName(){  
    return name; 
   } 
   public double getSalary(){  
    return salary; 
   } 
   public Date getHireDay(){  
    return hiraDay; 
   } 
   public void raiseSalary(doble byPercent){  
    double raise = salary * byPercent/100;  
    salary += raise;  
   } 
   //单元测试  main
   public static void main(){
	  Employee e = new Employee("Harry",50000);
	  System.out.println(e.getName()+" "+e.getSalary());
  }
	
   private String name; 
   private double salary; 
   private Date hireDay;
   }

方法参数

参数传递:1、传递的是值(值调用)、布尔类型(true、false)
2、传递的是变量地址(引用调用)

传递的值不能改变其内容。 只是将值传递过来。

特别讲一下 交换两个雇员对象的方法

public static void swap(Employee x,Employee y){
	Employee temp = x;
	x = y;
	y = temp;
}



//main方法:
public static void main(String[] args){
	Employee a = new Employee("Alice",...);
	Employee b = new Employee("Bob",...);
	swap(a,b);//最终白费力气,什么都没变 a、b仍用之前的
}

原因在于Java程序设计语言对对象采用的不是引用调用,而是值传递
该方法只是改变了x和y(a、b的拷贝),没有改变变量a,b

在Java程序设计语言中,方法参数的使用情况:

  • 一个方法不能修改一个基本数据类型的参数(即数值型和布尔型)
  • 一个方法不能改变一个对象参数的状态
  • 一个方法不能实现让对象参数引用一个新的对象

ParamTest.java

对象构造

多种编写构造器的方式:

重载

例如:GregorianCalendar有多个构造器:可以用

GregorianCalendar today = new GregorianCalendar();
//或者
GregorianCalendar deadline = new GregorianCalendar(2099.Calendar,DECEMBER,31);

这种叫做重载 :有相同的名字,但是参数不同(参数类型、个数不同,且都要指明) 指出方法名以及参数类型------方法的签名
编译器根据所提供的构造方法找到与其对应的;若编译器找不到匹配的或者找到多个,就会产生编译时错误(该过程为重载解析)

注意:返回类型不是方法签名的一部分(不能有两个名字相同、参数类型也相同却返回不同类型值的方法)

默认域初始化

若构造其中没有显式地进行赋值,那么会自动度为默认值:数值=0,布尔值=false,对象引用=null
不明确地对域进行初始化,会影响代码可读性

默认构造器

没有参数的构造器
例:

public employee(){
	name ="";
	salary =0;
	hireDay = new Date();
}

若在类中没有提供任何一个构造器,则系统会自动提供一个默认构造器,所有实力域的值均为默认值
注意:若类中提供了一个及以上构造器,但是没有编写默认的构造器(也就是无参的构造器),而在构造对象时还想使用默认的,则不合法,会产生错误

若编程人员希望所有域被赋值为默认值 则可使用

public ClassName(){
}

显示域初始化

在调用构造器时,应到确保不管怎样调用,每个实例域都可以被设置为一个有意义地初值。
赋初值:初始值是常量的情况

class Employee{
	......
	private String name ="Lisa";
	......
}

初始值可以不是常量。调用方法对域进行初始化

class Employee{
	 ......
	static int assignId(){
		int r = nextId;
		nextId++;
		return r;
	}
 	......
 	private int id = assignId();   //每个雇员有一个id域,都会调用assignId()
}

参数名

参数命名时技巧:
1、在参数前加上前缀或者后缀之类的 , _xxx,(固定字母)xsalary,msalary
2、参数变量用同样的名字将实例域屏蔽起来
例:

public Employee(String name,double salary){
	this.name = name;                //this是隐式参数
	this.salary =salary;
}

调用另一个构造器

this除了是隐式参数以外,还可以调用同一个类的另一个构造器
例:

public Employee(double s){
	this("Employee #"+nextId,s);   //Employee()调用Employee(String,double)
	nextId++;
}

当调用new Employee(60000)时,Employee(double)构造器将调用Employee(String,double)构造器。

初始化块

class Employee{
	public Employee(){
	}
	......
	private static int nextId;
	private int id;
	private String name;
	private double salary;
	......
	//初始化块
	{
		id = nextId;
		nextId++;
	}
}

先运行初始化块,然后再运行构造器的主体部分
调用构造器的具体处理步骤:
1、所有数据域被初始化为默认值(0、false或null)
2、按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块
3、若构造器第一行调用了第二个构造器,则执行第二个构造器的主体
4、执行这个构造器的主体

对类的静态域进行初始化的代码稍复杂,可使用静态的初始化块:

static{
	Random generator = new Random();
	nextId = generator.nextInt(10000);
}

对象析构与finalize方法

析构器最常见操作:回收分配给对象的存储空间
由于Java有自动的垃圾回收器,不需要人工回收内存,所以Java不支持析构器

若特殊情况(资源不再需要,将其回收和再利用),可为类添加finalize方法—将在垃圾回收器清除对象之前调用。实际应用中,因很难知道什么时候才能调用,故而不要用这个方法回收短缺资源 不鼓励使用

若某资源需使用完毕后立即关闭,则需要人工应用类似dispose或close的方法来完成相应的清理操作。
注意:若该类使用了这样的方法,对象不再使用时一定要调用它

包 用于存放类 确保类名的唯一性 每个包之间独立
在包中定位类 是 编译器的工作。
优点:便于组织代码,当与被人代码合并时方便分开管理
Java类库,包括java.lang、java.util和java.net等 具有层次结构
所有标准的Java包都处在java和javax包层次中
一个类可使用所属包中的所有类与其他包中的公有类

类导入-------访问另一个包中的公有类

方法一: 在每个类名之前添加完整的包名

java.util.Date today = new java.util.Date();

方法二: 使用import语句
import语句 : 一种引用(含有类的简明描述) 可导入一个特定的类或者整个包 位于源文件的顶部(但位于package语句的后面)

import java.util.*;     //导入java.util包中的所有类        
import java.util.Date;       //导入一个包的特定类

指出特定的类方便代码理解,知道加在了哪些类

Eclipse中,菜单选项Source -> Organize Imports 自动扩展指定的导入列表

只能使用星号* 导入一个包
不能使用 import java.* 或者 import java.*.*导入以java为前缀的所有包

大多情况下,只导入所需要的包即可。但在发生命名冲突的时候,必须要注意包的名字
例:java.util和Java.sql包中都有日期Date类

import java.util.*;
import java.sql.*;
Date today;           //编译错误     编译器无法确定程序使用的是哪一个Date类  

解决办法: 增加一个特定的import语句

import java.util.Date;

若是这两个Date类都要使用,则在每个类名的前面加上完整的包名

java.util.Date deadline = new java.util.Date();
java.sql.Date today = new java.sql.Date(.......);

静态导入

导入静态方法和静态域 添加在源文件的顶部

import static java.lang.System.*;  
//System类的静态方法和静态域
out.print("Goodbye!!");                //System.out.print
exit(0);                                        //System.exit

导入特定的方法或域

import static java.lang.System.out;  

静态导入的实际应用:

  • 算术函数 Math类 使用算术函数
sqrt(pow(x,2)+pow(y,2))                        //清晰一些
Math.sqrt(Math.pow(x,2)+Math.pow(域,2)); 
  • 笨重的变量 大量带有冗长名字的常量
if(d.get(DAY_OF_WEEK) == WONDAY)		//容易一些
if(d.get(Calendar,DAY_OF_WEEK) == Calendar.MONDAY)

将类放入包中

包名需要放在源文件的开头 若放在默认包中 则无需声明
com.horstmann.corejava包中所有原文件放在子目录com/horatmann/corejava中。编译器将类文件也放在相同的目录结构中。

Employee.java与Employee.class放在com.horstmann.corejava包中
PayrollApp.java与PayrollApp.class放在com.mycompany包中
两个在不同的包中
从基目录编译和运行类,包含com目录:
javac com/mycompany/PayrollApp.java
编译器对文件操作
java com.mycompany.PayrollApp
Java解释器加载类

包作用域

在默认情况下,包不是一个封闭的实体
任何人都可以向包中添加更多的类 在使用时要多加注意 正确使用

类路径CLASSPATH 告诉编译器package的位置

类的路径必须与包名匹配。
另外:类文件也可以存储在jar文件中。一jar文件中可包含多个压缩形式的类文件和子目录(节省空间有改善性能)
有关于创建jar文件的详细内容见第十章。。。。

为使类可被多个程序共享,要做到:

  1. 把类放到一个目录中 树状结构
  2. 将jar文件放在一个目录中
  3. 设置类路径 ----- 所有包含类文件的路径的集合

CLASSPATH环境变量 ---------告诉编译器package的位置
PATH环境变量 ---------指定命令搜索路径
例: javac编译程序时,到PATH所指路径下查找能否找到相应命令程序
JAVA_HOME环境变量 -------指向jdk安装目录
例:Eclipse/NetBeans/Tomcat等软件就是通过搜索JAVA_HOME变量来找到并使用安装好的jdk

详细设置 这里不再叙述

文档注释

/** 开始
这种注释的方式将代码和注释保存在同一文件中,在代码修改时,重新运行javadoc就可轻而易举保持二者的一致性

注释的插入

javadoc实用程序(utility)在下面特性中抽取信息:

  • 公有类与接口(接口见第六章)
  • 公有的和受保护的方法(受保护特性见第五章)
  • 公有的和受保护的域

注释应当放在所描述特性的前面。以/**开始,*/结束

/**…*/中添加 @+自由格式文本 概要性语句
(自由格式文本可使用HTML修饰符,
例:强调<em>...</em>
设置“打印机”字体<code>...</code>
着重强调<strong>...</strong>
图像<img>...</img>
等) 切勿使用<h1><hr>,会与文档的格式产生冲突。

javadoc自动抽取这些概要性语句形成概要页。

类注释 ----- 放在import语句之后,类定义之前

/**
*
*
*/
public class Employee{


}

或者

/**

                   //没必要在每一行的开始都用星号*
*/
public class Employee{

}

但是: 大部分IDE提供了自动添加星号,并当注释行改变时自动重新排列这些星号的功能

方法注释-------放在所描述方法前

除通用标记外,还可使用:

  • @param variable description
    对当前方法的参数部分添加一个条目,可占据多行,可使用HTML标记
    一个方法的所有@param标记必须放在一起
  • @return description
    对当前方法添加返回部分,可跨越多行,可使用HTML标记
  • @throws class description
    添加一个注释,表示该方法可能抛出异常(异常详细内容见十一章)

域注释

只需对公有域(通常指静态常量)建立文档
例:

/**
 *  The "Hearts" cars suit
 * /
public static final int HEARTS = 1;

通用注释

可用在类文档的注释中:

  • @author name
    产生一个作者条目。可使用多个@author标记,每个@author标记对应一个作者
  • @version text
    产生一个版本条目。text可以是对当前版本的任何描述

可用于所有文档的注释中

  • @since text产生一个始于条目。text可以是对引入特性的版本描述
    例:@since version 1.7.1
  • @deprecated text
    对类、方法或变量添加一个不再使用的注释。text中给出取代意见
    例:@deprecated Use <code>setVisible(true)</code> instead

超级链接:连接到javadoc文档的相关部分或外部文档

  • @see reference------------可用于类中,也可用于方法中
    例1:
    @see com.horstmann.corejava.Employee#raiseSalary(double)
    提供类、方法或变量的名字。 可省略包名、类名,链接将定位于当前包、当前类。
    注意: 一定要使用#,不要使用. javadoc实用程序容易混淆

    例2:
    @see <a href="www.horstmann.com/corejava.html"> The core Java home page</a>
    可超链接到任何URL
    也可简写为
    @see “Core Java 2 volume 2”

可为一个特性添加多个@see标记,但必须将其放到一起

  • 可在注释中任何位置放指向其他类或方法的超级链接,以及插入个人专用标记
    例:{@link package.class#feature label}
    特性描述规则与@see一样

包与概述注释

包注释: 在每个包目录中添加一个单独的文件

  • 方法一
    给一个以package.html命名的HTML文件。在标记<body><body>之间的所有文本都会被抽取出来
  • 方法二
    给一个以package-info.java命名的Java文件,该文件必须包含一个/*/界定的javadoc注释,跟随在一个包语句之后。不应该包含更多代码或注释。
  • 方法三
    为所有的源文件提供一个概述性的注释,放在一名为overview.html文件中,文件位于包含所有原文件的父目录中。<body></body>之间的文本将被抽出来。用户从导航栏中选择“overview”时,会显示注释。

注释的抽取

HTML文件存放于目录docDirectory下

  1. 切换到想要生成文档的源文件目录
  2. 若是一个包,运行javadoc -d docDirectory nameOfPackage
    多个包生成文档,运行。。。。。。。。。。nameOfPackage1 nameOfPackage2 …
    文件在默认包,运行javadoc -d docDirectory *.java

不可省略-d docDirectory,否则HTML文件会被提取到当前目录下,会造成混乱

可使用多种命令行对javadoc程序进行调整:

  • -author 和-version在包含@author和@version的文档中调整
  • -link :为标准类添加超链接
    例:javadoc -link http://java.sun.com/javase/6/docs/api*.java
    所有标准类库会自动连接到Sun网站的文档
  • -linksource :每个源文件被转换为HTML,无颜色编码,有行编号,且每个类和方法都转变为指向源代码的超链接

类设计技巧

  1. 一定将数据设计为私有
    不要破坏封装性
    可编写访问器方法getXXX或者更改其方法setXXX,以保持实例域的私有性

  2. 一定要对数据初始化
    Java不对局部变量进行初始化,但对对象的实例域进行初始化。
    不要依赖于系统提供的默认值,程序员应设置默认值或在所有构造器中设置默认值

  3. 不要在类中使用过多的基本数据类型
    用其他类代替多个相关的基本数据类型的使用。

  4. 不是所有的域都需要独立的域访问器和域更改器

  5. 使用标准格式进行类的定义

    类内容顺序:

    1 公有访问特性部分
    2 包作用域访问特性部分
    3 私有访问特性部分

    每一部分的顺序:

    1 实例方法
    2 静态方法
    3 实例域
    4 静态域

每一部分要保持一致 顺序可调换(域 和 方法之间可调换)

  1. 将职责过多的类进行分解
    ”复杂的“分解为多个”简单的“ 。不要走极端,太简单,太复杂

一个类实现两个独立的概念:一副牌(含有shuffle方法和draw方法)+一张牌(含有查看花色和面值的方法)Card类-----表示单张牌

public class CardDeck{
	public CardDeck(){}
	public void shuffle(){}
	public Card getTop(){}
	public void draw(){}

private Cad[] cards;  
 //可使用查看花色、面值(Card类中)的方法  以及在本类中的方法
}
public class Card{    //查看花色、面值
	public Card(int aValue,int aSuit){}
	public int getVaule(){}
	public int getSuit(){}
	
	private int value;
	private int suit;
}
  1. 类名和方法名要能体现出其职责
    与变量应该有一个能反映其含义的名字一样,类也应如此。
    养成良好的命名习惯 :名词Order 、形容词+名词RushOrder、动名词+名词BillingAddress 等等
    访问器方法 getXXX ,更改器方法 setXXX

2018/10/8 第四章结束。。。。

猜你喜欢

转载自blog.csdn.net/weixin_43137176/article/details/82790483