Java基础:面向对象(二)

Java基础:面向对象(二)


文章目录

  • Java基础:面向对象(二)
    • 1. 面向对象编程思想
    • 2. 类与对象
      • 2.1 类
        • 2.1.1 类的定义
        • 2.1.2 成员变量
        • 2.1.3 局部变量
      • 2.2 对象
        • 2.2.1 对象的定义
        • 2.2.2 对象的使用
        • 2.2.3 对象创建的原理
    • 3. 封装
    • 4. 构造方法
    • 5. 对象作为方法的参数或返回类型
    • 6. 对象数组
      • 6.1 声明数组变量
      • 6.2 创建数组对象
    • 7. static关键字
      • 7.1 static可以修饰属性
      • 7.2 static可以修饰方法
      • 7.3 static可以修饰代码块
      • 7.4 单例模式
        • 7.4.1 饿汉式单例模式
        • 7.4.2 懒汉式单例模式
    • 8. 使用访问修饰符实现封装
      • 8.1 包的概念
      • 8.2 导包操作
      • 8.3 静态导入
    • 9. 代码封装
    • 10. this关键字
    • 11. 继承关系
      • 11.1 继承的概念
      • 11.2 继承类型
      • 11.3 继承的特性
      • 11.4 子类实例化过程
      • 11.5 属性的隐藏
      • 11.6 方法重写(方法覆盖)
      • 11.7 抽象方法和抽象类
      • 11.8 final关键字的用法
    • 12. 多态
      • 12.1 多态的概念
      • 12.2 向上转型(上溯造型)
      • 12.3 向下转型(下溯造型)
      • 12.4 里式代换原则
      • 12.5 instanceof运算符
    • 13. 组合关系
    • 14. 接口
        • 14.1 接口的概念
        • 14.2 语法格式
        • 14.3 接口的应用
          • 14.3.1 接口的多态
          • 14.3.2 接口与抽象类
          • 14.3.3 简单工厂模式
          • 14.3.4 工厂方法模式
          • 14.3.5 缺省适配器模式
    • 15. 内部类
      • 15.1 简介
      • 15.2 分类
        • 15.2.1 成员内部类(普通内部类)
        • 15.2.2 静态内部类
        • 15.2.3 局部内部类
        • 15.2.4 匿名内部类


1. 面向对象编程思想

  • 面向对象分析(Object Oriented Analysis,OOA):面向对象分析是软件开发过程的第一步,它主要关注于对问题域的理解和分析。
  • 面向对象设计(Object Oriented Design,OOD):面向对象设计是在面向对象分析的基础上进行的,它主要关注于如何将分析阶段得到的需求转化为具体的设计。
  • 面向对象编程(Object-Oriented Programming,OOP):面向对象编程是面向对象软件开发的实现阶段,它主要关注于使用面向对象编程语言来实现设计阶段的成果。面向对象编程的主要特性包括封装性继承性多态性,这些特性有助于提高代码的可重用性、可维护性和可扩展性。

2. 类与对象

2.1 类

2.1.1 类的定义

在Java中,类(Class)是对象(Object)的模板,它定义了一类对象的属性和行为。类的定义格式如下:

[访问修饰符] class 类名{成员变量(属性);成员方法(行为);内部类;代码块;
}
2.1.2 成员变量

成员变量(包括实例变量和静态变量)是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。Java中类的成员变量都有默认值。例如,整数类型为0,浮点数类型为0.0,布尔类型为false,字符类型为'\u0000',引用类型为null

2.1.3 局部变量

方法体方法参数或者代码块中定义的变量被称为局部变量。局部变量没有默认值,声明和初始化都是在方法中,方法结束后,变量就会自动销毁。

:成员变量有默认值,局部变量没有默认值,产生的原因?

:成员变量和局部变量在默认值行为上的差异主要源于它们在生命周期、存储位置、作用域和初始化机制上的不同。以下是具体的原因:

  1. 生命周期
    成员变量:随着类的实例化或类的加载而被创建,并在类的实例或类本身被销毁时销毁。
    局部变量:在方法、构造函数或初始化块执行时创建,并在执行完毕后销毁。
  2. 存储位置
    成员变量:实例变量存储在堆内存中(随着对象的创建而分配),静态变量存储在方法区(也称为静态存储区或类变量区)。
    局部变量:存储在栈内存中,每个方法执行时都会在栈内存中创建一个栈帧,局部变量就存储在这个栈帧中。
  3. 作用域
    成员变量:可以在类的任何方法中访问(对于实例变量)或在类的外部通过类的实例或类名(对于静态变量)访问。
    局部变量:只能在声明它们的方法、构造函数或初始化块内部访问。
  4. 初始化
    成员变量:如果没有显式地初始化,Java在创建类的实例或JVM(Java虚拟机)类加载时,会自动为成员变量赋予默认值。
    局部变量:使用前必须显式初始化,否则编译时会出现错误。

2.2 对象

2.2.1 对象的定义

对象是类的一个实例,有状态和行为。类和对象的关系,就是抽象和具体的关系。创建对象的基本语法格式如下:

类名 对象名 = new 类名();

实例化对象

2.2.2 对象的使用

调用对象的属性和方法,如果是在当前类中,可以直接访问属性和方法。如果在其他类中,通过点.运算符来访问其属性和方法。例如,如果有一个名为Person的类,需要创建per1per2per3三个对象,使用setget方法对属性进行赋值和取值操作。代码示例如下:

/* Test.java */
public class Test {public static void main(String[] args) {Person per1 = new Person();Person per2 = new Person();Person per3 = new Person("王麻子", 28);per1.setName("张三");per1.setAge(10);per2.setName("李四");per2.setAge(18);per1.init();System.out.println("姓名:" + per2.getName());System.out.println("年龄:" + per2.getAge());per3.init();}
}
/* Person.java */
public class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public void init() {System.out.println("姓名:" + name);System.out.println("年龄:" + age);}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

🆚🆚运行结果:

姓名:张三
年龄:10
姓名:李四
年龄:18
姓名:王麻子
年龄:28
2.2.3 对象创建的原理
  • 在Java虚拟机(JVM)的内存模型中,程序计数器、Java栈、堆、本地方法栈和方法区是五个重要的组成部分。
  • 当使用new关键字创建一个对象时,同时操作了栈和堆,在栈内存中保存对象的引用(对象的首地址),在堆内存中保存对象的属性。
  • 编写.java文件(源文件)的时候,文件存储在硬盘上,这个文件只是包含了类的定义和源代码,但它并没有被JVM加载到内存中执行。当编译这个.java文件时,Java编译器(如javac命令)会检查源代码的语法和语义。编译成功后,它会生成一个或多个.class文件(类文件)。这些类文件包含了JVM执行程序所需的字节码(Byte-code)和其他信息。当运行(如java命令)包含main方法的类时,JVM会加载这个类文件到内存中。加载过程中,JVM会执行以下步骤:
    • 加载:JVM通过类加载器(ClassLoader)查找并加载指定的类文件到内存中。
    • 链接
      • 验证:确保被加载的类的正确性和安全性。
      • 准备:为类的静态变量分配内存,并将其初始化为默认值。
      • 解析:把类中的符号引用转换为直接引用。
    • 初始化:为类的静态变量赋予正确的初始值。
  • 操作对象都是通过引用完成,一旦引用出栈,没有被引用的对象就变成了垃圾,JVM的垃圾回收器(Garbage Collector,GC)会负责回收其占用的内存空间。

