OnJava(一)

本文最后更新于 2 年前,文中所描述的信息可能已发生改变。

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

面向对象编程(OOP)

  1. 以对象为中心:将现实世界的事物(问题)进行建模,即抽象,将复杂的问题分解为对象,每个对象拥有自己的属性和行为,最终通过对象之间通过协作解决问题。
  2. 封装性:通过封装将数据和方法封装在对象内部,对象对外部提供公共接口进行交互,隐藏内部实现细节。
  3. 继承性:通过继承实现代码的重用和扩展,子类可以继承父类的属性和方法,并可以添加自己的特定实现。
  4. 多态性:同一个方法在不同的对象上可以有不同的实现,提供更灵活的编程方式。 重点在于对象的设计和关系,强调模块化和可维护性。

面向过程编程

  1. 以过程为中心:将问题分解为一系列的步骤和函数,通过按顺序执行这些步骤来解决问题。
  2. 以数据为重点:将数据和操作数据的函数分离,通过函数对数据进行处理和操作。
  3. 自顶向下的设计思路:问题的解决从上到下,逐步细化,最后得到具体的实现。
  4. 强调算法和步骤的设计,关注问题的解决过程和流程。

在实践中,面向对象编程通常用于处理较大规模和复杂度较高的项目,通过封装、继承和多态性等特性,可以更好地组织和管理代码。面向过程编程更适用于简单和较小规模的问题,强调问题的解决过程和流程。

二、访问控制符

修饰符同一个类同一个包不同包的子类全范围
private
default
protected
public

终结:private仅自己可见,default包可见,protected子类可见,public随便见

三、static和this的作用

用于修饰类的成员(字段、方法、代码块和内部类),其作用是使成员与类关联而不是与类的实例(对象)关联。下面是static 的主要作用:

  1. 静态字段(Static Fields): 静态字段是属于类的字段,而不是属于类的每个实例的字段。 所有类的实例共享相同的静态字段的值。 可以通过类名直接访问静态字段,无需实例化对象。

  2. 静态方法(Static Methods): 静态方法是属于类的方法,而不是属于类的实例的方法。 可以通过类名直接调用静态方法,无需实例化对象。 静态方法只能直接访问静态字段和调用其他静态方法,不能直接访问非静态字段和调用非静态方法。

  3. 静态代码块(Static Blocks): 静态代码块是在类被加载时执行的代码块,用于初始化静态字段或执行其他静态操作。 静态代码块只在类加载时执行一次。

  4. 静态内部类(Static Inner Classes): 静态内部类是嵌套在其他类中的类,使用 static 修饰。 静态内部类可以直接访问外部类的静态字段和方法,而不需要外部类的实例。 需要注意的是,static 成员在内存中只有一份副本,并且可以通过类名访问,因此适用于与类相关而不是与对象实例相关的属性和方法。使用静态成员可以节省内存空间,并且在某些情况下提供更方便的访问方式。

然而,过度使用静态成员可能会导致代码的耦合性增加和可测试性降低,因此需要谨慎使用。一般来说,静态成员适用于那些在整个应用程序中都具有相同状态或行为的成员,而非依赖于特定对象实例的成员。

this代表当前对象的引用。它主要有以下几个作用:

  1. 引用当前对象: 在实例方法中,this 可以用于引用当前正在调用该方法的对象。 在构造方法中,this 可以用于引用当前正在创建的对象。

  2. 解决命名冲突: 当方法或构造方法的参数与类的字段名相同时,可以使用 this 关键字来区分它们。 通过 this.fieldName 可以访问当前对象的字段,而不是参数。

  3. 调用其他构造方法: 在一个构造方法中,可以使用 this() 来调用同一类中的其他构造方法。 这种方式允许在一个构造方法中重用代码,并在初始化过程中提供不同的参数组合。

  4. 传递对象给其他方法或构造方法: 可以使用 this 关键字将当前对象作为参数传递给其他方法或构造方法。 需要注意的是,this 关键字只能在非静态的方法和构造方法中使用,因为它代表的是当前对象的引用,而静态方法没有隶属于具体对象的概念。

通过使用 this 关键字,可以引用当前对象、解决命名冲突、调用其他构造方法以及传递对象给其他方法,提高代码的可读性和灵活性。

