1 类的定义
一类具有共同属性和行为的抽象。类的组成是属性和行为。属性,在类中通过成员变量来体现(类中方法外的变量)。行为,在类中通过成员方法来体现。
2 类定义的格式
[标识符] class 类名 {
// 成员变量
// 成员方法
}
// 范例
public class Person {
String name;
int age;
public void show() {
System.out.println(name + " " + age);
}
}
3 类的使用
类定义完成之后,肯定无法直接使用。如果要使用,必须依靠对象,那么由于类属于引用数据类型,所以对象的产生格式(两种格式)如下:
// 声明并实例化对象
类名 对象名称 = new 类名称();
// 声明,然后实例化对象
类名 对象名称 = null;
对象名称 = new 类名称();
public class Phone {
String brand;
public void call() {
System.out.println("打电话");
}
}
// 创建对象
Phone p = new Phone();
// 使用成员变量
p.brand;
// 使用成员方法
p.call();
4 堆内存和栈内存
4.1 堆内存
保存对象的属性内容。堆内存需要用new关键字来分配空间。任何情况下,只要看见关键字new,都表示要分配新的堆内存空间,一旦堆内存空间分配了,里面就会有类中定义的属性,并且属性内容都是其对应数据类型的默认值。
4.2 栈内存
基本类型(int、short、long、byte、float、double、boolean、char)、对象句柄
优点:存取速度比堆内存快,仅次于寄存器;数据可以共享
缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性
5 成员变量和局部变量的区别
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置 | 类中方法外 | 方法内或者方法声明上 |
内存中位置 | 堆内存 | 栈内存 |
生命周期 | 与对象一起存在消亡 | 调用存在,完毕消失 |
初始值 | 有默认的初始值 | 没有初始值,必须先定义赋值,然后才能使用 |
6 this关键字
### 6.1 定义:this关键字指向的是当前对象的引用
6.2 作用:
- this.成员变量,指的是访问类中的成员变量,用来区分成员变量和局部变量(重名问题)
- this.方法名称,用来访问奔雷的成员方法。this()访问本类的构造方法,只能用在构造方法中,必须是构造方法第一条语句
- 当需要返回当前对象的引用时,就常常在方法写return this
7 封装
应用private修饰成员变量,隐藏对象的成员变量,外界无法直接操作,可以通过getXxx()/setXxx(),从而提高代码的安全性和复用性
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
8 构造方法
构造方法是一种特殊的方法
作用:创建对象
public class 类名 {
修饰符 类名(参数)
}
功能:主要完成对象数据的初始化
8.1 构造方法注意事项
① 构造方法的创建
- 如果没有定义构造方法,系统将给出一个默认的无参的构造方法
- 如果定义了构造方法,系统将不再提供默认的构造方法
② 构造方法的重载
- 如果自定义了带参的构造方法,需要再使用无参的构造方法,就必须再写一个无参的构造方法
③ 推荐的使用方式
- 无论是否使用,都手工写无参的构造方法
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
9 继承
可以使得子类拥有父类的属性和行为,还可以在子类中重写、追加属性和行为。使用关键字extends
9.1 格式
格式:public class 子类名 extends 父类名 {}
范例:public class Son extends Father {}
父类,也被称为基类、超类;子类,也被称为派生类
9.2 优点
1、提高代码复用性(多个类相同的成员可以放到同一个类中)
2、提高代码维护性(成员需要修改,修改一处即可)
9.3 缺点
继承让类与类之间产生关系,增强了类的耦合性,当父类发生变化时,子类同样会发生变化
9.4 何时使用继承
- 继承体现的关系 is a
- 假设法:我有两个类A和B,如果他们满足A是B的一种(或B是A的一种),就说明他们存在继承关系,这个时候就可以考虑使用继承来体现,否则就不能滥用继承
- 举例:苹果和水果,猫和动物,男人和人
class Person {
}
class Man extends Person {
}
9.5 注意事项
1、Java中,只支持单继承,不支持多继承
2、Java类支持多层继承
10 super关键字
super代表父类的引用,用于访问父类的属性、方法(包括构造方法)
10.1 语法
访问父类的属性:super.属性名=值
访问父类的方法:super.方法(实参列表)
访问父类的构造:super(实参列表) // 必须在子类的构造器的第一句
10.2 使用场景
1、当子类需要显示调用父类的构造器时,则必须通过super关键字
2、当子类和父类成员重名时,为了访问父类的成员,则必须通过super关键字
10.3 注意事项
1、super的使用不限于直接父类
2、如果直接父类和间接父类都有相同成员,则默认访问到是直接父类,遵循就近原则
3、this(实参列表)和super(实参列表)不能同时出现在构造器中
10.4 this和super的对比
1、this:代表本类对象,可以访问本类的属性、方法(包括构造)。它的作用主要为了区分成员变量和局部变量,以及调用本类构造器。
2、通过this访问成员时,先从本类中查找,如果找不到,则从父类一直往上找。
3、super:代表父类引用,如果访问父类属性、方法(包括构造)。它的作用主要为了区分本类和父类的成员,以及调用父类构造器。
4、通过super访问成员时,先从直接父类查找,如果找不到,则从间接父类一直往上找。
11 方法重写
子类中出现和父类一样的方法声明
class Person {
public void eat() {
System.out.println("吃面条");
}
}
class Man extends Person {
// 注解帮助我们检查重写方法声明的准确性
@Override
public void eat() {
System.out.println("吃米饭");
}
}
11.1 注意事项
1、因为私有方法不能被继承,所以私有方法没有重写的概念
2、子类方法访问权限不能更低(public>protected>默认>private)
12 修饰符
12.1 权限修饰符
修饰符 | 同一个类中 | 同一个包中子类无关联 | 不同包的子类 | 不同包的无关联 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
12.2 状态修饰符
12.2.1 final(最终)
final关键字是最终的意思,可以修饰成员方法、成员变量、类
修饰的方法:表示该方法是最终的方法,不能被重写
修饰的变量:表明该变量是常量,不能被再次赋值
修饰的类:表明该类是最终的类,不能被继承
final class Person {
public final String name = "buddha";
public final void eat() {
System.out.println("吃面条");
}
}
final修饰基本数据类型的局部变量,其数据值不能再发生改变
final修饰引用数据类型的局部变量,其地址值不能再发生改变
12.2.2 static(静止)
static关键字是最终的意思,可以修饰成员方法、成员变量
修饰的变量:该变量的数据就是一个共享的数据
public class Demo {
public static void main(String[] args) {
// 对象名.属性名
Person p = new Person();
System.out.println(p.name);
// 类名.属性名(推荐)
System.out.println(Person.name);
}
}
class Person {
public static String name = "buddha";
}
修饰的方法:独立于对象实例,被所有实例所共享使用
public class Demo {
public static void main(String[] args) {
// 对象名.方法名
Person p = new Person();
p.eat();
// 类名.方法名(推荐)
Person.eat();
}
}
class Person {
public static void eat() {
System.out.println("吃米饭");
}
}
static访问特点:静态成员方法只能访问静态成员
非静态的成员方法
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问非静态的成员方法
静态的成员方法
- 能访问静态的成员变量
- 能访问静态的成员方法
13 多态
同一个接口,使用不同的实例而执行不同的操作
13.1 定义格式
父类类型 变量名 = new 子类类型()
13.2 多态特点
成员变量:编译看左边,执行看左边
成员方法:编译看左边,执行看右边
这个特点是因为:成员方法被重写,而成员变量没有被重写;使用多态后,父类引用变量调用方法时,会调用子类重写后的方法
13.3 实现多态的前提
1、有继承/实现关系
2、子类重写父类方法
- static方法,因为被static修饰的方法是属于类,而不属于实例
- final方法,因为被final修饰的方法无法被子类重写
- private的方法对于子类不可见;protected方法可以被重写,但是无法被外部引用
3、父类引用指向子类对象
13.4 多态转型
向上转型格式
父类类型 变量名 = new 子类类型()
适用场景:当不需要面对子类类型时
向下转型格式
子类类型 变量名 = (子类类型) 父类类型的变量
适用场景:当要使用子类特有功能时
14 抽象类
一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,则该类必须定义为抽象类
14.1 抽象类的特点
1、抽象类和抽象方法必须使用abstract关键字修饰
[修饰符] abstract class 类名{}
[修饰符] abstract 返回数据类型 方法名();
2、抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
3、抽象类不能实例化
4、抽象类的子类
- 要么重写抽象类中的所有抽象方法
- 要么是抽象类
14.2 抽象类的成员特点
1、成员变量:可以是变量,也可以是常量,abstract不能修饰成员变量
2、构造方法:有,用于子类访问父类数据的初始化
3、成员方法:既可以是抽象的,也可以是非抽象的
- 抽象方法:强制要求子类做的事情
- 非抽象方法:提高代码的复用性
15 接口
更加抽象的抽象类
15.1 接口的特点
1、接口用关键字interface修饰
public interface 接口名 {}
2、类实现接口用implements表示
public class 类名 implements 接口名 {}
3、接口不能实例化
4、接口的实例类
- 要么重写接口中所有的抽象方法
- 要么是抽象类
15.2 接口的成员特点
1、成员变量
- 只能是常量
- 默认修饰符:public static final
2、构造方法
- 接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在
- 一个类没有父类,默认继承自Object类
3、成员方法
- 只能是抽象方法
- 默认修饰符:public abstract
15.3 类、抽象类和接口的关系
1、类和类的关系
- 继承关系,只能单继承,但是可以多层继承
2、类和接口的关系
- 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
3、接口和接口的关系
- 继承关系,可以单继承,也可以多继承
15.4 抽象类和接口的区别
1、成员区别
- 抽象类:常量、变量、构造方法、抽象方法、非抽象方法
- 接口:常量、抽象方法
2、关系区别
- 类与类:单继承、多层继承
- 类与接口:单实现,多实现
- 接口和接口:单继承,多继承
设计理念
- 抽象类:对类抽象,包括属性和行为
- 接口:对行为抽象,主要是行为