3. 封装

  • 定义:封装是将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。具体来说,封装通过定义私有变量(使用private作为访问修饰符)和公有方法(公共的gettersetter方法)来实现,私有变量只能在类的内部访问,而公有方法可以在类的外部访问和调用。
    公有方法
  • 作用:数据隐藏,提高代码的可维护性,实现接口和抽象。降低耦合性,实现高内聚、低耦合。

4. 构造方法

在Java中,构造方法(也称为构造函数或构造器)是一种特殊的方法,用于在创建对象时初始化该对象的状态。构造方法的基本语法格式如下:

public class ClassName {  // 类的成员变量  // ...  // 构造函数  public ClassName() {  // 构造函数的实现代码  // 这里可以初始化类的成员变量等  }  // 如果有需要,可以定义带参数的构造函数  public ClassName(parameterType1 parameter1, parameterType2 parameter2, ...) {  // 构造函数的实现代码  // 这里可以使用传入的参数来初始化类的成员变量等  }  // 类的其他方法  // ...  
}
  • 名称:构造方法的名称必须与类名完全相同。这是Java语言规定的一个特性,以便在创建对象时能够自动调用相应的构造方法。
  • 返回类型:构造方法没有返回类型,也不允许使用void关键字声明返回类型。这是因为构造方法的主要目的是初始化对象,而不是返回任何值。
  • 访问修饰符:构造方法可以使用访问修饰符(如publicprotectedprivate)来限制其可见性和可访问性。通常,构造方法被声明为public,以便可以从类的外部创建对象。但是,在某些情况下,你可能希望将构造方法声明为protectedprivate,以实现特定的设计目标(如单例模式、工厂方法等)。
  • 参数列表:构造方法可以具有任意数量和类型的参数。这些参数在创建对象时通过new关键字传递给构造方法,以便在初始化对象时使用。通过提供不同参数的构造方法,可以实现对象的多样化初始化。
  • 默认构造方法:在Java中,每个类至少有一个构造方法。如果你没有显式地定义任何构造方法,那么Java编译器会自动为你生成一个默认的无参构造方法。如果你定义了至少一个构造方法,默认的无参构造方法可能不会被自动生成。
  • 构造方法的调用:如果是在其他类中,通过new的方式来调用构造方法;如果是在自己的类中,可以在构造方法之间进行互相调用。使用this([参数]),必须写在构造方法中的第一行。
  • 继承:子类不会继承父类的构造方法,但子类构造方法可以通过super()关键字调用父类的构造方法。

5. 对象作为方法的参数或返回类型

创建一个类,然后创建该类的对象,并将这些对象作为参数传递给方法或作为方法的返回值。代码示例如下:

public class Person {  private String name;  private int age;  // 构造方法、getter和setter方法...  // 示例方法,接受Person对象作为参数  public void greet(Person otherPerson) {  System.out.println(this.name + " says hello to " + otherPerson.getName());  }  // 示例方法,返回Person对象  public Person getOlderPerson(Person person) {  if (this.age > person.getAge()) {  return this;  } else {  return person;  }  }  
}

6. 对象数组

对象数组是一种可以存储多个对象的数组。每个数组元素都可以是一个对象的引用,指向一个实际的对象。

6.1 声明数组变量

声明一个数组变量,指定数组将要存储的对象的类型,并使用方括号[]表示它是一个数组。

Student[] students; // 声明一个Student类型的数组变量

6.2 创建数组对象

使用new关键字和类的名称来创建数组对象,并指定数组的大小(即它可以存储的元素数量)。

students = new Student[3]; // 创建一个可以存储3个Student对象的数组。

或者,可以在声明变量的同时创建数组对象:

Student[] students = new Student[3]; // 类名[] 数组 = new 类名[数组长度];

代码示例如下:

// Test.java
public class Test {public static void main(String[] args) {Student student1 = new Student("小明", "男");Student student2 = new Student("小红", "女");Student student3 = new Student("小丽", "女");Teacher teacher = new Teacher();Student[] students = new Student[3];students[0] = student1;students[1] = student2;students[2] = student3;teacher.sign(students);}
}
// Teacher.java
public class Teacher {public void sign(Student[] students) {for (Student student : students) {String gender = student.getGender();if (gender.equals("男")) {System.out.println(student.getName() + "到");} else {System.out.println(student.getName() + "有");}}}
}
// Student.java
// ...

🆚🆚运行结果:

小明到
小红有
小丽有

7. static关键字

7.1 static可以修饰属性

  • 静态成员变量(类成员变量):使用static修饰的,作用范围在整个类的所有对象上。所有对象共享这个变量,在内存中只有一个副本。访问通过类名.变量名访问。在类加载时被初始化,存储在堆里。
  • 实例成员变量:没有static修饰,作用范围在某个实例对象上。在创建对象时被初始化,存在多个副本。各个对象不互相影响。通过实例对象名.变量名访问。

7.2 static可以修饰方法

  • 静态方法(类方法):使用static修饰,不能直接使用实例变量,只能直接使用静态变量。只能直接调用静态方法,不能直接调用实例方法。通过类名.方法名()访问。不允许使用this关键字(代表对象)。
  • 实例方法:没有static修饰,既可以使用静态变量,又可以使用实例变量。既可以直接访问实例方法,又可以直接访问静态方法。 通过实例对象名.方法名()访问。

代码示例如下:

public class Car {// 静态成员变量public static int count = 0;// 实例成员变量private String licenseNumber;private String brand;// 构造方法public Car(String licenseNumber, String brand) {this.licenseNumber = licenseNumber;this.brand = brand;// 每次创建Car对象时,都更新静态变量countcount++;}// 静态方法,用于返回当前Car对象的数量public static int getCurrentNumberOfCars() {return count;}// 实例方法,用于显示Car对象的详细信息public void displayDetails() {System.out.println("第" + count + "辆车的车牌号是:" + licenseNumber + ",品牌是:" + brand);}public static void main(String[] args) {// 可以通过类名直接访问静态成员变量System.out.println("最初车的数量:" + Car.count);// 创建Car对象,通过对象引用访问实例成员变量、实例方法Car car1 = new Car("A12345", "问界M9");System.out.println("第" + count + "辆车的车牌号是:" + car1.licenseNumber + ",品牌是:" + car1.brand);Car car2 = new Car("B67890", "小米SU7");car2.displayDetails();// 可以通过类名访问静态方法,获取Car对象的数量System.out.println("目前车的数量:" + Car.getCurrentNumberOfCars());}
}