四、面向接口编程与面向切面编程

面向接口编程是指将程序设计的重点放在接口上,而不是具体的实现类。它强调使用接口作为交互的协议,通过定义接口来描述类之间的协作关系,而不关心具体的实现细节。面向接口编程有助于实现松耦合的代码结构,提高代码的可扩展性和可维护性。通过面向接口编程,我们可以定义通用的接口,并通过不同的实现类来实现不同的行为。例如:

java
public interface Animal {
    void sound();
}

public class Cat implements Animal {
    public void sound() {
        System.out.println("Meow");
    }
}

public class Dog implements Animal {
    public void sound() {
        System.out.println("Woof");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal cat = new Cat();
        Animal dog = new Dog();

        cat.sound();  // Output: Meow
        dog.sound();  // Output: Woof
    }
}

在上面的例子中,Animal 接口定义了动物的行为,Cat 和 Dog 类分别实现了 Animal 接口,并提供了各自的实现。通过面向接口编程,我们可以使用统一的 Animal 接口引用不同的实现类对象,实现了对具体实现的解耦。

面向切面编程(Aspect-Oriented Programming): 面向切面编程是一种用于处理横切关注点(Cross-Cutting Concerns)的编程范式。横切关注点是指在程序中多个模块中重复出现的功能或逻辑,如日志记录、事务管理、权限控制等。面向切面编程通过将横切关注点从核心业务逻辑中剥离出来,形成可重用的模块,以便在需要的地方进行调用,从而提高代码的可维护性和复用性。面向切面编程通常使用切面(Aspect)来描述横切关注点,并使用切点(Pointcut)来定义在哪些位置应用切面的逻辑。

当在多个方法执行的前后总是要执行同一种操作逻辑时就可使用此方法将这部分逻辑剥离出来,从而达到代码复用的目的

五、异常的分类

分为受检异常非受检异常

  1. 受检异常: 编译时检查,必须处理或抛出,否则编译不通过 通常为Exception但不包括RuntimeException及其子类 示例:IOException、ClassNotFoundException、SQLException 等。
  2. 非受检异常: 运行时检查,没有强制处理的要求 一般由于逻辑错误引起 Unchecked Exception 的直接子类是 RuntimeException。 示例:NullPointerException、ArrayIndexOutOfBoundsException、IllegalArgumentException 等。

六、泛型的作用

它的作用是在编译时提供类型安全和参数化类型的支持。通过使用泛型,可以在编写代码时指定类、接口或方法的参数类型,从而实现更加灵活和安全的代码。

  1. 类型安全:泛型可以在编译时检查类型的一致性,避免了在运行时出现类型转换错误。通过指定参数类型,可以确保只有兼容的类型被使用,减少了程序中的类型错误。

  2. 代码复用:通过使用泛型,可以编写可重用的代码,减少了代码的重复性。可以定义通用的类、接口或方法,能够适应不同类型的数据。

  3. 避免类型转换:使用泛型可以避免手动进行类型转换的繁琐过程。在使用泛型集合类时,可以直接获取到指定类型的数据,无需手动进行类型转换。

  4. 提高代码可读性和可维护性:泛型可以提供更加清晰和易于理解的代码结构。通过在代码中使用泛型,可以清楚地指定数据类型的意图,使代码更易于阅读和维护。

java
public class MyList<T> {
    private T[] elements;
    private int size;

    public MyList(int capacity) {
        elements = (T[]) new Object[capacity];
        size = 0;
    }

    public void add(T element) {
        elements[size] = element;
        size++;
    }

    public T get(int index) {
        return elements[index];
    }

    public int size() {
        return size;
    }
}

public class Main {
    public static void main(String[] args) {
        MyList<Integer> list = new MyList<>(5);
        list.add(1);
        list.add(2);
        list.add(3);

        System.out.println("Size: " + list.size());
        System.out.println("Element at index 1: " + list.get(1));
    }
}

在上面的例子中,MyList 类使用泛型 <T> 定义了一个通用的列表类。通过在实例化时指定具体的类型参数,如 MyList<Integer>,可以创建一个整数类型的列表。这样可以避免手动进行类型转换,并且能够在编译时检查类型的一致性。

函数式接口——Java
SmallRye Mutiny(响应式编程库)