这里写目录标题
1.面向对象概述
面向过程:是具体的,按步骤进行,适合处理简单问题。
面向对象:是抽象的,解决问题先分类,对所分的类进行单独思考,适合处理复杂问题、多人协作问题。但对分类后的细节问题,仍需面向过程解决。
面向对象编程OOP的本质:以类的方式组织代码,以对象的形式组织(封装)数据。
OOP的三大特性:封装、继承、多态
从认识论考虑:先有对象后有类!对象是具体的,类是抽象的,类是对对象的抽象。
从代码运行考虑:先类后有对象!类是对象的模板
2.回顾及加深方法
- 静态方法和非静态方法
-
在不同类中
可以直接调用静态方法,但是调用非静态方法必须先实例化后调用!
-
在一个类中
📜 非静态方法之间可以直接相互调用
📜静态方法之间也可以直接相互调用
📜但是**静态方法不能调用非静态方法*
⭐️因为静态方法和类一起加载,而非静态方法在类实例化(New)之后才存在,所以已经存在的调用还没存在的会出错
- 值传递
public class 值传递 {
public static void main(String[] args) {
int a=1;
change(a);
System.out.println(a);//输出 1
}
//返回值为空
public static void change(int a) {
a =100;//改变的是形参a
}
}
- 引用传递
//引用传递:传递的是对象,本质还是值传递
//只能有一个 public class,但是可以有多个 class
class Person{
String name;//一个属性:name
}
public class 引用传递 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //输出 null
引用传递.change(person);
System.out.println(person.name); //输出 ssss
}
public static void change(Person per) {
//per 是一个对象,指向传递的person
per.name="sssss";
}
}
3.对象的创建分析
- 类与对象的关系
❗️ 类是一种抽象的数据类型,它是对 某一类 事物整体的描述 / 定义,是一个模板,不能代表一个具体的事物!!!
❗️ 对象是对抽象概念的具体实例,对象(在堆中)是通过引用(在栈中)来操作的
- 类与对象的创建
- 创建类
public class Pet {
//属性:也称字段Field 或者 成员变量
//属性构成 修饰符 + 属性类型 + 属性名 = 属性值;
//默认属性 数字:0 0.0 、char:u0000 、boolean:false 、 引用:null
public int age;
public String name;
//利用默认的无参构造器
//方法
public void shout() {
System.out.println(this.name+"叫了一声");
}
}
- 创建对象
使用 new 关键字创建对象。在new对象的时候,除了 分配内存空间 之外,还会给创建好的对象进行默认初始化(例如,对属性初始化),以及对类中构造器的调用。
3. 构造器
一个类即使什么都不写,也会存在一个默认构造方法
类中的构造器,也称构造方法,是创建对象时必须调用的。主要作用为:new创建对象时,本质是在调用构造器、初始化值;并且构造器有以下两个特点:
- 必须和类的名字相同
- 没有返回类型,不能写void!!
人为定义一个构造器(显示定义一个构造器),能够初始化一些信息,可分为:无参构造器和有参构造器
-
无参构造器
-
有参构造器
❗️一旦定义了有参构造器,就必须显示定义无参构造器,该无参构造器可以什么都不写创建构造器的快捷键:alt+insert
-
创建对象的内存分析
创建对象时,对象名字即引用变量名都在栈中,实际new的对象在堆中
4.面向对象的三大特性
1.封装
封装主要是针对类中的属性而言
属性私有 private ;get / set :提供一些可以操作属性的方法
快捷键:alt+insert 生成 get/set 方法
- 该露的露,该藏的藏
程序设计要求 ”高内聚、低耦合 “。高内聚:类的内部数据操作细节由自己完成,不许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装主要是针对类中的属性而言
- 封装的意义
- 提高程序安全性,对传入的数据进行安全性判断
- 隐藏对数据操作的细节
- 提高了系统的维护性
- 统一接口,均为 get/set 方法
public class Student {
//属性私有
private String name;
private int id;
private char sex;
//提供一些可以操作属性的方法
//提供 public 的 get/set 方法
//get 获得数据的值
public String getName() {
return this.name;
}
//set 设置数据的值
public void setName(String name1) {
this.name=name1;
}
public int getId() {
return id;
}
public void setId(int id1) {
if (id1>0 && id1<100) {
//数据安全性检验
this.id = id1;
}else {
System.out.println("学号不合法");
}
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("三吉");
System.out.println(s1.getName());
s1.setId(105);//输出 学号不合法
}
}
2.继承 extends
类与类之间的关系:继承、依赖、组合、聚合等等。
继承的本质是对某一批类的抽象,从而实现对现实世界更好地建模。extend 的意思是“扩展”,即子类是父类的扩展。子类,又称派生类;父类,又称基类。
父类中私有的属性或方法,无法被继承。Java中所有的类默认直接或间接地继承Object类
❗️ Java中只有单继承,没有多继承,只能直接继承一个类(一个儿子只能有一个父亲)
快捷键:CTRL+H 打开继承树
⭐️ super
-
super 只能在继承条件下使用
-
在子类中可以通过 super+ . 对父类中的公共/受保护的属性或方法进行调用
-
创建子类,总是会先调用父类的无参构造器。若利用super()显示地调用父类的无参构造器,则需要将super()放在子类无参构造器的最前面
-
super 和 this 不能同时调用构造方法!
⭐️ 方法重写
方法重写和静态方法无关,只和非静态方法有关
方法重写的前提是要有继承关系,是子类重写父类的非静态方法
快捷键:alt+insert
方法重写 |
---|
重写的前提是:有继承关系,子类重写父类的方法 |
方法名相同,方法体不同 |
参数列表必须相同 |
修饰符:范围只可以扩大,即子类访问权限 大于等于 父类访问权限 public > protected > default > private |
返回类型:子类方法返回类型 小于等于 父类方法返回类型 |
抛出的异常:异常范围只可以缩小,即子类抛出异常 小于等于 父类抛出异常 |
重写的意义 |
---|
父类的功能,子类不一定需要,或者不一定满足子类的需要 |
3.多态
多态,即同一个方法可以根据指向对象的引用不同而调用不同的方法。
多态存在的条件:有继承关系、子类重写父类的方法。父类引用指向子类对象
实现动态编译(类型的最终状态只有在执行的过程中才能决定),使得可扩展性增强。
多态中(有继承关系时)对象能执行哪些方法,主要看该对象的左边,左边有该方法则能调用,没有则报错。若父子类都有该方法,但子类重写了父类的方法则调用子类重写的方法。
父类,可以指向子类,但是不能调用子类独有的方法
多态 |
---|
多态是方法的多态,没有属性的多态 |
多态存在于有继承关系的父子类,否则会出现 类型转换异常ClassCastException |
方法重写 |
父类引用 指向 子类对象 Father f=new Son(); |
注意什么方法不能重写!例如,被static修饰的方法(属于类,不属于实例)、被final修饰的方法、被private修饰的方法
- instanceof
instanceof 判断两个类之间是否存在父子关系
X instanceof Y,看X引用指向的对象是否为Y的子类型,有就返回true,无则返回false。如果X类和Y类没有继承关系则编译报错
- 类型转换
基本类型之间的转换,高转低——强转,低转高——自动
引用类型之间也遵循如上规则
5.抽象类和接口
1.抽象类Abstract
在一个类前加关键字 abstract ,就变成了抽象类,抽象出共有属性,提高开发效率
抽象类不能多继承
抽象方法没有方法体,在一个类中,只声明了方法名字而不实现方法体,在方法前加关键字 abstract ,就变成了抽象方法。抽象方法不能脱离抽象类而单独存在。
普通方法也可以出现在抽象类中
//抽象类
public abstract class Action {
//抽象方法,有人帮我们实现
//抽象方法必须在抽象类中
public abstract void run();
//普通方法
public void eat() {
System.out.println("吃饭啦");
}
}
**抽象类 **中如果有 抽象方法 ,则继承该 抽象类的子类 必须重写这些抽象方法,除非子类也是抽象类。
//抽象类的所有方法,必须由抽象类的子类实现
//除非子类也是抽象类
public class A extends Action{
@Override
public void run() {
}
}
抽象类不能直接 new 实例化,只能靠 它的子类 new实现!,抽象类虽然有构造方法,但是不能直接实例化的原因是抽象类是用来初始化的,而非实例化的
注意:在抽象类的方法权限修饰符禁止用private,因为抽象类的目的就是要实现代码复用,方便子类继承。
抽象类的中抽象方法只允许用public和默认修饰(JDK1.8之前默认是用protected修饰,但在JDK1.8之后则是默认为default修饰) , 所以抽象类的子类访问权限修饰符可以是public 或 protected
Java中只能实现单继承,但是可以利用 接口 实现多继承
2.接口Interface
- 普通类 中只有具体的实现
- 抽象类 中具体的实现(即普通方法)和规范(即抽象方法)都有
- 接 口 中只有规范,只能进行约束,将约束和实现分离
接口 就是规范,定义的是一组规则,本质是契约,需要大家遵守,让不同的人实现。接口是面向对象的精髓,是对于对象的抽象。
接口 中定义的所有方法 ,默认为抽象方法 public abstract 的,意味着接口需要有实现类。抽象方法没有方法体。
接口没有构造方法
在 JDK8 中 ,接口中的方法可以被default和static修饰,但是!!!被修饰的方法必须有方法体。
接口 中定义的所有属性 默认为 静态常量 public static final,但是一般不在接口中定义属性。
接口 和抽象类一样不能直接被实例化,因为接口中没有 构造方法。
一个类可以实现多个接口,需要关键字 implement,类必须重写接口中的方法。接口和类不一样,接口中只有方法的定义,类中有方法的实现
注意:在接口的子类中,子类方法的访问权限修饰符不能低于父类(父类方法的默认权限为 public abstract),因此子类方法也只能为public
//接口类
public interface UserService {
//接口中定义的 所有属性 默认为 静态常量 public static final
public static final int age=18;
//用户服务: 增删改查
//接口中定义的 所有方法 都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//接口类
public interface TimeService {
void timer();
}
//类 可以实现 接口,利用关键字implement
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
6.内部类和OOP实战
1.内部类
内部类 就是在一个类的内部定义一个类。如,A类中定义一个B类,则B类相对于A类就称为内部类,A类相对B类为外部类。
- 成员内部类
❣️ 内部类的实例化 需要调用 外部类
❣️ 内部类 可以访问 外部类的 私有变量和私有方法
public class Outer {
private int id;
public void out() {
System.out.println("这是外部类的方法");
}
public class Inner{
public void in() {
System.out.println("这是内部类的方法");
}
//内部类 可以访问 外部类的私有变量、私有方法
public void getId() {
System.out.println(id);
}
public void getMethod() {
out();
}
}
}
- 静态内部类
❣️ 内部类 不可以访问 外部类的私有变量和私有方法,因为 静态内部类先实例化
- 局部内部类
方法中定义的变量为 局部变量,方法中定义的类为 局部内部类
public class Outer2 {
public void method() {
//方法中定义的变量为 局部变量
int a=10;
//局部内部类
class Inner {
public void in() {
System.out.println("这是局部内部类的方法");
}
}
}
}
- 匿名内部类
匿名内部类,即 没有名字来初始化类,不需要将实例保存到变量中。
匿名内部类可以匿名创建类、接口