🆚🆚运行结果:

最初车的数量:01辆车的车牌号是:A12345,品牌是:问界M92辆车的车牌号是:B67890,品牌是:小米SU7
目前车的数量:2

7.3 static可以修饰代码块

执行顺序和优先级:静态代码块>构造代码块>构造方法。

  • 静态代码块:类加载的时候执行,并且只执行一次,优先于各种代码块和构造方法,最开始执行的。
  • 构造代码块:在创建对象时被调用,每创建一次对象,都会执行一次构造代码块。 执行顺序,优先于构造方法执行。一个类如果有多个构造方法时,每通过构造方法,创建一个对象,代码块都会被执行一次。但是对于构造方法来讲,只执行某一个构造方法(根据参数执行)。

代码示例如下:

public class TestInitialization {public TestInitialization() {System.out.println("Constructor executed.");}{System.out.println("Instance block executed.");}static {System.out.println("Static block executed.");}public static void main(String[] args) {TestInitialization obj1 = new TestInitialization();TestInitialization obj2 = new TestInitialization();}
}

🆚🆚运行结果:

Static block executed.
Instance block executed.
Constructor executed.
Instance block executed.
Constructor executed.

7.4 单例模式

单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只能创建一个实例对象,自行实例化,并向整个系统提供这个对象。

7.4.1 饿汉式单例模式

饿汉式单例模式(Eager Initialization Singleton)是一种在类加载时就立即创建单例实例的设计模式。这种模式相比于懒汉式单例模式(Lazy Initialization Singleton),它的优势在于其线程安全性,因为JVM在加载类时会对静态变量进行初始化,并且这个初始化过程是线程安全的。

// 饿汉式单例模式
public class Singleton {private Singleton() { // 私有构造函数,防止外部通过new创建实例}private static final Singleton single = new Singleton(); // 提供一个当前类的私有静态成员变量public static Singleton getInstance() { // 提供一个公有的静态方法,返回成员变量return single;}
}
7.4.2 懒汉式单例模式

非线程安全的懒汉式单例模式是最基本的懒汉式单例模式实现,但在多线程环境下是不安全的。

// 非线程安全的懒汉式单例模式
public class Singleton2 {private Singleton2() {}private static Singleton2 singleton;public static Singleton2 getInstance() {if (singleton == null)singleton = new Singleton2();return singleton;}
}

为了保证懒汉式单例模式的线程安全,通常有以下3种方法:

  1. 线程安全的懒汉式单例模式:使用synchronized关键字来保证线程安全,但这种方式在性能上较差,因为每次调用getInstance()方法时都需要进行同步;
  2. 双重检查锁定(Double-Check Locking,DCL)的懒汉式单例模式:DCL模式通过两次检查实例是否为null来避免不必要的同步,是线程安全且性能较好的实现方式。为了避免指令重排导致的问题,需要将instance声明为volatile
// 双重检查锁定的懒汉式单例模式
public class Singleton3 {private volatile static Singleton3 instance;private Singleton3() {}public static Singleton3 getInstance() {if (instance == null) { // 第一次检查  synchronized (Singleton3.class) {if (instance == null) { // 第二次检查  instance = new Singleton3();}}}return instance;}
}
  1. 静态内部类的懒汉式单例模式:利用静态内部类的特性来实现懒汉式单例模式,这种方式既保证了线程安全,又避免了同步带来的性能开销。
// 静态内部类的懒汉式单例模式
public class Singleton4 {private Singleton4() {}// 静态内部类  private static class Singleton4Holder {private static final Singleton4 INSTANCE = new Singleton4();}// 提供全局访问点  public static Singleton4 getInstance() {return Singleton4Holder.INSTANCE;}
}

8. 使用访问修饰符实现封装

8.1 包的概念

包(Package)是Java中用于组织类的命名空间。它可以把相关的接口枚举注解组合在一起,形成一个逻辑上的单元。包的主要目的是为了解决类的命名冲突和进行更好的代码组织。
包
以下是一些在Java类库中比较常用的包:

包名说明
java.langjava语言包,不需要进行导包,就可以使用的
java.utiljava实用工具包
java.iojava输入输出流包
java.sql操作数据库相关的包
java.netjava网络包
java.text处理文本、日期、时间、数字、消息的类和接口
java.swing图形用户界面

包的用途:

  1. 避免命名冲突;
  2. 可以按功能将类进行组合;
  3. 可以保护类、数据和方法。

📌

  1. package打包语句必须在代码的第一条语句。前面只能有空白和注释;
  2. 使用package时,会在磁盘上生成对应的目录;
  3. 每个源文件只能有一条打包语句。

8.2 导包操作

在同一个包中,类之间互相访问,可以不需导包操作;如果类不在同一个包下面,需要使用import进行导包操作。

  • import可以出现多次。
  • 声明在package之后,在class之前。
  • 导包可以使用通配符*

8.3 静态导入

静态导入(Static Import)是一种导入静态成员(例如静态方法、静态字段或静态枚举常量)的方式,而无需通过类名来引用它们。要使用静态导入,需要使用import static关键字。代码示例如下:

import static com.coder.test.MathUtils.add;

9. 代码封装

代码封装通常指的是使用不同的访问修饰符(Access Modifiers)来控制类、成员变量(属性)和方法的可见性和可访问性。Java提供了四种访问修饰符:

privatedefaultprotectedpublic
同类TTTT
同包FTTT
子类FFTT
通用性FFFT
  • 属性和方法的访问修饰符
    • public:公有的,最高的访问权限,所有类都可以访问,不管是否同包。
    • protected:受保护的,可以被同包的类访问,以及不同包中的子类访问。
    • default(无修饰符,也称为包级私有或默认访问权限):不使用访问修饰符关键字来声明,表示默认,当前类和同包可以访问。
    • private:只能在当前类中访问,不对外公开。
  • 类的访问修饰符
    • public:所有类都可以访问。
    • default:只能当前包中访问。

10. this关键字

  • this.属性名:用于引用当前对象的该属性。
  • this.方法名():用于调用当前对象的该方法。
  • this([参数]):用于调用当前类的另一个构造器,这称为构造器的重载调用或构造器链。必须是构造器(构造方法)中的第一个语句,且只能调用一次。
  • this:用于返回当前对象的引用。

11. 继承关系

11.1 继承的概念

继承是一种机制,它允许一个类(称为子类、派生类或扩展类)继承另一个类(称为父类、超类或基类)的属性和方法。子类可以继承父类的所有非私有成员(即publicprotecteddefault),并且可以选择性地覆盖(@Override)父类的方法,或者添加新的属性和方法。继承关系通常被称为is-a关系。继承的语法格式如下:

class 父类 {
}class 子类 extends 父类 {
}

11.2 继承类型

Java主要支持的是单一继承(Single Inheritance),即一个类只能直接继承自一个父类。
java继承类型

11.3 继承的特性

Java继承具有以下几个主要特性:

