重新开始学Java-3面向对象
看到Java的第三部分了,开始涉及面向对象的部分。也是自己基础最差的部分了~
3-面向对象
面向过程与面向对象
面向过程
关注点:
关注实现过程,注重因果关系
优点:
- 业务逻辑简单
- 快速开发
- 前期投入成本低
缺点:
- 业务逻辑复杂的时候,实现较困难
- 耦合度高,扩展力差
- 没有独立体,组建不能复用
面向对象
关注点:
关注独立对象,由独立对象拼接能完成的功能
优点:
- 耦合度低,扩展力强
- 组件能够复用
- 易处理复杂的业务逻辑
缺点:
- 前期投入成本高(抽取独立体,进行系统分析和设计)
面向对象三大特性
- 封装!
- 继承!
- 多态!
有了封装,才有继承;有了继承,才有多态
面向对象开发过程:
- 面向对象分析(Object-oriented analysis,OOA)
- 面向对象设计(Object-oriented design,OOD)
- 面向对象编程(Object-oriented programming,OOP)
类和对象
什么是类
是从现实世界中抽象出来的,具有共同特征的模板
什么是对象
现实世界中真实存在的个体
类和对象的关系
实例化的类,叫做对象
对象抽象出来的,叫做类
类的语法
[修饰符列表] class 类名
eg:
public class Student{
类体;
}
其他信息
- 除了基本数据类型,其他定义的数据类型都是引用数据类型
- 类描述的内容:属性和动作
对象的创建
JVM内存信息
方法区内存:一个(静态变量存储在方法区内存)
堆内存:一个(对象创建后,存放在堆内存中,GC机制针对的内存区)
栈内存:一个线程一个
基础数据类型的默认值
数据类型 | 默认值 |
---|---|
byte、short、int、long | 0 |
float、double | 0.0 |
char | \u0000 |
boolean | false |
引用数据类型 | null |
类、引用和对象
用个栗子说明一下:
//假设已有一个类叫Student
Student s=new Student();
代码中:
Student表示一个类,是类的定义
s表示指向Student对象的一个引用,属于局部变量
new Student()表示应用构造函数,实例化了一个Student对象
面向对象的封装性
好处
- 提高安全性
- 避免对象复杂的内容显示出来
- 方便重用
步骤
- 将类的属性信息私有化
- 对类的属性信息获取与赋值设定相应函数(set函数和get函数)
构造方法
语法结构
修饰符列表 构造方法名(形参列表){}
eg:
public class Student{
int stu_no;
//无参构造函数
public Student(){
}
//有参构造函数
public Student(int stu_no){
this.stu_no=stu_no;
}
}
构造方法作用
- 创建对象
- 给类中定义的属性赋值
构造方法调用
new 构造方法名()
构造方法的返回值
返回构造方法所属类本身
其他信息
在定义类的时候,会默认创建缺省值的构造方法
但如果开发人员提供了构造方法,系统不再提供缺省值的构造方法(建议在定义类的时候都写上缺省值的构造方法)
参数传递
Java的函数参数传递的本质:传递的是参数值
但由于有些参数保存的是对象地址,那么将参数值传递的时候,传递的是地址,那么再对参数进行修改,数据会保存
this关键字
实质
存储的是指向自己的地址
语法
- 通常可以省略不写
- Static修饰的变量和方法不能使用this关键字(原因见static部分)
- 当用来区分局部变量和实例变量时,this不能省略
- 可以用this()直接调用无参的构造函数
static关键字
含义
表示静态的,类级别的
语法规定
在类加载的时候初始化,存储在方法区内存中
用“类名.”方式访问,“引用.”方式也可以访问
静态代码块
在类加载的时候执行
语法格式如下
static{
java语句;
}
实例代码块
在类构造函数前执行
语法格式如下
{
java语句;
}
静态和实例的区别
是否存在对象
继承
语法格式
修饰符列表 class 类名 extends 父类名{
java语句;
}
名词
假设A继承B
A类被称为:子类、派生类、subclass
B类被称为:父类、超类、supercalss
语法规定
- java中只允许单继承
- 私有的不继承
- 构造方法不继承
- 其余的信息可以继承
- 如果一个类没有继承任何类,默认继承java.lang.Object类
方法重写
也叫方法覆盖,override,overwrite
方法重载
方法重载关注点:
- 在同一类中
- 方法名相同
- 形参数据类型可以不同
- 形参数据个数可以不同
- 形参数据顺序可以不同
- 和函数的返回值无关
方法重写应用场景
子类从父类继承的方法不能满足需求
重写条件
- 两个类存在继承关系
- 重写的方法返回值类型相同,形参相同,函数名相同
- 访问权限不能更低,只能更高(举个栗子:父类的方法权限为protected,子类重写的方法只能是protected或者public)
- 抛出的异常不能更多,可以更少
其他信息
- 方法重写只针对函数,不针对属性
- 私有函数不存在继承,所以不能覆盖
- 构造方法不存在继承,所以不能覆盖
- 静态方法不能覆盖
多态
向上转型
子类型转换为父类型,称为向上转型
语法
父类 父类引用=new 子类();
规定
- 通过父类引用,只能调用父类中存在的方法(编译阶段)【静态绑定】
- 父类引用实际调用的是子类重写的方法(运行阶段)【动态绑定】
出现动态绑定的原因:
语法实际创建的子类对象,因此调用的也是子类方法
向下转型
父类型转换为子类型,称为向下转型,通常会应用强制类型转换
通常是需要调用子类中特有的方法,因此需要向下转型
语法
子类 子类引用=(子类)父类引用
注意!!!
如果通过向上转型创建的子类对象和强制类型转换的子类需要相同,否则报错类型转换异常(classcastException)
instanceof
向上转型过程中,只要编译通过,运行不会报错
但向下转型过程中,编译通过,运行可能会出错
解决向下转型中的报错问题:instanceof
语法格式
引用 instanceof 类
输出结果
布尔类型,true或者false
举个栗子
假如:
s instanceof Student
true:表示s这个引用指向的是Student类型的对象
false:表示s这个引用指向的不是Student类型的对象
多态的作用
- 解耦合,提高程序扩展力
- 使系统是面向抽象对象编程,而非过程
final关键字
语法要求
- 表示最终的,不可变的
- final修饰的类不能被继承
- final修饰的变量一旦赋值,不能重新更改
- final修饰的方法不能覆盖
- final修饰的引用一旦指向某个对象,不能再指向其他对象,指向的对象可以修改值
- final修饰的实例变量必须手动赋值(或者在构造方法中赋值)
第六条举个栗子
public class Student{
final String classname="3班";
或者
final String classname;
public Student(){
classname="3班";
}
}
常用情况
通常final和static连用,修饰的应用称为常量
常量名通常全部大写,单词间用下划线连接
举个例子
public static final double PI=3.1415926;
import和package
package机制
作用
便于管理程序
语法
- 只能写一句
- 一个包对应一个目录,包之间用.隔开
- 写了包名,类名就变成包名+类名了
- 写了包名,字节码(.class)文件再包名构成的文件夹下
package 包名;
包的明名规范
- 通常是公司域名倒序+项目名+模块名+功能名
- 包名全部小写
import
语法
import 类名;
或者
import 包名+类名;
规则
同一个包下的类不需要导入,不在同一个包下的类需要导入
java.lang中的类全部不需要导入,会自动引入
访问控制权限
内容
权限名称 | 访问范围 |
---|---|
public | 表示公开的,在任何地方都能访问 |
protected | 表示受保护的,只能在同一个包和子类中访问 |
缺省 | 只能在同一个包中访问 |
private | 表示私有的,只能在本类中访问 |
其他
四个访问控制权限可以用来修饰方法、变量
类只能由缺省和public修饰
super关键词
注意点
- super不是引用数据类型,不存储内存地址,不指向父类对象
- super表示的是当前对象中父类型特征
- 和this是相同的,需要对象,所以不能用在静态上下文中
成员方法中的super
当子类和父类中同时存在某数据,需要在子类中访问父类型中对应数据应用super
构造方法中的super
系统默认,表示调用父类型的构造方法
注意:虽然调用了父类型的构造方法,但并没有创建父类型的对象!!!
super()
抽象类
定义
修饰符列表 abstract class 类名{
java语句;
}
抽象方法定义
访问权限 abstract 返回值 方法名(形参列表);
语法规则
- 抽象类不能实例化对象,但存在构造方法
- 抽象类中可以定义抽象方法
- 抽象类中不一定有抽象方法,抽象方法只能在抽象类中
- 非抽象类继承抽象类,必须将抽象类中的所有抽象方法覆盖/实现/重写
- final不能修饰抽象类和抽象方法(因为不能继承和重写)
接口
接口完全是抽象的
定义
修饰符 interface 接口名{
}
语法规则
- 接口中只能出现常量和抽象方法
- 接口没有构造方法,不能被实例化
- 接口和接口之间能够多继承
- 一个类可以实现多个接口(implements)
- 一个非接口类要实现接口,需要将接口中所有方法实现/覆盖/重写
- 接口中出现的一定是常量,所以可以省略修饰符public static final
- 接口中出现的一定是抽象方法,所以可以省略修饰符public abstract
接口和抽象类的关系
当接口和抽象类都能实现某一功能时,优先选择接口
因为类在实现接口的同时,还保留了类的继承,且接口是可以多继承的
Object类
是所有没有定义类的父类
toString()
返回值
返回java对象的字符串表示形式
通用形式:类名@对象内存地址经哈希算法得到的int值转成16进制
常用
如果print函数中传递的参数是引用数据类型,默认调用toString()
equals()
若传递的参数是引用数据类型,则比较两者的内存地址,地址相同返回true,否则返回false
所以,两个字符串对比是否相同要用String.equals(),因为重写了
若需要比较的是引用数据类型,需要重写equals()
finalize()
垃圾回收机制在回收前,调用finalize()方法
可以用来释放资源,也可以避免垃圾数据被回收(让垃圾数据被重新指向)
hashcode()
返回值:
对象的哈希码值
clone()
创建并返回对象的副本,通常用以避免某对象的结构造成破坏
内部类
特点
可以用来访问外部类中的私有变量
生成的文件命名格式:外部类名$内部类名.java
静态内部类
静态内部类等同于静态变量
可以直接访问外部类的静态数据,不能访问外部类的成员数据
创建静态内部类对象:
new 外部类.内部类()
成员内部类
成员内部类等同于成员变量
可以直接访问外部类的所有数据
成员内部类中不能有静态的声明
创建成员内部类对象:
外部类 外部类对象=new 外部类构造方法;
内部类 内部类对象=外部类对象.new 内部类构造方法;
局部内部类
局部内部类等同于局部变量
一般在类的成员方法中定义,不再用访问控制权限符修饰
局部内部类中不能定义静态方法
局部内部类只能访问由final修饰的局部变量
局部内部类对象的创建只能在定义的成员方法中进行
匿名内部类
直接举个栗子吧~
public class Test{
public static void method1(CustomerService cs){
cs.logout();
}
public static void main(String[] args){
method1(new CustomerService(){
public void logout(){
System.out.println("用户服务退出");
}
});
}
}
interface CustomerService{
void logout();
}
单例模式
类的对象只有一个
优势
避免空间重复利用被浪费
创建要点
- 构造函数私有化
- 提供一个静态的对象引用
- 提供静态的获取类对象的方法
饿汉式单例模式
直接举栗子~
public class User{
private static User u=new User();
private User(){}
public static User getInstance(){
return u;
}
}
懒汉式单例模式
直接举栗子~
public class User{
private static User u;
private User(){}
public static User getInstance(){
if(u==null)
u=new User();
return u;
}
}
类之间的关系
泛化关系
就是类之间的继承、接口之间的继承关系
UML中是用实线的空心箭头指向父类
实现关系
就是类对接口的实现
UML中是用虚线空心箭头指向接口
关联关系
类之间的连接(一个类中包含另一个类的对象)
UML中是用实线箭头指向被关联的对象,表示可以通过此类找到另一个类
聚合关系
关联关系的一种,比关联关系更强,是整体和部分的关系
整体和部分之间不存在依赖关系,整体不决定部分的生命周期
UML中是以实线连接,空心菱形位于整体旁边
合成关系
比聚合关系要更强,也是整体和部分的关系
整体和部分之间存在强依赖,整体决定了部分的声明周期
UML中是以实线连接,实心菱形位于整体旁边
依赖关系
比关联关系弱(另一类的对象只在类的方法形参中出现)
UML中以虚线连接,箭头指向被依赖的对象,表示应用到另一个类的对象
is-a,is-like-a,has-a
is-a 表示泛化关系
is–like-a表示实现关系
has-a 表示关联关系/聚合关系/合成关系/依赖关系
以上。
到这算是非常非常非常粗糙的把Java表面的内容过了一下啦~~~
还需比较细致的对中间的部分内容复习一下呀~