前言:
面向对象的本质:以类的方式组织代码,以对象的方式(组织)封装数据
定义:类是一种抽象的数据类型,类是对象的模板,定义对象的(静态的)属性和(动态的)行为。
public class Person {
// 属性(字段)(成员变量)
String name;
int age;
// 方法
void speak() {
System.out.println("I'm " + name);
}
}
// 创建对象(类实例化后会返回一个自己类型的对象)
// p1就是Person类的一个实例
Person p1 = new Person(); // 使用 new 关键字创建对象,堆内存分配空间
p1.name = "Alice"; // 属性赋值
p1.speak(); // 方法调用
内存模型:
栈内存(p1) → 堆内存(Person实例)
├─ name: "Alice"
└─ age: 0
分析:栈(Stack)内存放的变量引用名,堆(Heap)内存放的是实际的对象属性值和方法。
Ps:多个引用变量可以指向同一个对象。
示例:Person p2 = p1; // p2 和 p1 指向同一对象
public class Student {
String id;
// 默认构造器(无参)
public Student() {
this.id = "0000"; // this指代当前对象,实例化初始值
}
// 带参构造器(重载),构造器支撑重载
public Student(String id) {
this(); // 调用无参构造器(必须首行)
this.id = id;
}
}
定义: 构造器用于创建对象时 初始化,与类同名,无返回值
关键规则:
this()
必须放在构造器首行public class Person {
String name;
int age;
public Person() {
this("Unknown", 0); // 调用另一个构造器
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
分析:
this()
,但必须放在第一行定义: 封装 是面向对象的基本原则,目的是保护数据,防止外部直接访问。
修饰符 | 类内 | 同包 | 子类 | 任意位置 |
---|---|---|---|---|
private | ✓ | ✗ | ✗ | ✗ |
default | ✓ | ✓ | ✗ | ✗ |
protected | ✓ | ✓ | ✓ | ✗ |
public | ✓ | ✓ | ✓ | ✓ |
public class User {
//使用 private 限制访问,确保属性(字段)只能在类内访问,也可以避免被直接修改
private final String id; //final 修饰不变对象,让变量不可变,提升线程安全
private String username;
private String password;
// 提供公共方法
// 使用 getter 和 setter 方法,初始化/获取变量方法
public String getUsername() {
return username;
}
public void setUsername(String name) {
this.username = name;
}
// 其他方法...
}
封装优势:
定义: 继承使得子类复用父类的属性和方法,使用 extends 关键字。
//父类
class Animal {
String name;
public Animal(){
System.out.println("Aniaml 无参构造执行");
}
void eat() {
System.out.println("Eating...");
}
}
//子类(派生类)Dog,继承父类(基类)的name属性和eat方法
class Dog extends Animal { // 单继承
public Dog(){
//隐藏代码:调用了父类的无参构造
super();
Sywtem.out.println("Dog 无参构造执行");
}
void bark() {
System.out.println("Woof!");
}
}
public class InheritanceDemo {
public static void main(String[] args){
Dog dog = new Dog(); //自动调用构造器
dog.name = "Buddy";
dog.eat(); // 继承自 Animal
dog.bark(); // Dog 自己的方法
}
}
输出:
Aniaml 无参构造执行
Dog 无参构造执行
Eating…
Woof!
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类构造方法
}
}
-调用父类方法
class Parent {
int value = 10;
void show() {
System.out.println("Parent");
}
}
class Child extends Parent {
int value = 20;
@Override
void show() {
System.out.println(this.value); //访问该对象字段(20)
System.out.println(super.value); // 访问父类字段(10)
super.show(); // 调用父类方法
}
}
继承限制:
super规则:
super()
必须是第一行。(隐藏默认调用父类无参构造器)重写要求:
class Shape {
public void draw() {
System.out.println("Drawing shape");
}
}
class Circle extends Shape {
@Override // 注解
public void draw() {
System.out.println("Drawing circle");
}
//如果可以,优先使用 super.method() 复用父类逻辑,减少代码重复。
}
ps:
以上方法为非静态方法,若以父类引用指向子类
Shape s=new Circle();(子类的构造方法)
s.draw();
非静态方法调用的是对象的方法,输出Drawing circle。
但如果使用static修饰静态方法,静态方法是同类加载的,调用的是类的方法,输出Drawing shape
@Override作用:
作用:
使用场景:
super(...)
调用父类构造方法,必须位于构造器的第一行。示例:
class Parent {
public int value = 10;
public Parent(String msg) {
System.out.println("Parent constructor: " + msg);
}
public void show() {
System.out.println("Parent show");
}
}
class Child extends Parent {
public int value = 20;
public Child(String msg) {
super(msg); // 调用父类构造器,必须是第一行
System.out.println("Child constructor: " + msg);
}
@Override
public void show() {
super.show(); // 调用父类方法
System.out.println("Child show");
}
public void display() {
System.out.println("Child value: " + this.value);
System.out.println("Parent value: " + super.value);
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child("Hello");
child.show();
child.display();
}
}
输出:
Parent constructor: Hello
Child constructor: Hello
Parent show
Child show
Child value: 20
Parent value: 10
作用:
使用场景:
this
表示当前对象的成员变量。this(...)
调用同类中其他构造器,必须是构造器中的第一行。示例:
class Person {
private String name;
private int age;
// 使用 this 调用其他构造器
public Person() {
this("Unknown", 0); // 调用带参构造器
}
public Person(String name, int age) {
// 使用 this 区分成员变量与局部变量
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("My name is " + this.name + ", age " + this.age);
}
}
public class Test {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person("Alice", 25);
p1.introduce();
p2.introduce();
}
}
输出:
My name is Unknown, age 0
My name is Alice, age 25
关键字 | 主要用途 | 使用位置 | 注意事项 |
---|---|---|---|
super | 访问父类成员,调用父类构造器 | 子类方法、构造器中 | 在构造器中,必须是第一行调用 |
this | 表示当前对象,访问本类成员;调用本类其他构造器 | 本类方法、构造器中 | 在构造器中,this() 调用也必须放在第一行 |
定义:
在同一个类中,方法名相同,但参数列表(参数个数或参数类型)不同。
重载体现的是 编译时多态性(静态绑定)。
特点:
返回类型无法决定是否重载
)示例:
public class Calculator {
// 加法重载
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
// 参数个数不同
public int add(int a, int b, int c) {
return a + b + c;
}
}
定义:
子类重写父类中已经存在的方法(方法名、参数列表必须一致),以提供新的实现。
重写体现的是 运行时多态性(动态绑定)。
特点:
@Override
注解,帮助编译器检测是否正确重写了父类方法。示例:
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog(); // 编译时为 Animal,但运行时为 Dog
animal.makeSound(); // 输出 "Bark",运行时调用子类的方法
}
}
特性 | 重载(Overload) | 重写(Override) |
---|---|---|
定义 | 同一类中方法名相同,参数列表不同 | 子类中方法名、参数列表与父类完全一致 |
多态性 | 编译时多态性(静态绑定) | 运行时多态性(动态绑定) |
返回类型 | 可相同也可不同 | 必须与父类方法相同或为其子类(协变返回类型) |
访问修饰符 | 与方法重载无直接关系 | 子类方法不能缩小父类方法的访问权限 |
注解 | 无特定要求 | 建议使用 @Override 注解 |
创建对象时的内存分配过程?
this和super能否同时出现?
以下代码输出什么?
class A {
int i = 10;
void print() { System.out.println(i); }
}
class B extends A {
int i = 20;
public static void main(String[] args) {
new B().print();
}
}
上文链接:https://blog.csdn.net/weixin_73492487/article/details/146284259