  • 单一继承:Java只支持单继承,即一个类只能有一个直接的父类。虽然直接继承是单一的,但可以通过多层继承来间接地继承多个类的特性。
  • 继承属性和方法:子类可以继承父类的非私有(publicprotected)属性和方法。子类可以访问和操作这些继承来的属性和方法。
  • 方法重写(Override):子类可以提供一个与父类方法签名相同(方法名、参数列表和返回类型相同)但实现不同的方法。当通过子类对象调用该方法时,将执行子类中的方法实现,而不是父类中的方法。
  • 构造方法不被继承:子类不继承父类的构造方法。但子类可以通过调用父类的构造方法来初始化从父类继承的属性。这通常通过super()关键字在子类构造方法中完成。
  • 访问权限:子类可以访问父类的公有(public)和保护(protected)成员,但不能直接访问父类的私有(private)成员,必须通过gettersetter方式进行访问。
  • 多态性:继承是实现多态性的基础之一。多态性允许在运行时根据对象的实际类型来调用相应的方法。例如,父类引用可以指向子类对象,并调用子类重写的方法。
  • super关键字:子类可以通过super关键字来引用父类的属性和方法。这允许子类在需要时访问父类的实现或数据。
  • 初始化顺序:在子类实例化时,首先执行父类的静态代码块,然后执行子类的静态代码块。接着,当创建子类对象时,会先调用父类的构造方法(如果有通过super()显式调用或者隐式调用),然后执行子类的构造方法中的代码。
  • 子类可以添加新的属性和方法:子类可以拥有父类所没有的属性和方法,这扩展了父类的功能。
  • final类和final方法:如果一个类被声明为final,则它不能被继承。同样,如果一个方法被声明为final,则它不能在子类中被重写。

11.4 子类实例化过程

子类实例化过程:加载类(包括父类和子类)——>初始化静态变量和静态初始化块——>分配内存——>调用父类构造函数——>初始化父类实例变量和实例初始化块——>执行父类构造函数体——>初始化子类实例变量和实例初始化块——>执行子类构造函数体——>对象创建完成。

❓问:在子类创建对象时,是否也创建了父类的对象?
✅答:不会创建父类对象,只是创建了父类空间,并进行了初始化操作。

📌

  1. 如果父类有无参的构造方法,子类super()可以省略;
  2. 如果父类中没有无参的构造方法,子类super(参数)不可以省略;
  3. 如果使用super()显式地调用父类的构造方法,要求必须写在子类构造方法中的第一行;
  4. 子类的构造方法中,不能同时出现super()this()

11.5 属性的隐藏

  • 在父类中定义一个属性,在子类中定义了一个同名的属性,在子类中访问,会隐藏父类的属性。
  • 在子类中,有两个同名属性,一个是继承自父类的,使用super属性名访问,一个是子类自己的,使用this属性名访问。
  • 在方法中,如果访问到属性,继承自父类的方法,使用的是父类的属性,子类自己的方法,使用的是子类属性。

代码示例如下:

public class TestPro {public static void main(String[] args) {Son son = new Son();son.showName();son.testName();}
}
class Father {String name = "父类的属性";public void testName() {System.out.println("3. " + name);}
}
class Son extends Father {String name = "子类的属性";public void showName() {System.out.println("1. " + name);System.out.println("2. " + super.name + "\t" + this.name);}
}

🆚🆚运行结果:

1. 子类的属性
2. 父类的属性	子类的属性
3. 父类的属性
  • 如果父类中有一个静态变量,则被所有子类所共享,其中一个子类修改了值,其他子类访问也是修改后的值。如果子类自己写了一个同名的静态变量,则子类中访问的是自己的变量,不再是父类变量。

代码示例如下:

public class TestPro2 {public static void main(String[] args) {Son son = new Son();son.showName(); // 打印父类的静态变量Son2 son2 = new Son2();son2.setName(); // 修改静态变量的值son.showName();}
}
class Father {static String name = "父类的属性";public void testName() {System.out.println("3. " + name);}
}
class Son extends Father {// static String name = "子类的属性";public void showName() {System.out.println("4. " + name);}
}
class Son2 extends Father {public void setName() {name = "新子类的属性";}
}

🆚🆚运行结果:

4. 父类的属性
4. 新子类的属性

11.6 方法重写(方法覆盖)

方法重写(Override)是面向对象编程的一个重要概念,它发生在子类与父类之间。方法重写的使用有以下要求:

  • 方法签名相同:方法名、参数列表必须相同;
  • 返回类型相同或子类:返回类型必须相同,或者是其子类;
  • 访问权限不能更严格:子类方法的访问权限(publicprotecteddefaultprivate)不能低于父类中被重写的方法的访问权限;
  • 不能重写final方法:如果父类中的方法被声明为final,那么它不能被重写;
  • 不能重写static方法:如果父类中的方法是static的,那么子类中的同名同参数列表的方法并不是覆盖父类方法,而是隐藏了父类方法,因为static方法是与类关联的,而不是与对象关联的,所以它们不参与多态;
  • 使用@Override注解:在Java中,建议在使用重写时加上@Override注解。这样,如果子类的方法不符合重写的要求(比如方法签名不匹配),编译器会报错;
  • 抛出异常不能更广泛:子类方法抛出的异常类型必须是父类方法抛出的异常类型的子集或者相同,子类方法不能抛出比父类方法更多的异常,但可以选择不抛出异常。

📌

  1. 使用方法重写的场景:子类和父类的方法要完成相同功能,但采用不同的算法或公式。
  2. 必须要重写的方法:抽象方法(由abstract修饰)必须在子类中被重写。
  3. 不能重写的方法:构造方法(constructor)、私有方法(由private修饰)、最终方法(由final修饰)、静态方法(由static修饰)。

11.7 抽象方法和抽象类

抽象(Abstraction)是实现设计和实现相分离的一种关键手段。这种分离是面向对象编程(OOP)的基本原则之一,它使得软件设计更加模块化、可维护和可扩展。

  • 抽象方法:使用abstract关键字修饰,只有方法的声明(方法头),没有方法的实现(方法体)。不能是静态方法。
  • 抽象类:使用abstract关键字修饰,可以有抽象方法,也可以有普通方法,也可以有构造方法,也可以没有抽象方法。如果一个类中有抽象方法,则这个类必须是抽象类。抽象类不能实例化。

11.8 final关键字的用法

final可以用来修饰类、方法、变量(包括实例变量、静态变量和局部变量)和常量表达式。以下是final关键字的用法:

