【基础篇】面向对象基础小结

面向对象基础小结

面向对象和面向过程的区别

两者的主要区别在于解决问题的方式不同:

  • 面向过程:是把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题。
  • 面向对象:会先抽象出对象,然后用对象执行方法的方式解决问题。

面向对象开发的程序一般更易维护、易复用、易扩展。

求圆的面积和周长的示例

面向过程:

直接定义圆的半径,并使用该半径直接计算出圆的面积和周长(即将问题的过程拆分成了两个方法来解决)。

public class Main {
public static void main(String[] args) {
// 定义圆的半径
double radius = 3.0;
// 计算圆的面积和周长
double area = Math.PI * radius * radius;
double perimeter = 2 * Math.PI * radius;
// 输出圆的面积和周长
System.out.println("圆的面积为:" + area);
System.out.println("圆的周长为:" + perimeter);
}
}

面向对象:

定义一个 Circle 类来表示圆(即先抽象出一个对象),该类包含了圆的半径属性和计算面积、周长的方法(用对象的方法解决问题)。

public class Circle {
// 定义圆的半径
private double radius;
// 构造函数
public Circle(double radius) {
this.radius = radius;
}
// 计算圆的面积
public double getArea() {
return Math.PI * radius * radius;
}
// 计算圆的周长
public double getPerimeter() {
return 2 * Math.PI * radius;
}
public static void main(String[] args) {
// 创建一个半径为3的圆
Circle circle = new Circle(3.0);
// 输出圆的面积和周长
System.out.println("圆的面积为:" + circle.getArea());
System.out.println("圆的周长为:" + circle.getPerimeter());
}
}

创建一个对象用什么运算符?对象实体与对象引用有何不同?

new 运算符。

  • new 创建对象实例(对象实例在堆内存中),
  • 对象引用指向对象实例(对象引用存放在栈内存中)。
  • 一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)
  • 一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球)

对象的相等和引用相等的区别

  • 对象的相等一般比较的是内存中存放的内容是否相等。
  • 引用相等一般比较的是他们指向的内存地址是否相等。
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
// 使用 == 比较字符串的引用相等
System.out.println(str1 == str2); // false -- 一个在常量池中,一个在堆内存中
System.out.println(str1 == str3); // true -- 都在常量池中
// 使用 equals 方法比较字符串的相等
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true

构造方法有哪些特点?是否可被 override?

构造方法特点如下:

  • 名字与类名相同。
  • 没有返回值,但不能用 void 声明构造函数。
  • 生成类的对象时自动执行,无需调用。
public class Person {
private String name;
private int age;
// 构造方法没有返回值,并且不能用void声明构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
public static void main(String[] args) {
// 生成对象时自动执行构造方法
Person person = new Person("John", 25);
person.display();
}
}

构造方法不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况

面向对象三大特征

面向对象编程的三大特征是:封装、继承和多态。

  1. 封装(Encapsulation):封装是将对象的属性和方法组合在一起,形成一个独立的、自包含的整体,对外部隐藏对象的内部细节,只向外部提供公共接口(方法),以便外部的代码能够通过这些接口访问对象。封装可以提高代码的可维护性和重用性,同时也可以保护对象的数据安全。

    // 例如 封装一个实体类
    public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }
    public String getName() {
    return name;
    }
    public int getAge() {
    return age;
    }
    public void setName(String name) {
    this.name = name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    }
  2. 继承(Inheritance):继承是指在已有类的基础上,创建一个新的类,并且让新类拥有已有类的属性和方法。被继承的类称为父类或基类,继承的类称为子类或派生类。子类可以在不重复编写代码的情况下,拥有父类的公共属性和方法,同时还可以增加自己的属性和方法,以实现更加复杂的功能。

    // 继承上面那个父类,下面这个是子类
    public class Student extends Person {
    private int grade;
    public Student(String name, int age, int grade) {
    super(name, age);
    this.grade = grade;
    }
    public int getGrade() {
    return grade;
    }
    public void setGrade(int grade) {
    this.grade = grade;
    }
    }
  3. 多态(Polymorphism):多态是指同一个方法调用,由于对象不同可能会产生不同的行为。多态可以让不同的对象对同一个消息做出不同的响应,从而提高代码的灵活性和可扩展性。多态有两种实现方式:静态多态(重载)和动态多态(重写和接口实现)。

    • 在 Java 中,多态的实现主要依赖于两个机制:继承和方法重写

    • 调用子类中重写的 move() 方法,从而产生不同的行为。这就是多态的体现。

    // 多态示例代码
    public class Animal {
    public void move() {
    System.out.println("Animal move");
    }
    }
    public class Dog extends Animal {
    public void move() {
    System.out.println("Dog move");
    }
    }
    public class Cat extends Animal {
    public void move() {
    System.out.println("Cat move");
    }
    }
    public class Main {
    public static void main(String[] args) {
    Animal a1 = new Animal();
    Animal a2 = new Dog(); // 使用子类对象替换父类对象
    Animal a3 = new Cat(); // 使用子类对象替换父类对象
    a1.move();
    a2.move();
    a3.move();
    }
    }

