五、Java类和对象
1、概述
1.1、基本概念
类是具有相同属性和行为的一组对象的集合
,包含数据和操作,数据被称为成员变量
,操作被称为方法
对象是类的实例,即对象 = 数据 + 行为
或者对象 = 状态 + 操作
类抽象的、概念上的定义,对象是一个具体的、实际存在的个体,即一个实例
1.2、类的特性
封装:提供多种访问的权限,目的是:隐藏类中成员变量和方法的细节
继承:提供从已存在的类创建新的类的机制
多态:方法执行的多样性,表现为:覆盖和重写
1.3、定义类
Java程序设计的基本单位就是类,Java源文件就是由若干个类构成的
// 格式
声明类{
成员变量的声明
方法的声明及实现
构造方法
代码块
内部类
}
// 定义类的格式
[修饰符] [abstract|finally] class 类名 [extends 父类] [implements 接口列表]{ // 注:修饰符:省略 或者 public
// 声明成员变量
[修饰符] [static] [final] 数据类型 成员变量名 [ = 表达式] // static: 类成员变量 ;final: 常用于声明常量
// 注:修饰符:public、private、protected、省略
// 尽可能用private
// 声明方法
[修饰符] [static] [finally] 返回值类型 方法名([参数列表]) [throws 异常类]{
语句序列
[return [返回值]]
}
// 注:修饰符:public、private、protected、省略
// throws 异常类:声明方法抛出指定异常
}
1.4、变量
1.4.1、分类
名称 | 定义位置 | 作用域 |
---|---|---|
成员变量 | 在类中声明 | 整个类 |
局部变量 | 在方法中声明 | 该方法 |
1.4.2、补充
对成员变量的操作只能在方法中
在一个确定的域中,变量名应该是唯一的
1.4.3、成员变量和局部变量的区别
成员变量 | 局部变量 | |
---|---|---|
访问权限 | 整个类都可以访问 | 只在所属区域有效 |
内存位置 | 堆内存 | 栈内存 |
默认值 | 有 | 无 |
存在时间 | 随着对象的创建存在,随着对象的删除消失 | 随着所属区域的结束释放 |
2、基本操作
2.1、创建对象的步骤
2.1.1、对象的声明
声明完后,无实体,不能调用,仅仅在栈内存中开辟了一个空间
// 格式
类名 对象名;
Mydate data;
2.1.2、实例化
在堆中开辟了空间,可以调用
// 格式
对象名 = new 类名([参数列表])
//也可声明和实例合成一步
类名 对象名 = new 类名([参数列表])
2.2、使用对象
对象时一种引用型变量,变量中存放着引用,指向堆中的地址
2.3、构造方法
创建对象时自动调用,名字与所在类完全相同,不会被子类继承
3、成员变量
静态成员变量 | 普通成员变量 | |
---|---|---|
别名 | 类成员变量 | 实例成员变量 |
形式区别 | 有static修饰 | 无static修饰 |
存储位置 | 方法区(共享区域区)的静态区 | 堆内存中 |
对该类的所有对象都一致 | 区分同一类创建的各个对象 | |
调用方式 | 类名和对象都可调用 | 只能被对象调用 |
4、静态初始化块
不包含在任何方法体中
当类被载入时,静态代码块被执行,且只执行一次
可以用来进行初始化
类是在第一次被使用时进行载入
class A{
static{
//静态代码块
}
}
5、成员变量初始化顺序
静态成员变量定义时直接给出初始值 > 静态初始化 > 实例成员变量定义时给出初始值 > 初始化块 > 构造方法
6、方法
实例方法 | 类方法 | |
---|---|---|
区别 | 除构造方法外的其他方法 | 声明时使用static修饰 |
调用 | 可以调用类方法和实例方法 | 只能调用类方法 |
操作 | 可以操作类成员变量和实例成员变量 | 只能操作类成员变量 |
只能被对象调用 | 类和对象都可调用 |
7、匿名对象
不定义对象的引用,直接调用这个对象的方法的对象
new 类名().方法名();
用处:
1、该对象只使用一次
2、将匿名对象作为实参传递给一个方法调用
8、this引用
代指使用当前对象的成员变量
不可以出现在类方法中
// 使用this调用本类重载的构造方法时,this()必须是第一条语句
class Person{
int age;
Person(int age){
this.age = age;
}
Person(){
this(30);
this.age = 20;
}
}
9、继承
9.1、基本概念
由已有的类创建新的类的机制
Java不支持多重继承,即一个类只能由一个父类
若没有声明父类,默认继承Object类
// 格式
[修饰符] class 子类名 [extends 父类名]{
}
9.2、继承原则
1、子类继承父类的成员变量
2、子类继承父类除构造方法外的方法
3、子类可以增加自己的成员变量和方法
4、子类可以重新定义父类的成员变量贺方法
5、子类不能删除父类的成员变量和方法
6、重写时,重写后的方法不能拥有比重写前更严格的访问权限、不能比被重写前产生更多的异常
9.3、补充
this代表本类对象的引用
super代表一个父类空间
9.4、super
1、调用被子类隐藏的成员变量和方法
2、调用父类的构造方法,必须在子类的构造方法中使用,且必须是子类构造方法的第一条
,本质上来说并不是创建一个“独立的父类“,而是为了完成当前对象的父类型特征的初始化操作
9.5、访问控制
类的访问权限:public、缺省
public | protected | default | private | |
---|---|---|---|---|
当前类的方法 | √ | √ | √ | √ |
同一包内 | √ | √ | √ | × |
其他包内的继承类 | √ | √ | × | × |
其他包内的非继承类 | √ | × | × | × |
10、多态
方法的多态:方法的重写、方法的重载
类型的多态:子类是一种父类类型
10.1、类型的多态
父类引用能够被赋值为子类对象,反之则不行
父类 = 父类
父类 = 子类
子类 = 父类
10.2、上转型对象
zi是fu的子类或者间接子类,当用子类zi创建一个对象,并把这个对象的引用放到父类声明的对象中时,称这个对象是子类zi对象的上转型对象,上转型对象的实体是子类负责创建的,但上转型对象会失去原对象(子类)的一些成员变量和功能
上转型对象的成员变量同父类
一致
上转型对象的方法同子类
一致
11、abstract类和final类
// abstract修饰的类称为抽象类
abstract class A{
}
// final类不能被继承,即不能有子类
final class A{
}
11.1、abstract类
特点:
1、构造方法、类方法不能被声明为抽象方法
2、抽象方法只允许声明,不允许实现,而且不允许同时使用final和abstract
3、不能用new运算符创建对象:如果一个非抽象类是某个抽象类的子类,则必须重写全部抽象方法为不使用abstract修饰的方法
11.2、final关键字
修饰类 | 不能被继承 |
---|---|
修饰成员变量 | 不能改变,通常与static同时使用,定义一个常量 |
修饰方法 | 不能被重写 |
11.3、final类
// 声明最终类
public final class 类名
// 声明最终方法
public final 返回类型 方法名([参数列表])
12、接口
12.1、基本操作
可以增加很多类都需要实现的功能,使用相同的接口不一定有继承关系
通过interface
声明一个接口
interface 接口名 [extends 父接口]
接口只允许有方法体,不允许实现
如果一个类实现了某个接口,必须实现这个接口的所有方法,即为这些方法提供方法体
// 使用implements表示实现了一个或多个接口
interface A implements B,C……{
}
接口是引用类型
12.2、接口回调
把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量,那么该接口变量就可以调用贝类实现的接口中的方法
interface A{
void shout();
}
class dog implements A{
void shout(){
System.out.println("Wang!");
}
}
public class Main{
public static void main(String[] args){
A a;
a = new dog();
a.shout(); //Wang!
}
}
13、接口和抽象类的比较
接口 | 抽象类 |
---|---|
抽象方法 | 抽象方法和非抽象方法 |
只能有常量 | 常量变量都有 |
没有构造方法 | 可以有构造方法 |
接口是特殊的抽象类
14、内部类
14.1、基本概念
内部类同外部类一样,在外部类中相当于外部类的一个成员
外部类的成员变量在内部类仍有效
内部类的方法也可以调用外部类的方法
14.2、内部类分类
定义位置 | 说明 | |
---|---|---|
成员内部类 | 类的内部 | 外部类的实例成员;在没有外部类的实例的情况下,内部类不能实例化;可以用任何修饰符修饰 |
局部内部类 | 方法或语句块内 | 只能在他的方法内使用 |
匿名类 | 没有类名的局部内部类 | |
嵌套顶级类 | 使用static修饰的成员内部类 |
// 局部内部类的声明
外部类实例.new 内部类();
15、浅拷贝与深拷贝
对于基本数据类型,可以通过赋值语句完成复制
对于引用型数据类型,通过赋值语句不能完成真正意义上的复制
浅拷贝:仅仅复制他所考虑的对象
深拷贝:复制他所考虑的对象和扶植的对象所引用的对象
六、Java异常处理
1、程序错误与处理
类型 | 发现 | 说明 | 举例 |
---|---|---|---|
语法错 | 编译时发现 | 违反语法规范 | 使用未定义的变量 |
逻辑错 | 系统无法发现 | 程序员考虑失误 | |
语义错 | 运行时发现 | 在语义上出现错误 | 除数为0 |
2、异常处理机制
// 格式
try{
}catch(){
}finally{
}
3、Java的错误和异常
3.1、错误
程序运行时遇到的硬件、操作系统、其他软件或操作的错误
当产生错误时,会抛出Error类对象
2.3、异常
在硬件操作系统正常时,程序运行时遇到的运行错误
Java的异常处理机制使程序能够捕获和处理异常
4、程序错误与处理
通过异常处理机制,使程序具有处理错误的能力,运行错误时也不会导致程序终止
在没有发生异常的情况下:try—finally
发生异常的情况下:try—catch—finally
5、java的异常处理
5.1、catch子句捕获异常的匹配规则
1、抛出异常对象与catch子句的参数类型相同
2、抛出对象为catch子句参数类的子类
3、按照先后次序补货抛出异常对象,只捕获一次
建议:
1、多个catch子句需要按照子类到父类的次序进行排列
2、通常最后一个catch子句的异常类声明为Exceptuion
5.2、Exception的输出方法
getMessage()
5.3、方法声明抛出异常的throws子句
如果一个方法将产生异常,而该方法不想处理或不能处理该异常,可以在方法声明时,采用throws子句声明该方法将抛出异常
抛出后,必须
捕获并处理该异常
[修饰符] 返回值类型 方法([参数列表])[throws 异常类]
抛出自定义异常对象的throw语句也必须由try语句捕获并处理
自定义的异常类通过扩展Throwable
子类来创建自定义异常类,但是,通常更多的是扩展Exception
类
6、注意事项
1、子类在覆盖父类方法时,父类的方法如果抛出了异常,则子类的方法只能抛出父类的异常或者父类异常的子类
2、父类抛出多个异常,则子类只能抛出父类异常的子集
3、如果父类的方法没有抛出异常,则子类覆盖是绝对不能抛出异常的,只能try