  • 定义终结类(最终类)
    • 当一个类定义为final时,就表明不能继承这个类,表示不能产生子类。
    • final类里面的所有方法,都是隐式的final,不会产生子类,也不会覆盖方法,所以不需要在final类中为方法加final关键字。
  • 定义终结方法
    • 不能被子类重写。所有private方法都是隐式的final方法,在private方法中,不需要使用final关键字修饰。
    • final方法可以被重载(同名,参数列表不同)。

代码示例如下:

private int test1() {return 0;
}
//...
public final void test2() {//...
}
public final void test2(int x) {//...
}
  • 定义常量
    • 修饰引用类型:无法更改引用所指向的对象地址,但引用的对象属性可以修改。
    • 修饰基本数据类型:无论是编译期常量还是非编译期常量,一旦它们被初始化,它们的值就不能再被修改。
    • static final:static final的作用主要是用来声明全局常量,这些常量属于类并且其值不能被改变。这样的常量通常在类加载时初始化,并且可以在整个应用程序中通过类名来访问。

代码示例如下:

public class Test {// 编译期常量final int[] a = {10, 20, 30, 40}; // 引用类型final int i = 10; // 基本数据类型// 非编译期常量Random random = new Random();final int j = random.nextInt(10);public static void main(String[] args) {final Student student = new Student(); // 引用类型student.setName("张三");student.setGender("男");student.setName("李四");System.out.println(student);Test t = new Test();System.out.println(t.i);System.out.println(t.j);}
}
class Student {//...@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", gender='" + gender + '\'' +'}';}
}

🆚🆚运行结果:

Student{name='李四', gender='男'}
10
6

📌final不可以和abstract放在一起对方法和类进行修饰。


12. 多态

12.1 多态的概念

在Java中,多态(Polymorphism)是面向对象编程的三大特性之一(封装、继承和多态),它允许我们以统一的方式处理不同类型的对象。以下是多态的必要条件和优点:

  • 多态的必要条件
    • 继承关系:多态需要存在继承关系。
    • 方法重写:子类必须重写父类的方法,以实现自己的特有行为。
    • 父类引用指向子类对象:在程序中使用父类类型的引用变量指向子类对象,即将子类对象赋给父类引用变量。
    • 父类引用调用重写方法:通过父类引用变量调用子类对象中重写的方法。
    • 运行时绑定:通过动态绑定机制,根据对象的实际类型来调用相应的方法。这是实现多态的关键机制之一。
  • 多态的优点
    • 简化代码。
    • 面向抽象编程,不面向具体编程(依赖倒转原则)。
    • 易于扩展,增强代码可读性。

12.2 向上转型(上溯造型)

向上转型(Upcasting)是指将子类的引用赋值给父类类型的变量。由于子类继承了父类的所有属性和方法(除了私有属性和方法),因此父类类型的变量可以引用子类对象。这种转换是自动的,不需要显式地进行类型转换。语法格式如下:

父类类型 对象名 = new 子类类型();

12.3 向下转型(下溯造型)

向下转型(Downcasting)是指将父类类型的引用转换为子类类型的变量。由于父类引用可能指向的是子类对象,也可能是其他子类对象或父类对象本身,因此这种转换是不安全的,因为它可能会导致ClassCastException。为了进行向下转型,我们需要显式地使用类型转换操作符,并且最好使用instanceof关键字进行检查,以确保转换是安全的。语法格式如下:

子类类型 对象名 = (子类类型)父类引用;

代码示例如下:

class Animal {void eat() {System.out.println("所有的动物都要吃东西");}
}
class Dog extends Animal {@Overridevoid eat() {System.out.println("小狗爱吃骨头");}
}
class Cat extends Animal {@Overridevoid eat() {System.out.println("小猫爱吃鱼");}
}
public class Main {public static void main(String[] args) {// 向上转型Animal animal1 = new Dog();animal1.eat();Animal animal2 = new Cat();// 向下转型if (animal2 instanceof Animal) { // 使用instanceof关键字进行检查Cat cat = (Cat) animal2;cat.eat();}}
}

🆚🆚运行结果:

小狗爱吃骨头
小猫爱吃鱼

12.4 里式代换原则

里式代换原则(Liskov Substitution Principle,LSP)是面向对象设计的基本原则之一。这个原则强调了在程序设计中,子类应当能够替换其父类并出现在父类能够出现的任何地方,而不会改变程序的行为。里式代换原则要求:

  1. 子类必须完全实现父类的方法;
  2. 父类出现的地方,子类一定可以出现;
  3. 子类出现的地方,父类不一定可以出现。

12.5 instanceof运算符

判断一个对象是否属于某个类(或其父类),返回boolean类型的值,如果属于就返回true,否则返回false

object instanceof Class

其中:object是要测试的对象,Class是要检查的类名。


13. 组合关系

组合(Composition)关系是一种表示“部分-整体”关系的设计概念,它表示一个对象(组合对象)包含另一个对象(被组合对象)作为其实例变量(字段、属性)。这种关系也称为has-a关系,它表示一个对象有另一个对象作为其一部分。代码示例如下:

class Engine {// Engine类的属性和方法private String type;public Engine(String type) {this.type = type;}public String getType() {return type;}
}
class Car {// Car类包含Engine类的实例变量,表示组合关系private Engine engine;public Car(Engine engine) {this.engine = engine;}public void start() {// 使用被组合对象的方法System.out.println("汽车开始启动" + engine.getType() + "引擎");}
}
public class Main {public static void main(String[] args) {Engine engine = new Engine("V8");Car car = new Car(engine);car.start();}
}

🆚🆚运行结果:

汽车开始启动V8引擎

📌:合成聚合复用原则(Composite/Aggregate Reuse Principle,CARP)是面向对象设计中的一个重要原则,它强调在复用代码时,应该优先使用对象的组合/聚合关系,而不是通过继承关系来达到复用的目的。


14. 接口

14.1 接口的概念

接口(Interface)是一个完全抽象的类,它不能被实例化,但可以被类实现(Implement)。实现关系通常被称为like-a关系。接口主要用于定义一组方法,这些方法被称为接口方法,这些方法不提供具体的实现,而是由实现接口的类来提供。

14.2 语法格式

接口的语法格式如下:

[修饰符] interface 接口名 [extends 接口名[, 接口名...]] {  // 常量(字段)  [public] [static] [final] 数据类型 常量名 =;  // 抽象方法  [public] [abstract] 返回类型 方法名(参数列表);  // 默认方法(从JDK 1.8开始)  [public] default 返回类型 方法名(参数列表) {  // 方法体  }  // 静态方法(从JDK 1.8开始)  [public] static 返回类型 方法名(参数列表) {  // 方法体  }  // 私有方法(从Java 9开始)  // 私有静态方法  private static 返回类型 方法名(参数列表) {  // 方法体  }  // 私有实例方法(从Java 9开始)  private 返回类型 方法名(参数列表) {  // 方法体  }  
}

类的语法格式如下:

[修饰符] class 类名 [implements 接口名[, 接口名...]] {  // 成员变量(字段)  [修饰符] 数据类型 变量名;  // 构造方法  [修饰符] 类名(参数列表) {  // 构造方法体  }  // 方法  [修饰符] 返回类型 方法名(参数列表) {  // 方法体  }  // 初始化块(可选)  {  // 初始化代码  }  // 内部类、接口等(可选)  
}

其中:

  • 接口的定义:[访问修饰符] interface 接口名{}
  • 接口中的数据成员(变量)默认都是public static final的,也就是公有的静态常量。
  • 接口中的方法默认是public abstract的,因此可以省略这些修饰符。
  • 从Java 8(JDK 1.8)开始,接口中可以包含带有具体实现的方法,称为默认方法,使用default来标记。
  • 从Java 8开始,接口中可以包含静态方法,使用static来标记,并且不能是抽象的。
  • 从Java 9开始,接口中可以包含私有方法(包括私有静态方法和私有实例方法),这些私有方法只能在接口内部使用,并且不能被实现类访问。
  • 接口不是类,没有构造方法,不能实例化。
  • 接口可以实现多继承。
  • 一个接口,可以被多个类实现。
  • 类和接口的关系:class 类名 implements 接口名{}
  • 一个类可以实现多个接口:class 类名 implements 接口1[,接口2...]{}
  • 一个类可以在继承一个父类的同时,实现一个或多个接口:class 类名 extends 父类 implements 接口1[,接口2...]{}
14.3 接口的应用
14.3.1 接口的多态

接口(Interface)是实现多态性(Polymorphism)的一种重要方式。接口的多态实现方式主要依赖于这三个关键概念:接口定义,类实现接口,接口引用指向实现类的对象。代码示例如下:

/* 接口定义 */
interface Shape { // 图形void draw();void calculateArea();
}
/* 类实现接口 */
class Circle implements Shape { // 圆@Overridepublic void draw() {System.out.println("画个圆");}@Overridepublic void calculateArea() {// 实现计算圆面积的代码}
}
class Rectangle implements Shape { // 矩形@Overridepublic void draw() {System.out.println("画个矩形");}@Overridepublic void calculateArea() {// 实现计算矩形面积的代码}
}
public class Main {public static void main(String[] args) {/* 接口引用指向实现类的对象 */Shape shape1 = new Circle(); // Circle 是 Shape 的一个实现Shape shape2 = new Rectangle(); // Rectangle 也是 Shape 的一个实现// 调用 draw 方法shape1.draw();shape2.draw();// 调用接口中定义的其他方法shape1.calculateArea();shape2.calculateArea();}
}

🆚🆚运行结果:

画个圆
画个矩形
14.3.2 接口与抽象类

接口(Interface)和抽象类(Abstract Class)是两种用于实现多态性和代码重用的重要机制。接口与抽象类的主要区别:

  • 目的:接口主要用于定义对象的行为规范,而抽象类则用于定义对象的共同属性和行为的模板。
  • 方法:接口只包含抽象方法,而抽象类可以包含抽象方法和非抽象方法。
  • 继承与实现:类通过extends关键字继承抽象类,通过implements关键字实现接口。
  • 多重继承:一个类可以实现多个接口,但只能继承一个抽象类(直接继承)。
  • 字段:接口中的字段都是常量(隐式staticfinal),而抽象类可以包含各种类型的字段。
14.3.3 简单工厂模式

简单工厂模式(Simple Factory Pattern)是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,它由一个工厂类根据传入的参数来决定创建哪一种产品类的实例。简单工厂模式是最简单的工厂模式,但它不是一种设计模式,因为它没有遵循开闭原则(Open-Closed Principle),即扩展开放,修改关闭。
简单工厂模式
代码示例如下:

// 定义一个产品接口
interface Product {void use();
}
// 实现产品接口的具体产品类
class ProductA implements Product {@Overridepublic void use() {System.out.println("使用产品A");}
}
class ProductB implements Product {@Overridepublic void use() {System.out.println("使用产品B");}
}
// 工厂类,负责创建产品对象
class SimpleFactory {// 静态方法,根据传入的参数创建对应的产品对象public static Product createProduct(String type) {if ("A".equals(type)) {return new ProductA();} else if ("B".equals(type)) {return new ProductB();} else {return null; // 或者抛出异常}}
}
// 客户端代码
public class Client {public static void main(String[] args) {// 使用工厂类创建产品对象Product productA = SimpleFactory.createProduct("A");if (productA != null) {productA.use(); }Product productB = SimpleFactory.createProduct("B");if (productB != null) {productB.use();}// 试图创建一个不存在的产品类型Product productC = SimpleFactory.createProduct("C");if (productC == null) {System.out.println("无法创建产品C");}}
}

🆚🆚运行结果:

使用产品A
使用产品B
无法创建产品C
14.3.4 工厂方法模式

工厂方法模式(Factory Method Pattern)定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建的任务交给它的子类来完成。这样做既保证了核心类的稳定,又使得子类可以根据自身需要来灵活创建对象。
工厂方法模式
代码示例如下:

// 产品接口
interface Product {void use();
}
// 具体产品类A
class ProductA implements Product {@Overridepublic void use() {System.out.println("使用产品A");}
}
// 具体产品类B
class ProductB implements Product {@Overridepublic void use() {System.out.println("使用产品B");}
}
// 工厂接口
interface Factory {Product createProduct();
}
// 具体工厂类A
class FactoryA implements Factory {@Overridepublic Product createProduct() {return new ProductA();}
}
// 具体工厂类B
class FactoryB implements Factory {@Overridepublic Product createProduct() {return new ProductB();}
}
// 客户端代码
public class Client {public static void main(String[] args) {Factory factoryA = new FactoryA();Product productA = factoryA.createProduct();productA.use();Factory factoryB = new FactoryB();Product productB = factoryB.createProduct();productB.use();}
}

🆚🆚运行结果:

使用产品A
使用产品B
14.3.5 缺省适配器模式

缺省适配器模式(Default Adapter Pattern)是适配器模式(Adapter Pattern)的一个特殊形式,是一种结构型设计模式,用于处理接口中方法数量过多,或者大部分方法都有默认实现的情况。缺省适配器模式通过提供一个实现了目标接口的缺省适配器类,该类为接口中的每个方法都提供了默认实现,从而允许子类继承该适配器类时只需要关注自己感兴趣的方法,而不需要实现接口中的所有方法。
缺省适配器模式
代码示例如下:

// 目标接口
interface MyInterface {void method1();void method2();void method3();// ... 可能还有其他方法
}
// 缺省适配器类,实现了MyInterface接口并提供默认实现
class DefaultAdapter implements MyInterface {@Overridepublic void method1() {System.out.println("Default implementation of method1");}@Overridepublic void method2() {System.out.println("Default implementation of method2");}@Overridepublic void method3() {System.out.println("Default implementation of method3");}// ... 其他方法的默认实现
}
// 具体实现类,继承自缺省适配器并覆盖部分方法
class MySpecificImplementation extends DefaultAdapter {@Overridepublic void method1() {// 覆盖默认实现System.out.println("Specific implementation of method1");}// method2 和 method3 使用默认实现
}
// 客户端代码
public class Main {public static void main(String[] args) {MyInterface myImpl = new MySpecificImplementation();myImpl.method1();myImpl.method2();myImpl.method3();}
}

🆚🆚运行结果:

Specific implementation of method1
Default implementation of method2
Default implementation of method3

15. 内部类

15.1 简介