注意,三个对象指定的都是 父类(Animal)

关于继承如下 3 点需要记住:

  1. 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有
  2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。

子类无法直接访问父类的私有属性和方法

class ParentClass {
private String privateProperty = "Private property";
public void publicMethod() {
System.out.println("Public method");
}
private void privateMethod() {
System.out.println("Private method");
}
}
class ChildClass extends ParentClass {
public void childMethod() {
System.out.println("Child method");
System.out.println(publicProperty); // 子类可以访问父类的公有属性
publicMethod(); // 子类可以调用父类的公有方法
// 子类无法访问父类的私有属性和私有方法
// System.out.println(privateProperty); // 这行代码会报错
// privateMethod(); // 这行代码会报错
}
}
public class Main {
public static void main(String[] args) {
// 创建子类对象
ChildClass child = new ChildClass();
// 子类对象可以访问和调用父类的公有属性和方法
System.out.println(child.publicProperty);
child.publicMethod();
}
}

子类可以间接访问父类的私有成员 – 所以说拥有

class ParentClass {
private String privateProperty = "Private property";
private void privateMethod() {
System.out.println("Private method");
}
public void accessPrivateMembers() {
System.out.println(privateProperty); // 子类间接访问父类的私有属性
privateMethod(); // 子类间接调用父类的私有方法
}
}
class ChildClass extends ParentClass {
// 子类继承了父类的私有属性和私有方法,但无法直接访问
public void accessParentPrivateMembers() {
accessPrivateMembers(); // 子类间接访问父类的私有成员
}
}
public class Main {
public static void main(String[] args) {
ChildClass child = new ChildClass();
child.accessParentPrivateMembers();
}
}

多态的特点:

  • 对象类型(父类)和引用类型(子类)之间具有继承(类)/实现(接口)的关系;
  • 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
  • 多态不能调用“只在子类存在但在父类不存在”的方法;(多态指向的都是父类)
  • 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。

接口和抽象类有什么共同点和区别?

interfaceabstract

共同点

  • 都不能被实例化。
  • 都可以包含抽象方法。
  • 都可以有默认实现的方法(Java 8 可以用 default 关键字在接口中定义默认方法)。

区别

  • 【接口】主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。【抽象类】主要用于代码复用,强调的是所属关系。
  • 一个类只能继承一个类,但是可以实现多个接口。
  • 【接口】中的成员变量只能是 public static final 类型的,不能被修改且必须有初始值,而【抽象类】的成员变量默认 default,可在子类中被重新定义,也可被重新赋值。
// 定义一个接口
public interface Animal {
public void eat();
}
// 定义一个抽象类
public abstract class Vehicle {
private int speed;
public void setSpeed(int speed) {
this.speed = speed;
}
public int getSpeed() {
return speed;
}
public abstract void run(); // 抽象方法
}
// 实现接口
public class Dog implements Animal {
public void eat() {
System.out.println("The dog is eating.");
}
}
// 继承抽象类
public class Car extends Vehicle {
public void run() {
System.out.println("The car is running.");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 使用接口
Animal animal = new Dog();
animal.eat(); // The dog is eating.
// 使用抽象类
Vehicle vehicle = new Car();
vehicle.setSpeed(60);
System.out.println("The speed of the car is " + vehicle.getSpeed() + " km/h."); // The speed of the car is 60 km/h.
vehicle.run(); // The car is running.
}
}

深拷贝和浅拷贝的区别了解吗?什么是引用拷贝?

【深拷贝】会完全复制整个对象,会在堆上新创建一个地址(原对象的内部对象 Address);

而【浅拷贝】只会在堆上新创建一个对象,但是内部地址还是原对象的,与原对象共用一个 Address 对象。

【引用拷贝】不会创建一个新的对象,而只是单纯的引用堆里面的原对象。

System.out.println("The speed of the car is " + vehicle.getSpeed() + " km/h."); // The speed of the car is 60 km/h.
vehicle.run(); // The car is running.
}
}

深拷贝和浅拷贝的区别了解吗?什么是引用拷贝?

【深拷贝】会完全复制整个对象,会在堆上新创建一个地址(原对象的内部对象 Address);

而【浅拷贝】只会在堆上新创建一个对象,但是内部地址还是原对象的,与原对象共用一个 Address 对象。

【引用拷贝】不会创建一个新的对象,而只是单纯的引用堆里面的原对象。
在这里插入图片描述

学习参考

Java基础常见面试题总结(中) | JavaGuide(Java面试 + 学习指南)

posted @   cmty  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示