3.1类和对象
1.面向对象的概念
1)面向对象
在一个结构体中定义窗口的大小,位置,颜色,背景等属性,对窗口操作的函数与窗口本身的定义没有任何关系,如HideWindow,MoveWindow,MinimizeWindow,这些函数都需要接受一个代表要被操作的窗口参数,是一种谓语与宾语的关系。
2)面向对象
定义窗口时,除了要指定在面向过程中规定的那些属性,如大小,位置,颜色,背景等外,还要指定该窗口可能具有的动作,如隐藏,移动,最小化等。这些函数被调用时,都是以某个窗口要隐藏,某个窗口要移动的语法格式来使用的,这是一种主语与谓语的关系。
3)面向对象的三大特征
---封装 (Encapsulation)
---继承 (Inheritance)
---多态 (Polymorphism)
4)面向对象的思想概述
面向对象的编程思想力图使计算机语言中对事物的描述与现实世界中该事物的本来面目尽可能的一致。
类(class)和对象(object)是面向对象方法的核心概念。类是对一类事物描述,是抽象的、概念上的定义;对象是实际存在的该类事物的每个个体,因此也称实例(instance)。
如果将对象比作汽车,那么类就是汽车的设计图纸。所以面向对象程序设计的重点是类的设计,而不是对象的设计。
5)类和对象举例
//定义一个类
public class Animal {
public int legs;
public void eat(){
System.out.println("eating");
}
public void move() {
System.out.println("moving");
}
public static void main(String[] args) {
//声明并创建一个Animal类的对象,将该对象命名为xb
Animal xb=new Animal();
//调用对象xb中的方法
xb.eat();
}
}
- legs是类的属性,也叫类成员变量。
- eat,move是方法,也叫类的成员函数。
6)声明类
语法格式:
[< 修饰符>] class < 类名>
{ [<属性声明>]
[<构造器声明>]
[<方法声明>]
}
说明:修饰符public:类可以被任意访问
类的正文要用{ }括起来
举例:
public class Person{
private int age ; //声明私有变量 age
public void showAge(int i) { //声明方法showAge
age = i;
}
}
7)声明属性
语法格式:
[<修饰符>] 类型 < 属性名> [=初值] ;
说明: 修饰符 private:该属性只能由该类的方法访问。
修饰符 public: 该属性可以被该类以外的方法访问。
类型:任何基本类型,如int、boolean或任何类。
属性有时也称为:数据成员(数据),成员变量(变量)
举例:
public class Person{
private int age; //声明private变量 age
public String name = “Lila”; //声明public变量 name
}
8)声明方法
语法格式:
<修饰符> <返回类型> <方法名>([< 参数表>]) {
[< 语句>]
}
说明:修饰符:public,private,protected等。
返回类型:return语句传递返回值。没有返回值:void。
方法有时也称为:成员函数(函数)
举例:
public class Person{
private int age;
public int getAge() { return age; } //声明方法getAge
public void setAge(int i) { //声明方法setAge
age = i; //将参数i的值赋给类的成员变量age
}
}
9)对象的创建和使用
- 使用 new+构造方法 创建一个新的对象
- 使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)
举例:
如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,且互不干扰。
举例:
10)类的访问机制
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量(有一个例外)。
- 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。
11)对象的产生
当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的都是引用类型,如上面的Person及前面讲过的数组。
12)对象的使用
创建对象:
class Person {
int age;
void shout() {
System.out.println(“oh,my god! I am “ + age);
}
}
创建新的对象之后,我们就可以使用“对象名.对象成员”的格式,来访问对象的成员
public class TestPerson {
public static void main(String[] args) {
Person p1=new Person();
Person p2=new Person();
p1.age=-30;
p1.shout();
p2.shout();
}
}
上面程序运行的内存布局如下图:
13)对象的生命周期
13)匿名对象
- 我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象,如:new Person().shout();
- 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
- 我们经常将匿名对象作为实参传递给一个函数调用。
3.2信息的封装和隐藏
1.使用者对类内部定义的属性(对象的成员变量)的直接操作会导致数据的错误、混乱或安全性问题。
应该将legs属性保护起来,防止乱用。
保护的方式:信息隐藏。
2.Java中通过将数据声明为私有的(private),再提供公开的(public)方法:getXXX和setXXX实现对该属性的操作,以实现下述目的:
1)隐藏一个类的实现细节
2)使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作
3)便于修改,增强代码的可维护性
举例:
public class Animal {
private int legs; //将属性legs定义为private,只能被Animal类内部访问
public void setLegs(int i) {
if(i!=0&&i!=2&&i!=4)
{
System.out.println("wrong number of legs");
return;
}
legs=i;
}
public int getLegs() {
return legs;
}
}
public class Zoo {
public static void main(String[] args) {
Animal xb=new Animal();
xb.setLegs(4);
xb.setLegs(-1000);
// xb.legs=-1000; //非法
System.out.println(xb.getLegs());
}
}
3.3构造方法
1.构造器的定义与作用
1)构造方法的特征
---它具有与类相同的名称
---它不含返回值
---注意:在构造方法里不含返回值的概念是不同于“void”的,在定义构造方法时加了“void”,结果这个方法就不再被自动调了。
2)构造方法的作用
当一个类的实例对象刚产生时,这个类的构造方法就会被自动调用,我们可以在这个方法中加入要完成初始化工作的代码。这就好像我们规定每个“人”一出生就必须先洗澡,我们就可以在“人”的构造方法中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们要“洗澡”了。
2.构造器(构造方法)
1)功能:创建类的实例时,初始化实例的一组指令。
2)语法格式:
< 修饰符> <类名>([< 参数表>]) {
[< 语句>]
}
举例:
public class Animal {
private int legs;
public Animal() {legs = 4; } //构造器
public void setLegs(int i) { legs = i; }
public int getLegs(){return legs;}
}
创建Animal类的实例:Animal a=new Animal(); //调用构造器,将legs初始化为4
注释:构造器的名称必须与类名相同。修饰符:public、private、protected
构造器不是方法,没有返回值(连void也不能写)
3.默认的构造方法
1)Java语言中,每个类都至少有一个构造方法;
2)如果类的定义者没有显式的的定义任何构造方法,系统将自动提供一个默认的构造方法:
---默认构造方法没有参数
---默认构造方法没有方法体
---默认的构造方法:Animal(){}
所以:不编写构造方法就能用new Xxx()创建类的实例。
3)Java类中,一旦类的定义者显式定义了一个或多个构造方法,系统将不再提供默认的构造方法;
4)构造器的主要作用:利用构造器参数初始化对象的属性。
4.Person p = new Person(“Tom”,18) 的内存状态变化过程分析
3.4方法的重载
1. 函数(方法)
返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,….) {
程序代码
return 返回值;
}
其中:
形式参数:在方法被调用时用于接收外部传入的数据的变量。
参数类型:就是该形式参数的数据类型。
返回值:方法在执行完毕后返还给调用它的程序的数据。
返回值类型:函数要返回的结果的数据类型。
实参:调用函数时实际传给函数形式参数的数据。
2.函数调用的过程分析
3.函数的重载
1)函数的重载就是在同一个类中允许同时存在一个以上的同名函数,只要它们的参数个数或类型不同即可。如:
public class Test {
public static void main(String [] args){
int isum;
double fsum;
isum=add(3,5);
isum=add(3,5,6);
fsum=add(3.2,6.5);
}
public static int add(int x,int y) { reutrn x+y; }
public static int add(int x,int y,int z) { return x+y+z; }
public static double add(double x,double y){ return x+y; } }
2)在同一个类中可以定义多个同名方法----方法名重载(overload)
public class PrintStream{
public void print(int i) {……}
public void print(float f) {……}
public void print(String s) {……}
}
3)重载方法的参数列表必须不同
4)重载方法的返回值类型可以相同,也可以不同
5)调用时根据方法的参数类型来区分。
print(3);print(1.2f);print(“hello!”);
4.构造方法重载
1)构造方法一般用来创建对象的同时初始化对象。如
class Person{
String name;
int age;
public Person(String n , int a){ name=n; age=a;}
}
2)构造方法重载使得对象的创建更加灵活,方便创建各种不同的对象。
构造方法重载举例:
public class Person{
public Person(String name, int age, Date d) {this(name,age);}
public Person(String name, int age) {…}
public Person(String name, Date d) {…}
public Person(){…}
}
3)构造方法重载,参数列表必须不同
4)构造方法重载举例:
public class Person {
private String name;
private int age;
private Date birthDate;
public Person(String name,int age,Date d){
this.name=name;
this.age=age;
this.birthDate=d;
}
public Person(String name,int age){
this(name,age,null);//this.name=name; this.age=age;this.birthDate=null;
}
public Person(String name, Date d) {
this(name, 30, d); //this.name=name;
this.age=30;this.birthDate=d;
}
public Person(String name) {
this(name, 30); //this.name=name; this.age=30;
}
}
3.5this关键字
1.this是什么?
1)如果func2方法被调用,一定是事先已经有了一个存在的对象,func2被作为那个对象的方法被使用。
2)在func2内部能引用别的对象,同样也能引用func2所属的那个对象。
3)在func2中,自己所属的那个对象的引用名称是什么呢?
4)this关键字在Java程序里的作用和它的词义很接近,它在函数内部就是这个函数所属的对象的引用变量。
2.this引用句柄的存放位置
每个成员方法内部,都有一个this引用变量,指向调用这个方法的对象,类中的成员方法与this之间的关系如图:
3.6函数的参数传递
1.函数的参数传递----基本数据类型的参数类型
2.函数的参数传递----引用数据类型的参数传递
3.函数的参数传递----引用参数传递的一个问题分析
3.7package语句/import语句
1.源文件布局
2.软件包
1)包帮助管理大型软件系统:将语义近似的类组织到包中。
2)包可以包含类和子包。
3.package语句
1)package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。它的格式为:
package <顶层包名>[.<子包名>]* ;
举例:pack\Test.java
package p1; //指定类Test属于包p1
public class Test{
public void display(){
System.out.println("in method display()");
}
}
2)包对应于文件系统的目录,package语句中,用‘ . ’来指明包(目录)的层次;
3)包通常用小写单词,类名首字母通常大写
4.import语句
1)为使用定义在不同包中的Java类,需用import语句来引入所需要的类。Import语句告诉编译器到哪里去寻找类。
2)语法格式:
import 包名[.子包名…]. <类名 |*>
3)应用举例:
import p1.Test; //import p1.*;表示引入p1包中的所有类
public class TestPackage{
public static void main(String args[]){
Test t = new Test(); //Test类在p1包中定义
t.display();
}
}
5.JDK中主要的包介绍
1)java.lang——包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。
2)java.net——包含执行与网络相关的操作的类。
3)java.io——包含能提供多种输入/输出功能的类。
4)java.util——包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。