一.类与对象
1.对象
在日常生活中对象就是我们认识世界的基本单元,它可以是人,也可以是物,还可以是一件事
整个世界就是由形形色色的对象构成的
对象是现实世界中的一个实体,特征是:对象的标示(名称)唯一 ;对象的状态(属性,数据区);对象的行为(方法,功能)
①对象的生成,使用和清除
构造函数(Constructor)
构造方法(constructor)是一类特殊的成员方法
从功能上讲,它使用new关键字用来对新创建的对象进行初始化
从形式来讲,它的特点:与类同名;没有任何返回值;在语法结构上与一般的方法相同
构造函数实例化对象的格式:类名 对象名=new 构造函数(实际参数)
New关键字的作用
为对象分配内存空间
引起对象构造方法的调用
为对象返回一个引用
访问对象的成员变量和成员方法
访问对象的成员变量和调用对象的成员方法通过圆点操作符( . )实现:
对象名 . 变量名
对象名 . 方法名
②对象的声明和初始化
用这个类去定义一个对象MyDesk :Desk MyDesk;
用new为其开辟存储空间:MyDesk = new Desk();
定义类对象并为其开辟空间:Desk MyDesk = new Desk()
无参构造函数创建对象时,成员变量的值被赋予了数据类型的隐含初值
2.类
①总结
在软件中,类就是一个模板,它定义了一类事物的状态和行为
类是对现实世界的抽象,因此类是一种抽象的复合数据类型
需求中提取类,即抽象的过程
创建一个类就是创建一个新的数据类型,实例化一个类,就得到一个对象
类的构成有两部分,分别是成员变量和成员方法
类的成员变量可以是基本类型或数组,也可以是类的对象
类的成员方法用于处理该类的数据,是用户与对象之间或对象之间的接口
②类的定义
类的定义格式如下:
[ 类修饰符 ] class 类名 extends 基类 implements 接口列表
{
[ 数据成员定义 ]
[ 成员方法定义 ]
}
类的定义说明
①关键字class表示类定义的开始
②类名要符合标识符的命名规范
③修饰符分为访问控制符和类型说明符
类的类型说明符主要有两个final和abstract
类的访问控制符有两个,一个是public,即公共类,另一个就是默认,即没有访问控制符:一个类被定义为公共类,就表示它能够被其它所有的类访问和引用;在一个Java源程序中只能有一个public类,这个类一般含有main方法;不用public定义的类,其只能被同一个包中定义的类访问和引用;在一个Java程序中可以定义多个这样的类
③成员变量的定义
成员变量的定义格式:[ 修饰符 ] 变量的数据类型 变量名 [=初始值]
修饰符主要有四种,分别是:public,private,protected,默认
④成员方法的定义
方法的定义格式
[ 修饰符 ] 返回值类型 方法名([ 形参说明 ])[throws 例外名1,例外名2...]
{
局部变量声明;
执行语句组;
}
方法的定义说明
常用的修饰符为public,private,protected,static,final等
返回值类型:方法一般需要有一个返回值表示执行结果,也可以无返回值(用void表示)返回值类型可以是java类型系统中的所有类型
有返回值的方法使用return语句将值返回给调用者
⑤类的设计原则
取有意义的名字
尽量将数据设计为私有属性
尽量对变量进行初始化
类的功能尽量单一
⑥类的默认构造函数
在Java里,如果一个类没有明显的表名哪一个类是它的父类,Object类就是它的父类
如果类中没有定义构造函数,编译器会自动创建一个默认的不带参数的构造函数
如果程序员为类定义了构造函数,Java就不会为该类创建默认的不带参数的构造函数
注意:如果类中提供的构造函数都不是无参数构造函数,却企图调用无参数构造函数初始化此类的对象,编译时会产生语法错误
⑦类的静态属性和静态方法
程序运行时的内存占用
代码区:存放程序的代码部分
数据区:存放程序的静态数据
堆区:存放程序动态申请的数据
栈区:存放程序的局部数据和参数
问题一:不论产生多少个对象,或不存在任何对象的情况下,某些特定数据的存储空间都只有一份
问题二:某些数据或者函数不要和class object绑在一起
解决方案:通过关键字static便可以处理这两种情况,当你将某个数据成员或某个成员函数声明为static时,它就不再局限于所属的class object上;java中把这种代表类范围信息的变量用关键字static修饰
Static的使用场合
用static修饰的属性(变量)称为静态属性,又叫类变量
用static修饰的方法称为静态方法,又叫类方法(在静态方法里取不到this)
可以用来修饰初始化语句块,这样的语句块常称为静态初始化语句块(要跟非静态初始化语句块区分开来)
static方法中不能直接调用非static的域或方法(必须通过对象名引用)
static函数并不需要先产生任何对象,就可以通过类名来调用
non-static数据/函数和对象绑定(原因)
在static函数中“直接”取用non-static数据/函数,会产生语法错误
⑧静态代码块与非静态代码块的异同点
相同点
都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个
一般在代码块中对一些static变量进行赋值
不同点
静态代码块在非静态代码块之前执行:静态代码块 → 非静态代码块 → 构造方法
静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new一次就执行一次
静态代码块
静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面
静态代码块里面的变量都是局部变量,只在本块内有效
静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类
一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行
静态代码块只能访问类的静态成员,而不允许访问实例成员
3.类与对象的关系
类与对象之间是抽象和具体的关系。类是创建对象的模板,对象是类的具体实例
类(class)是总称,对象(object)是个体,因此对象也叫实例(instance)
二.内存管理
内存管理通常有两种方法:
一种方法是由程序员在编写程序时显式地释放内存,例如C++
另一种方法是由语言的运行机制自动完成,例如Java
1.Java内存释放
垃圾自动回收机制。Java虚拟机后台线程负责内存的回收
垃圾强制回收机制:Java系统提供了方法“ System.gc() ”来强制立即回收垃圾(但系统并不保证会立即进行垃圾回收)
2.Java垃圾自动回收机制
判断一个存储单元是否是垃圾的依据是:该存储单元所对应的对象是否仍被程序所用
判断一个对象是否仍为程序所用的依据是:是否有引用指向该对象
Java的垃圾收集器自动扫描对象的动态内存区,对所引用的对象加标记,然后把没有引用的对象作为垃圾收集起来并释放出去
Java虚拟机可以自动判断并收集到“垃圾”,但一般不会立即释放它们的存储空间
Java系统自己定义了一套垃圾回收算法,用来提高垃圾回收的效率
3.Java内存强制回收
System.gc();
Java没有提供析构方法,但提供了一个类似的方法:protected void finalize()
Java虚拟机在回收对象存储单元之前先调用该对象的finalize方法,如果该对象没有定义finalize方法,则java系统先调用该对象默认的finalize方法
三.封装
1.理解
封装是指隐藏对象的属性和实现细节,仅仅对外公开接口
大的软件系统中往往封装了多个小的系统。大系统是建立在已有小系统的基础上的更为复杂,功能更强大的系统
系统的封装程度越高,那么它的相对独立性就越高,而且使用起来也更方便
封装特性是通过访问控制符好来实现的
2.访问控制符
①public
②private
③protected
④默认访问控制符(没有访问权限修饰符)
3.访问控制范围
①同一个类
②同一个包
③不同包的子类
④不同包的非子类
说明
public(公共变量):可以被任何包中的任何类所访问
private(私有变量):只能被定义它的类访问
protected(受保护变量):可以被定义它的类及其子孙类直接访问,也可以由同一包中的其他类直接访问
package(包变量):可以被定义它的类和同一个包中的其他类(包括派生子类)所访问。(包变量在声明时常常省略package关键字),在其他包中的子类则不能访问父类的包变量
一般而言:java中的成员变量被声明为private的,java的成员方法被声明为public的,构造方法大多数的时候,被声明为public的,但有时也被声明为private的
四.继承
1.软件的复用性
复用其它对象的代码有两种方法:
继承:继承是由子对象完全继承父对象的数据和操作。“ is ”的关系
包容:包容是指把一个对象作为另一个对象的一部分,从而达到复用的目的。“ has ”的关系
2.理解
继承是类实现可重用性和可扩充性的关键特征。在继承关系下类之间组成网状的层次结构
继承避免公用代码的重复开发,减少代码的冗余
通过继承增强一致性,从而减少模块间的接口和界面
3.类的继承
被继承的类称为父类(superclass),继承后产生的类称为子类(subclass)
单继承:如果子类只能有一个直接父类,称为单继承
多继承:如果子类可以有多个直接父类,称为多继承
格式:
[ 修饰符 ] class 类名 extends 父类名
{
类体
}
4.Java继承
Java不支持类的多继承,但支持接口的多继承
Java中的继承通过关键字extends
继承时,子类利用父类中定义的方法和变量就像它们属于子类本身一样
构造函数不能被继承
当通过子类不含参数的构造函数创建子类对象时,先执行父类不含参数的构造函数,再执行子类不含参数的构造函数
5.变量隐藏
变量隐藏:在子类对父类的继承中,如果子类的成员变量和父类的成员变量同名,此时称为子类隐藏了父类的成员变量
子类若要引用父类的同名变量。要用super关键字做前缀加圆点操作符引用,即super . 变量名
6.方法覆盖
方法覆盖:在子类中重写父类的方法,它们的名称,参数以及返回类型完全相同
通过改写方法体来完成不同的功能
7.Super关键字
如果子类调用父类的构造函数,则通过super()调用来实现
如果子类调用父类的同名方法,则通过super . 方法名()来实现
super用于:
引用父类对象的成员变量:super.age;
引用父类对象的成员方法:super.display();
调用父类的构造方法:super("Jack",Male,10);
8.This关键字
this变量代表对象本身
当类中有两个同名变量,一个属于类的成员变量,而另一个属于某个特定的方法(方法中的局部变量),使用this区分成员变量和局部变量
使用this简化构造函数的调用
this用于:
引用自身对象的成员变量:this.age;
引用自身对象的成员方法:this.display();
调用自身的构造方法:this( "Jack",Male,10);
this引用和super引用的对比
Java每个类都默认地具有null,this,super三个域,所以在任何类中都可以不加说明就可以直接引用它们:
null:代表“空”,用在定义一个对象但尚未为其开辟内存空间时
this和super:是常用的指代子类对象和父类对象的关键字
注意:
无论使用this调用本类构造函数,还是使用super调用父类构造函数,都必须是该方法体中的第一条可以执行语句,否则会产生语法错误
9.总结
继承时,子类利用父类中定义的方法和变量就像它们属于子类本身一样
构造函数不能被继承
当通过子类不含参数的构造函数创建子类对象时,先执行父类不含参数的构造函数,再执行子类不含参数的构造函数
五.多态
概念:指同一个方法(具有相同的签名)可作用于不同的对象,从而执行不同的方法代码并获得不同的结果
Java语言支持两种多态:动多态和静态多态
静态多态性:在编译时,就可以被系统识别,也称为编译时多态,也称为静态联编,也称为静绑定
Java中,重载方法采用静态联编的方法实现
动态多态性:在编译时不能被系统识别,而是在运行时才被系统识别,也称为运行时多态,也称为动态联编,也称为动绑定
Java中,覆盖(override)方法,抽象方法和接口采用动态联编的方法实现
方法重载(overloading):Java允许在同一个类或者子类中定义多个同名的方法,但这些方法的参数列表必须不同,即参数的个数不同,或参数类型不同,或参数顺序不同。这种做法称为方法重载
Java中构造方法也是可以重载的
注意1:返回类型不能用来区分重载的方法
注意2:如果一个类中有两个同名方法,其参数列表完全一样,仅仅返回值类型不同,则编译时会产生错误
方法覆盖
在子类中对父类的方法重写时,不仅要求重写的方法的名称,参数,以及返回的类型与被重写的方法完全一致,而且其访问控制也要满足以下2个要求:
①若父类方法定义时有异常抛出,则子类覆盖父类该方法时,该方法也不能有更多的异常抛出,否则编译时会产生错误
②子类方法不能缩小父类方法的访问权限
一个package方法可以被重写为package,protected和public的
一个protected方法可以被重写为protected和public的
一个public方法只可以被重写为public的
Instanceof关键字
Java允许在父类和子类的对象之间进行转换:自动转换,强制类型转换
自动转换
子类和父类之间存在着“ is a ”的关系,所以子类对象转换为父类对象时,是自动转换
或者说向上映射都是自动转换
强制类型转换
当父类对象转换为子类对象时,必须要强制类型转换。或者说向下映射都是强制类型转换
格式如下:
If(父类对象名 instanceof 子类名){
子类对象名 = (子类名)父类对象名;
}
else{
}
abstract关键字
抽象类:如果一个类用abstract修饰,则它是一个抽象类
抽象方法:如果一个方法用abstract修饰,则它是一个抽象方法;抽象方法是没有方法体的,以一个紧跟在声明后的“ ;”结束
注意事项
如果一个类继承自某个抽象父类,而没有具体实现抽象父类中的抽象方法,则必须定义为抽象类
抽象类是不能实例化的,它的作用是提供一个恰当的父类。因此一般作为其它类的超类,与final类正好相反
如果一个类里有抽象的方法,则这个类就必须声明成抽象的。但一个抽象类中却可以没有抽象方法
Final关键字
如果一个类没有必要再派生子类,通常可以用final关键字修饰,表明它是一个最终类
final类中的方法可以不声明为final方法,但实际上final类中的方法都是隐式的final方法
final修饰的方法不一定要存在于final类中
定义类头时,abstract和final不能同时使用
常量
在程序运行过程中,其值不变的量
Java中的常量使用关键字final修饰
final既可以修饰简单数据类型,也可以修饰复合数据类型
final常量可以在声明的同时赋初值,也可以在构造函数中赋初值
如果在声明常量的同时,使用static修饰,表明这个量是类常量
简单数据类型常量包括:整型常量,浮点数常量,字符常量,布尔常量
复合数据类型常量可以是Java类库定义的复合数据类型,也可以是用户自定义的复合数据类型
常量声明格式:final 数据类型 常量名 = 值
简单数据类型常量其值一旦确定,就不能被改变
复合数据类型常量指的是引用不能被改变,而其具体的值是可以改变的
常量既可以是局部常量,也可以是类常量。如果是类常量,一般在数据类型前加上static关键字修饰
常量名一般大写,多个单词之间用下划线连接
接口Interface
接口是一组方法集,接口中包含的方法都是抽象方法,定义方法体的任务留给实现该接口的类去完成
接口是用来实现类间(不相关类)多重继承功能的结构
接口是Java中的一种复合数据类型,是用interface关键字来定义的
接口是一种特殊的“类”,一种特殊的“抽象类”
接口中所有的方法都默认是public abstract的,并且只有方法头和参数列表,没有方法体
接口中所有的变量都默认是public static final的
接口中没有构造方法
接口可以继承,而且可以多重继承
一个类可以实现多个接口
接口中的方法体可以由Java语言书写,也可以由其他语言书写,用其他语言书写时,接口方法需要用native关键字修饰
接口的功能:通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系;通过接口可以指明多个类需要实现的方法;通过接口可以了解对象的交互界面,而不需要了解对象所对应的类;通过接口可以在运行时动态地定位类所调用的方法
[ public ] [ interface ] 接口名称 [ extends 父接口名列表 ]
{
//静态常量
[ public ] [ static ] [ final ] 数据类型 变量名 = 常量名;
//抽象方法
[ public ] [ abstract ] [ native ] 返回值类型
方法名(参数列表);
}
接口可以继承,而且可以多重继承
实现接口
[ 修饰符 ] class类名[ extends父类名 ][ implements接口A,接口B,...]
{
类的成员变量和成员方法;
为接口A中的所有方法编写方法体,实现接口A;
为接口B中的所有方法编写方法体,实现接口B;
......
}
注意
一个类在实现某个接口的抽象方法时,必须以完全相同的方法头。否则,只是在重载一个新方法,而不是实现已有的抽象方法
接口的抽象方法的访问限制符默认为public,所以类在实现这些抽象方法时,必须显式的使用public修饰符,否则将被警告为缩小了接口中定义的方法的访问控制范围
package关键字
包(package)帮我们管理大型的软件系统
包可以包含类,接口和子包
Java通过关键字packpage创建包
包(package)是类和接口的集合
Java用包来管理名称空间。包消除了不同组的类中潜在的类名冲突问题
Java里的每一个类都属于一个特定的包
“ 包是类的容器 ”
包是有层次的
包定义语句必须是Java源文件中的第一条可执行语句
在默认情况下,系统会为每一个 .java源文件创建一个无名包
无名包不能被其它包所引用,为解决这个问题,创建有名字的包