Java程序设计-- 第4章 类和对象设计
4.1 面向对象基础
·抽象
class Car{
int color_number;
int door_number;
int speed;
void brake(){};
void speedUp() {…};
void slowDown() { … };
}
·封装
封装是一种将操作和操作所涉及的数据捆绑在一起,使其免受外界干扰和误用的机制。
·继承
继承是指一个新的类(子类)继承原有类(父类)的基本特征,并可增加新的特性。
由于父类的基本特征可被所有子类对象共享,因此通过集成可以提高类的复用性。
人
学生 工人 教师
小学生 中学生 小学教师 中学教师
·多态
多态类是指类中同一名称的行为(方法)可以有很多种不同的功能,或者相同的接口有多种实现方法。
4.2 类和对象初探
类是描述对象的“基本原型”,它封装了一类对象的属性和可以改变这些属性的方法,在面向对象的程序设计中,类是程序的基本单元。
用户必须先定义类,并生成该类的实例,然后才能通过该实例访问其成员变量和方法。
4.3 定义类
类通过关键词class进行标识,基本形式如下:
[类修饰符] class 类名 [extends 父类名][implements 接口名]
{
//类名,包括定义类的成员变量和成员方法
}
//“extends 父类名”为可选项,表示所定义的类继承自其它父类。
//“implements 接口名”为可选项,它表示我们定义的类需要通过实现某个接口完成
成员变量的定义格式为:
[修饰符] 类型 成员变量名列表;
// 成员变量的修饰符(如public, protected, private, final, static等)为可选项,主要起到对变量进行访问控制和限定的作用。
方法表示对象所具有的行为,定义格式如下:
[修饰符] 返回值类型 方法名 ([参数列表]){
方法体
}
//如果方法不返回任何值,它必须声明为void
特殊成员方法
·main方法:
public static void main(String args[])
//是整个Java应用程序的执行起点
·构造方法
-方法名必须与类名相同,且不能有任何返回值。
-如类Student的构造方法可定义为:
Student(int i_no,String i_name){...}
或者
Student(String s){...}
方法重载
方法重载是指:多个方法拥有相同的方法名,但方法的参数列表不同,即参数的数量、类型不完全相同。
注意:返回类型不能用来区别重载的方法。
Java方法只有返回值类型不同算不算重载?
答:
只有返回值类型不同的方法,不构成重载;
只有形参的名称不同,不构成方法重载
package code0403;
public class OverLoad {
int sum(int a, int b){//定义双操作数的sum方法
return a+b;
}
int sum(int a, int b, intc) {//重载的三操作数sum方法
return a+b+c;
}
public static void main(String[] args) {
OverLoad o = new OverLoad();
System.out.println(o.sum(1, 5)); //调用双操作数sum方法
System.out.println(o.sum(3, 5, 8);//调用三操作数sum方法
}
}
4.4 对象
实例化对象
类作为一种抽象的复合数据类型,必须先要实例化(即生成对象),然后才能使用。
实例化对象格式:
类名 对象名=new 类名([参数列表])
//关键字new为每个生成的对象分配一片内存区域,并返回该对象的一个引用。
//如实例化类Point的对象p1
Point p1=new Point ();
初始化对象
为所创建对象的成员变量赋初值
-可直接在定义成员变量的同时对其赋值。
-也可通过构造方法初始化对象。
通过构造方法初始化对象步骤:
(1)定义一个或多个构造方法,并在方法体中对成员变量赋初值。
(2)调用或执行相应的构造方法。
package code0404;
class Student {
int no;
String name;
Student(int l_no, Stringl_name) {//定义构造方法
this.no = l_no;
this.name = l_name;//对成员变量no,name初始化
}
public static void main(String args[]) {
Student s1 = new Student(1,"zhangShan");//传递参数l_no=1;l_name= zhangShan
Student s2 = new Student(2,"xiaoMing");//传递参数l_no=2;l_name= xiaoMing
System.out.println("name=" + s1.name +" no="+ s1.no);
System.out.println("name=" + s2.name +" no="+ s2.no);
}
}
构造方法使用注意:
(1)构造方法只能由new运算符调用。
(2)构造方法也可以被重载。
(3)调用重载的构造方法时,同样根据参数的类型、个数等决定调用哪个构造方法。
(4)构造方法不能被继承。
(5)如果用户没有定义任何构造方法,则系统会自动生成缺省的无参构造方法。
使用对象
包括对成员变量的引用和成员方法的调用,可通过点运算符(.)来实现,格式如下:
-对象名.成员变量名
-对象名.成员方法名(实参列表)
注意:
-方法调用形式有两种形式:传值调用 和 引用
-传值调用是单向的,将实参的值对应传递给形参
-引用对实参和形参的影响则是双向的
package code0404;
class Student{
int no;
String name;
Student(int l_no,String l_name){
this.no = l_no;
this.name = l_name;
}
public static void main(Srting args[]){
Student s1 = new Student(1,"ZhangShan");//传递参数
Student s2 = new Student(2,"XiaoMing");//传递参数
System.out.println("name="+s1.name+" no="+s1.no);
System.out.println("name="+s2.name+" no="+s2.no);
}
}
//程序执行结果
name=ZhangShan no=1
name=XiaoMing no=2
使用静态变量和静态方法
·定义静态变量和静态方法:在变量或方法名前加一个关键字static即可
class ABCD{
char data;
static int share_data;
static int getData();
}
class Demo{
ABCD a,b,c,d;
}
//object a:char data,static int share_data
//object b:char data,static int share_data
//object c:char data,static int share_data
//object d:char data,static int share_data
·实例成员为特定实例所有,只能通过对象名访问。
·类成员(也称静态成员)为类所有,不属于某一个对象,可通过类名或对象名访问。
·静态成员变量在生成该类的第一个对象时分配内存空间,该空间被类的所有实例共享。
package code0404
class StaticTest{
static int staInt = 4;
static double statDouble = 16.0;
int instInt;
double instDouble;
public static void staticMethod(){ // 输出静态变量的值
System.out.print1n("statInt=" + statInt + ";statdouble=" + statDouble);
}
public void instMethod(){//输出实例变量的值
System.out.println("instInt=" + instInt + "; instdouble=" + instDouble);
}
public StaticTest(int intArg, double doubleArg) {
instInt = intArg;
instDouble = doubleArg;
}
public static void changestatic(int newInt, double newDouble) {//改变静态变量的值
statInt = newInt;
statDouble = newDouble;
}
public static void main(String args[]) {
StaticTest instance1 = new StaticTest(1, 2.0);
StaticTest instance2 = new StaticTest(3, 4.0);
instance1.instMethod();//调用实例方法
instance2.instMethod();
StaticTest.staticMethod();//调用静态方法
StaticTest.staticMethod();
instance2.staticMethod();
instance1.changestatic(8, 8.0);//改变静态变量的值
instance2 .staticMethod();//再次输出静态变量的值
StaticTest.staticMethod();
}
}
//程序运行结果
instInt=1; instdouble=2.0 instInt=3; instdouble=4.0
statInt=4; statdouble=16.0 statInt=4; statdouble=16.0 statInt=4; statdouble=16.0
statInt=8; statdouble=8.0 statInt=8; statdouble=8.0
主方法与命令行参数
·一个Java应用程序(application)源文件可以由一个或多个类构成,但其中只能有一个主类。
·主类的特征之一是类名与Java文件名相同,且必须含有main()方法
public static void main(String args[]){…}
//main()方法可以通过数组args[]接收多个命令行参数,即args[0]存放第一个参数,args[1]存放第二个参数…
关于类的public修饰符
-1.如果文件中只有一个类,文件名必须与类名一致,有没有public修饰都可以;
-2.一个Java文件中最多只能有一个public类;
-3.如果文件中不止一个类,而且有public类,文件名必须与public类名一致;
-4.如果文件中不止一个类,而且没有public类,文件名可与任一类名一致。
package code0404;
public class MainTest{
public static void main(String args[]) {
int n = args.length; // 取得参数的个数
if(n= 0)
System.out.print1n(" no parament! ");
else{
System.out.println(" number of paraments:"+ n);
for(int i=0;i<n;i++)
System.out.print1n(" args[ "+i+" ] = "+args[i]);
}
}
}
如果执行该程序: java MainTest I Love China
则程序输出为:
number of paraments : 3
args[ 0 ] = I args[ 1 ] = Love args[ 2 ] = China
4.5 包
·一组相关的类和接口集合称为包。
·包将java类、接口等有机地组织成层次结构,这个层次结构与具体的文件系统的目录树结构层次一致。
·同一个包中,类不可以重名,但是不同的包中允许相同的类名出现。
包的定义格式为:
package [包名1.[包名2.[包名3]]]
“.”指明包的层次
package语句必须是程序的第一条非空格、非注释语句。
通过package语句,可将Java程序分层次地存放在不同的目录下,目录名称与包的名称相同。
package code0404;
public class MainTest{
public static void main(String args[]){
int n = args.length;//取得参数的个数
}
}
包的引入
若要用到某些包中的类或接口,一种方法是在程序的开始部分写出相应的引入(import)语句,指出要引入哪些包的哪些类。
import [包名1.[包名2.[包名3.]]] (类名|*)
//(*)表示引入该包中所有的类 如:
//例如
import java.util.*; //引入java.util包中的所有类
import java.applet.Applet; //引入java.applet包中的类Applet
Date d=new Date(); //使用java.util包中的Date类
另一种方法不用引入语句,直接在要使用的类前给出其所在包名。
java.util.Date d=new java.util.Date(); //使用Date类的另一种方式
无论采用哪种方法,目的都是要使得被使用(引入)的类在用户程序中可见。
4.6 类及成员修饰符
修饰符可以对类及其成员进行限定,以说明它们的性质、相互关系和适用范围。
public、protected、private、final、abstract、static
public
public可以同时修饰类和成员变量、成员方法
public修饰一个类名,如public class A{……},则表示该类可以被其它类所访问或引用。
public修饰成员变量、成员方法,表示该类的成员不仅可以被其他内部成员访问,而且可以被其它类直接访问。
class ABC{
public int pub_i=5;
public void show(){
System.out.println("pub_i "+pub_i);
}
}
protected
主要用于修饰类成员。
表示被修饰的成员除了可以被类自身访问外,还可以被该类的子类,与该类在同一个包中的其它类访问。
package code0406;
class Prot {
protected int n = 3; //被保护变量
protected void show_n() { //被保护方法
System.out.println("n="+ n);
}
}
package code0406;
class ProtTest extends Prot { //生成子类
public static void main(String args[]) {
ProtTest abs = new ProtTest();
abs.show_n0; //访问父类的被保护成员.
abs.n = 10; //访问父类的被保护成员
abs.show_n();
}
}
private
private主要用于修饰类成员。
表示被修饰的类成员只能被类自身访问,任何其它类都无权修改或引用。
package code0406;
public class MyDate {
private int day, month, year; //定义私有变量
public void tomorow() {
day= day+ 1; //本类可以引用私有变量
}
public void setDay(int d) {day= d:}
}
package code0406;
public class MyDateUser{
public static void main(String args[]){
MyDate mydate = new MyDate 0; .
mydate.day = 21; //错误
System.out.println("day="+mydate.day); //错误
mydate.setDay(21); //正确
}
}
default
如果类成员前没有使用public,protected,private中的任何一个修饰符,我们称它使用了缺省(default)修饰符。
这时,只有该类本身以及与该类在同一个包中的其它类才可以直接访问这些缺省成员。
同一个类 | 同一个包 | 不同包中的子类 | 不同包中的非子类 | |
---|---|---|---|---|
private | ★ | |||
default | ★ | ★ | ||
protected | ★ | ★ | ★ | |
public | ★ | ★ | ★ | ★ |
final
final可用于修饰类、成员变量、成员方法。
final修饰的类不能再派生子类;
用final声明的方法不能再被重写;
用final声明的成员变量(即常量)初始化后,不能再被重新赋值或修改。