说明:与以下内容有关联
JVM_基础关键https://mp.youkuaiyun.com/mp_blog/creation/editor/145076828
目 录
一、面向过程与面向对象
1.面向过程(PO)
- 关注于进行的步骤;
- 代表语言:C ;
- 适用于处理流程简单的问题。
2.面向对象(OO)
- 关注于参与的对象;
- 代表语言:Java、Python、C# ;
- 更符合人类对于世界的认知,易于处理复杂问题;
- 高内聚,低耦合,易于扩展;
- 内容:OOA(面向对象分析)、OOD(面向对象设计)、OOP(面向对象编程);
- 三大特征:封装性、继承性、多态性。
二、 类与对象
1.类
- 将事物之间共同特征提取出来,形成一个类;
- 属性描述状态;
- 方法描述行为;
- 类就是属性和方法的集合。
2.对象
- 对象又称为实例,是实际存在的个体;
- 一个类可以创造多个对象。
3.实例
public class Phone {
String brand; // 手机品牌
double price; // 手机价格
String color; // 手机颜色
}
public class PhoneTest {
public static void main(String[] args) {
Phone phone1 = new Phone();
phone1.brand = "华为";
phone1.color = "黑色";
phone1.price = 5999.0;
System.out.println("手机品牌:" + phone1.brand);
System.out.println("手机颜色:" + phone1.color);
System.out.println("手机价格:" + phone1.price);
System.out.println("================");
Phone phone2 = new Phone();
phone2.brand = "荣耀";
phone2.color = "灰色";
phone2.price = 4999.0;
System.out.println("手机品牌:" + phone2.brand);
System.out.println("手机颜色:" + phone2.color);
System.out.println("手机价格:" + phone2.price);
}
}
三、封装性
1.什么是封装
将数据和方法包装到一个类中,隐藏了内部具体的实现细节,向外界提供有限的访问接口,以此实现对对象的保护和隔离,一定程度上保证了数据安全,同时提高了代码的可复用性和可维护性。
2.过程
- 属性私有化,即修饰符使用 private ,可以禁止外部程序对该属性随意访问,只能在本类中访问;
- 对外提供公开访问入口(getter、setter 方法),为保证外部程序仍然可以读取、修改该属性值。
3.实例
public class Animals {
private String name;
private String birth;
private char sex;
private int age;
public String getName() {
return name;
}
public String getBirth() {
return birth;
}
public char getSex() {
return sex;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setBirth(String birth) {
this.birth = birth;
}
public void setSex(char sex) {
this.sex = sex;
}
public void setAge(int age) {
this.age = age;
}
}
public class AnimalsTest {
public static void main(String[] args) {
Animals cat = new Animals();
cat.setName("小花");
cat.setBirth("2024-01-12");
cat.setSex('母');
cat.setAge(1);
System.out.println("宠物名称:"+cat.getName());
System.out.println("宠物生日:"+cat.getBirth());
System.out.println("宠物性别:"+cat.getSex());
System.out.println("宠物年龄:"+cat.getAge());
}
}
四、构造方法
1.作用(执行的两个阶段)
- 通过调用构造方法完成对象的创建;
- 为对象所有属性赋值,即对象初始化。
2.定义语法
[ 修饰符 ] 构造方法名(=类名)(形参列表){
// 构造方法体;
}
3.说明
- 构造方法名必须与类名一致;
- 使用 new 运算符调用构造方法;
- 构造方法无需提供返回值类型;
- 构造方法执行完毕,自动将创建的对象的内存地址返回;
- 当类中未显示定义构造方法,系统默认提供无参构造方法。若显示定义,则不再自动提供;
- 无参构造方法没有手动为属性赋值,则系统赋予默认值;
- 一个类可以定义多个构造方法,且自动构成方法重载;
- 使用 new 运算符完成创建对象,执行完构造方法完成初始化。也就是说,构造方法执行前,就完成了创建对象。
4.构造代码块
- 语法:在类体中使用 “ { } ” 构造代码块;
- 无需手动调用,在执行构造方法前执行一次构造代码块;
- 在执行构造代码块之前,就已完成对象创建;
- 作用:可以在不同的构造方法初始实现代码复用。
五、static 关键字
1.说明
- static 修饰的变量叫静态变量,static 修饰的方法叫静态方法;
- 在 static 修饰的情况下,采用【 类名. 】的方式访问,无需 new 对象;
- 对象级别的属性,通常定义为实例变量,一个对象占一个空间;
- 类级别的属性(所有对象都有该属性,且属性值相同),应该定义为静态变量,只占一个内存空间;
- 在 jdk 8 之后,静态变量存储在堆内存中,并在类加载时初始化;
- 静态方法中不可出现 this 关键字,因为 this 代表的是当前对象,而 static 方法中没有当前对象,所以无法直接调用实例方法、访问实例变量;
- 静态代码块语法:“ static { …… } ” ;
- 静态代码块在类加载时执行,且只执行一次;
- 一个类可以有多个静态代码块,遵循自顶向下依次执行原则;
- 若需要在类加载时刻执行部分代码,可以使用静态代码块。
2.实例
public class DoingNow {
public static void main(String[] args) {
DoingNow d = new DoingNow();
d.test1(); // 访问实例方法
DoingNow.test2(); // 访问静态方法
System.out.println(d.n1); // 访问实例变量
System.out.println(DoingNow.n2); // 访问静态变量
System.out.println("==========");
d.doSomething();
}
// 实例方法
public void test1() {
System.out.println("test1");
}
// 静态方法
public static void test2() {
System.out.println("test2");
}
// 实例变量
public String n1 = "n1";
// 静态变量
public static String n2 = "n2";
public void doSomething() {
this.test1(); // 访问实例方法
DoingNow.test2(); // 访问静态方法
System.out.println(this.n1); // 访问实例变量
System.out.println(DoingNow.n2); // 访问静态变量
}
}
六、继承性
1.说明
- 继承实现了代码复用、方法覆盖和多态;
- 语法: [ 修饰符 ] class 子类名 extends 父类名 { …… } ;
- Java 只支持单继承,一个类只能直接继承一个类,但可以多重继承;
- 子类继承父类时,只有私有和构造方法不支持继承;
- Java 中没有显示的继承,则默认继承 Object 类。
2.方法覆盖(重写)
(1)回顾方法重载
在开始叙述方法重写时,先来回顾一下方法重载:
- 同一个类中,可以有多个同名方法,但需要保证参数列表 类型、顺序、个数 至少有一个不同;
- 编译阶段 会根据参数列表决定调用哪个同名方法;
- 优点:减少方法的记忆。
// 方法重载实例
public static void main(String[] args) {
oLoad(1, 2);
oLoad("a", "b");
}
public static void oLoad(int a, int b) {
System.out.println("a + b = " + a + b);
}
public static void oLoad(String a, String b) {
System.out.println("a + b = " + a + b);
}
(2)方法重写
- 继承父类中的方法,无法满足子类的需要,则要用到方法重写;
- 子类中将父类的方法重写后,在调用时执行重写后的方法;
- 具有继承关系的父子类之间,有相同的 方法名、返回值类型、形参列表,可以进行方法重写;
- Java 中使用【 @Override 】注解,可以在编译时检查该方法是否是父类方法的重写,且只在编译阶段有效,与运行阶段无关;
- 若返回值类型是引用数据类型,则该返回值类型可以是原类型的子类型;
- 访问权限不可以变低;
- 抛出异常不可以变多;
- 由于私有方法和构造方法不支持继承,所以不可以方法重写;
- 方法重写针对实例方法,与实例变量和静态方法无关。
七、多态性
1.转型
(1)向上转型
- 有继承关系的两个类,子类型转换为父类型;
- 类似于基本数据类型的自动类型转换;
- 以下展示一个向上转型的实例,解释了为什么称之为多态,实际上是编译形态和运行形态;
public class Animal {
public void eat() {
System.out.println("Animal 正在吃");
}
public void play() {
System.out.println("Animal 正在玩");
}
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("Cat 正在吃");
}
@Override
public void play() {
System.out.println("Cat 正在玩");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("Dog 正在吃");
}
@Override
public void play() {
System.out.println("Dog 正在玩");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat();
animal.play();
System.out.println("========");
Animal cat = new Cat();
cat.eat();
cat.play();
System.out.println("========");
Animal dog = new Dog();
dog.eat();
dog.play();
}
}
- 编译阶段:编译器在 Animal 类中寻找 eat()方法和 play()方法,发生静态绑定,若成功则编译通过;
- 运行阶段:在 cat 和 dog 引用 中,堆内存存储的真正对象分别是 Cat 类型和 Dog 类型,所以是由 Cat 和 Dog 对象发生 eat 行为和 play 行为,发生动态绑定。
(2)向下转型
- 有继承关系的两个类,父类型转换为子类型;
- 类似于基本数据类型的强制类型转换;
- 当调用的方法是子类特有的(父类没有),则需要向下转型;
- 在向下转型时,为避免出现 ClassCastException 异常,建议先使用 instanceof 运算符验证;
- instanceof 运算符语法:(引用 instanceof 类型);
- instanceof 运算符结果是 true 或 false;
public class Animal {
public void eat() {
System.out.println("Animal 正在吃");
}
public void play() {
System.out.println("Animal 正在玩");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("Cat 正在吃");
}
@Override
public void play() {
System.out.println("Cat 正在玩");
}
public void catchMouse() {
System.out.println("Cat 正在抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("Dog 正在吃");
}
@Override
public void play() {
System.out.println("Dog 正在玩");
}
}
public class Test {
public static void main(String[] args) {
Animal cat = new Cat();
cat.eat();
cat.play();
System.out.println("=======");
Animal dog = new Dog();
dog.eat();
dog.play();
System.out.println("=======");
if (cat instanceof Cat) {
Cat cat2 = (Cat) cat;
cat2.catchMouse();
} else {
System.out.println(cat + "不是猫");
}
if (dog instanceof Cat) {
Cat dog2 = (Cat) dog;
dog2.catchMouse();
} else {
System.out.println(dog + "不是猫");
}
}
}
2.多态
- 使用多态可以满足设计模式的 OCP(开放封闭原则);
- 软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。OCP 要求软件实体应该是可扩展,而不可修改的;
- 方法重载、方法重写、向上转型、向下转型都属于多态;
- 多态可以降低耦合,提高扩展能力。
public class Animal {
public void eat() {
System.out.println("Animal 正在吃");
}
public void play() {
System.out.println("Animal 正在玩");
}
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("Cat 正在吃");
}
@Override
public void play() {
System.out.println("Cat 正在玩");
}
public void catchMouse() {
System.out.println("Cat 正在抓老鼠");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("Dog 正在吃");
}
@Override
public void play() {
System.out.println("Dog 正在玩");
}
}
public class Person {
public void dosome(Animal animal) {
animal.eat();
animal.play();
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
Person person = new Person();
person.dosome(cat);
person.dosome(dog);
}
}
八、super 关键字
1.回顾 this 关键字
- this 存在于该方法栈帧中局部变量表的0号槽位;
- 本质是引用;
- 保存的是当前对象的内存地址;
- 多数情况下可省略,但在区分局部变量和实例变量时不可省;
- 不能在静态上下文中使用,因为 this 代表的是当前对象,而 static 方法中没有当前对象;
- 通过【 this(实参)】可以在构造方法中调用本类其他的构造方法,以此实现代码复用,且只能出现在构造方法的第一行。
2. super 关键字
- this 保存的是当前对象的内存地址,而 super 代表的是当前对象的父类型特征;
- 不能在静态上下文中使用 super ;
- 当父类中有与子类相同的属性和方法时,super 关键字不可以省略;
- 通过子类的构造方法调用父类的构造方法,可以实现代码的复用,目的是为所继承的父类型特征初始化;
- 若子类的构造方法首行没有显示的写明 super()或 this(),则系统会默认调用 super();
- 【 super(实参)】只能出现在构造方法的第一行;
九、final 关键字
- final 修饰的类不能被继承;
- final 修饰的方法不能被重写;
- final 修饰的变量一旦赋值,不能被再次赋值;
- final 修饰的实例变量必须在构造方法执行结束前手动赋值;
- final 与 static 共同使用所修饰的实例变量是常量,语法如下例;
- final 修饰引用,一旦指向一个对象,则不可以指向其他对象,但所指向的对象内部的数据可以修改。
// 常量的定义
public static final int ERROR_NOT_FOUND = 404;
public static final int ERROR_SERVER = 500;