  • 在一个类中,定义另一个类,称作内部类(Inner Class)。
  • 内部类可以访问外部类中的属性和方法,不需要创建外部类的对象。
  • 外部类要访问内部类的属性民和方法,需要创建内部类的对象.
  • 如果内部类有和外部类同名变量和方法,则内部类的变量和方法优先级更高。
  • 外部类,修饰符publicdefault
  • 内部类,修饰符publicprotecteddefaultprivate

15.2 分类

15.2.1 成员内部类(普通内部类)

成员内部类(Member Inner Classes)可以直接访问外部类的变量和方法(包括私有和静态修饰的),不能使用static声明变量和方法的。编译后生成的class文件命名为 “外部类名$内部类名”。不能直接new一个内部类对象,必须使用外部类对象来创建内部类对象。
成员内部类
代码示例如下:

class Test {public static void main(String[] args) {OuterClass outer = new OuterClass();OuterClass.MemberInner MemberInner = outer.new MemberInner();MemberInner.test();}
}
class OuterClass {private int x = 10;private static int y = 20;class MemberInner {int x = 30;public void test() {System.out.println(OuterClass.this.x + x + y);}}
}

🆚🆚运行结果:

60

📌:如果外部类和内部类具有相同名称的成员变量或方法,内部类可以直接访问内部类的成员变量和方法,如果内部类访问外部类的成员变量或方法时,需要this关键字。

15.2.2 静态内部类

静态内部类(Static Inner Classes)使用static修饰的内部类,不能直接访问外部类的非静态成员变量和方法。如果要访问外部类的实例变量和方法,需要创建外部类的实例对象。可以创建静态变量和方法。静态内部类创建对象时,不需要创建外部类的对象,直接可以创建内部类的对象。代码示例如下:
静态内部类
代码示例如下:

class Test1 {public static void main(String[] args) {OuterStatic.test1(); // 类名.方法名()OuterStatic.InnerStatic innerStatic = new OuterStatic.InnerStatic(); // 创建内部类的对象innerStatic.test(); // 实例对象名.方法名()OuterStatic.InnerStatic.test1();}
}
class OuterStatic {private int x = 10;public static void test1() { // 静态方法System.out.println("OuterStatic");}static class InnerStatic {private static int y = 20; // 静态变量public static void test1() { // 静态方法System.out.println("InnerStatic");}public void test() { // 实例方法test1();OuterStatic outer = new OuterStatic();System.out.println(outer.x);}}
}

🆚🆚运行结果:

OuterStatic
InnerStatic
10
InnerStatic
15.2.3 局部内部类

局部内部类(Local Inner Classes)定义在外部类的方法或代码块中。可以直接访问外部类的所有成员变量和方法(包括私有的、静态的),不能使用访问修饰符(地位相当于局部变量),可以使用final修饰,防止其他类去继承。作用范围就在当前的方法或代码块中。
局部内部类
代码示例如下:

class Test2 {public static void main(String[] args) {OuterLocal outerLocal = new OuterLocal();outerLocal.outerMethod();}
}
class OuterLocal {public void outerMethod() {final int localVar = 10; // 保证数据运行的一致性,使用final来修饰class InnerLocal {public void display() {System.out.println("Accessing localVar: " + localVar);}}InnerLocal inner = new InnerLocal();inner.display();}
}

🆚🆚运行结果:

Accessing localVar: 10
15.2.4 匿名内部类

匿名内部类(Anonymous Inner Classes)是没有类名的内部类,通常用于继承一个类或实现一个接口,并且只需要使用一次。常用于GUI编程中的事件监听器、线程等。匿名内部类不能定义构造函数。语法格式如下:

new <类或接口> <类的主体>

匿名内部类
代码示例如下:
例1:

class Test3 {public static void main(String[] args) {AddInterface inter = new AddInterface() {@Overridepublic void add(int x, int y) {System.out.println(x + y);}};OuterAnony anony = new OuterAnony();anony.testAdd(inter, 10, 20);}
}
class OuterAnony {public void testAdd(AddInterface addInterface, int x, int y) {addInterface.add(x, y);}
}
interface AddInterface {void add(int x, int y);
}

例2:

class Test3 {public static void main(String[] args) {OuterAnony anony = new OuterAnony();anony.testAdd(new AddInterface() {@Overridepublic void add(int x, int y) {System.out.println(x + y);}}, 10, 20);}
}

例3:

class Test3 {public static void main(String[] args) {OuterAnony anony = new OuterAnony();anony.testAdd((x, y) -> System.out.println(x + y), 10, 20); // Lambda表达式}
}

🆚🆚运行结果:

30

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

以上内容是关于Java面向对象的基础知识,希望对初学者或再次学习者有所帮助,基础打扎实,不怕风吹雨打!如果以上内容有错误或者内容不全,望大家提出!我也会继续写好每一篇博文!
👍👍👍

待续未完
🙊🙊🙊

欢迎观看和提问!!!
👏👏👏

下一篇:Java基础:异常(三)
赞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/18369.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DataGrip使用ssh连接数据库的操作流程

1 选择数据源种类 2 配置ssh 3 填写host、port和认证方式 我选择的密码方式&#xff0c;也可选择其他方式连接&#xff1a; 本文由博客一文多发平台 OpenWrite 发布&#xff01;

【放球问题】920. 播放列表的数量

本文涉及知识点 【组合数学 隔板法 容斥原理】放球问题 本题同解 【动态规划】【组合数学】【C算法】920播放列表的数量 LeetCode 920. 播放列表的数量 你的音乐播放器里有 n 首不同的歌&#xff0c;在旅途中&#xff0c;你计划听 goal 首歌&#xff08;不一定不同&#x…

释放 OSINT 的力量:在线调查综合指南

开源情报 (OSINT) 是从公开信息中提取有价值见解的艺术。无论您是网络安全专业人士、道德黑客还是情报分析师&#xff0c;OSINT 都能为您提供先进的技术&#xff0c;帮助您筛选海量的数字数据&#xff0c;发现隐藏的真相。 在本文中&#xff0c;我们将深入研究大量的OSINT 资源…

冯喜运:5.29市场避险情绪升温,黄金原油小幅收涨

【黄金消息面分析】&#xff1a;周二&#xff08;5月28日&#xff09;美盘时段&#xff0c;由于美元走弱且市场情绪出现负面变化&#xff0c;黄金收复早前跌幅&#xff0c;站上2350美元关口。金价早盘一度走弱&#xff0c;源于美联储降息可能性降低带来压力&#xff0c;投资者在…

AWS联网和内容分发之Transit Gateway

将Amazon VPC、AWS账户和本地网络连接到一个网关中。AWS Transit Gateway通过中央枢纽连接Amazon虚拟私有云&#xff08;VPC&#xff09;和本地网络。此连接简化了您的网络&#xff0c;并且结束了复杂的对等关系。Transit Gateway充当高度可扩展的云路由器&#xff0c;每个新的…

李廉洋:5.29黄金早盘2365-2345区间,今日行情走势分析及策略。

黄金消息面分析&#xff1a;当前美国存在一个令人担忧且未被充分关注的问题&#xff1a;房地产行业低迷、高利率和抵押贷款利率、租金高涨以及美联储的紧缩政策构成了一个恶性循环。由于高房价和高抵押贷款利率&#xff0c;美国住房经济活动远低于两年前的水平。为了让该行业好…

基于 RNNs 对 IMDB 电影评论进行情感分类

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

YiShaAdmin:一款基于.NET Core Web + Bootstrap的企业级快速开发框架

前言 今天大姚给大家分享一款基于.NET Core Web Bootstrap的企业级快速后台开发框架、权限管理系统&#xff0c;代码简单易懂、界面简洁美观&#xff08;基于MIT License开源&#xff0c;免费可商用&#xff09;&#xff1a;YiShaAdmin。 项目官方介绍 YiShaAdmin 基于.NET…

区间相交-435. 无重叠区间,56. 合并区间

题目连接及描述 435. 无重叠区间 - 力扣&#xff08;LeetCode&#xff09; 56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 题目分析 二维数组&#xff0c;数组中每个元素为大小为2的一维数组&#xff0c;求移除区间的最小数量&#xff0c;使剩余区间互不重叠。今天写…

数据结构之堆(优先级队列)

前言 在上一章我们讲了二叉树&#xff0c;这一节我们来讲堆&#xff08;优先级队列&#xff09;&#xff0c;所以想知道堆创建&#xff0c;可以看一下二叉树的一些简单概念。http://t.csdnimg.cn/4jUR6http://t.csdnimg.cn/4jUR6 目录 前言 堆 1.概念 2.优先级队列的模拟实…

1.2数学基础

向量运算 矩阵运算 比较基础就不记录了 MVP矩阵推导 1.讲为什么要有矩阵变换和不同的坐标空间 将3D物体转化到2D平面为各个空间的运用做准备 2.介绍各个空间的概念和含义 MVP矩阵代表什么&#xff1f; MVP矩阵分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。…

positivessl泛域名证书500元13个月

随着创建网站的门槛变低&#xff0c;不论是个人用户还是企事业单位用户创建的域名网站也越来越多&#xff0c;怎么维护网络环境的安全成为了各个用户需要解决的问题。为了保护网站的数据安全&#xff0c;防止恶意攻击和数据泄露&#xff0c;大多数用户选择为域名网站安装数字证…

水电智能抄表是什么?

1.简述&#xff1a;水电智能抄表的兴起 水电智能抄表系统是现代科学技术和传统公共文化服务相结合的产物&#xff0c;它通过自动化技术性改变了传统的人工抄表方式&#xff0c;大大提高了高效率&#xff0c;降低生产成本&#xff0c;同时也为用户提供了更为贴心的服务。这一新…

轻兔推荐 —— 一个好用的软件服务推荐平台

给大家推荐一个好用的的软件服务推荐平台&#xff1a;轻兔推荐 网站界面简洁大方&#xff0c;没有太多杂七杂八的功能和页面&#xff0c;有明暗主题色可以选择&#xff0c;默认为亮色&#xff0c;可在网站上方手动切换。 每工作日都会推荐一款软件&#xff0c;有时会加更&…

内网安全--隧道技术-MSF上线本地

免责声明:本文仅做技术交流与学习... 不得不说,小白最近也是用上了viper,这里要特别感谢一下my bro 北岭敲键盘的荒漠猫 MSF--viper: --生成马子-->上线 --进入meterpreter. 1-查看路由,添加路由. 查看路由信息 : run autoroute -p run post/multi/manage/autoroute 添加…

『香橙派』基于Orange Pi AIpro打造高效个人云存储解决方案

&#x1f4e3;读完这篇文章里你能收获到 了解Orange Pi AIpro硬件优势&#xff0c;为构建高效云存储基础设施的理想平台。学会使用Orange Pi AIpro硬件平台&#xff0c;搭载Ubuntu Server系统&#xff0c;打造云存储环境。掌握利用Kodbox软件&#xff0c;享受文件管理、多格式…

微软MSBuild大会发布Copilot+PC:技术革新还是隐私噩梦?

微软在最近的MSBuild 2024大会上发布了全新的CopilotPC概念&#xff0c;这一技术结合了高通骁龙X Elite芯片&#xff0c;将人工智能与PC紧密结合。此次发布引起了广泛关注&#xff0c;不仅是因为其技术创新&#xff0c;还因为潜在的隐私问题。甚至连Elon Musk也对此表示担忧&am…

小熊家务帮day5 客户管理模块1 (小程序认证,手机验证码认证等)

客户管理模块 1.认证模块1.1 认证方式介绍1.1.1 小程序认证1.1.2 手机验证码登录1.1.3 账号密码认证 1.2 小程序认证1.2.1 小程序申请1.2.2 创建客户后端工程jzo2o-customer1.2.3 开发部署前端1.2.4 小程序认证流程1.2.4.1 customer小程序认证接口设计Controller层Service层调用…

C++ | Leetcode C++题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>> ret(numRows);for (int i 0; i < numRows; i) {ret[i].resize(i 1);ret[i][0] ret[i][i] 1;for (int j 1; j &…

Python | Leetcode Python题解之第117题填充每个节点的下一个右侧节点指针II

题目&#xff1a; 题解&#xff1a; class Solution:def connect(self, root: Node) -> Node:if not root:return Nonestart rootwhile start:self.last Noneself.nextStart Nonep startwhile p:if p.left:self.handle(p.left)if p.right:self.handle(p.right)p p.nex…