Java 面向对象 -- Java 语言的封装、继承、多态、内部类和 Object 类
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 007 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自己的技术栈的同学。与此同时,本专栏的所有文章,也都会准备充足的代码示例和完善的知识点梳理,因此也十分适合零基础的小白和要准备工作面试的同学学习。当然,我也会在必要的时候进行相关技术深度的技术解读,相信即使是拥有多年 Java 开发经验的从业者和大佬们也会有所收获并找到乐趣。
–
在我们对 Java 语言进行基本介绍之后,本篇文章将带领大家深入了解 Java 的面向对象编程(OOP)概念。我们将探讨封装、继承和多态这三大核心概念,以及内部类的使用和 Object 类的重要性。通过对这些内容的学习,读者将能够更好地设计和实现复杂的 Java 应用程序。
最后在前言的末尾我补充一下,如果这篇文章,对大家有所帮助或收获一定的乐趣和想法,那么非常欢迎大家能够,点赞、评论、收藏、订阅。这些也将是我持续更新的最大动力。
文章目录
- 1、面向对象的概念
- 1.1、面向对象和面向过程的区别
- 1.2、面向对象的一般步骤
- 2、关于封装
- 2.1、封装的概念
- 2.2、访问限定符
- 2.3、封装的优点
- 3、Java 内部类
- 3.1、成员内部类(Member Inner Class)
- 3.2、静态内部类(Static Nested Class)
- 3.3、局部内部类(Local Inner Class)
- 3.4、匿名内部类(Anonymous Inner Class)(涉及接口)
- 4、关于继承
- 4.1、什么是继承
- 4.2、子类和超类
- 4.2.1、子类
- 4.2.2、超类
- 4.3、`this` 和 `super` 关键字
- 4.4、子类中方法的重写
- 5、`Object` 类
- 5.1、`Object` 类的重要方法
- 5.2、`Object` 类的使用示例
- 6、特性:多态
- 6.1、多态概述
- 6.2、注意事项
- 6.3、编译时多态与方法签名
- 6.4、运行时多态
- 6.5、向上转型
- 6.6、向下转型
- 6.7、`instanceof` 关键字
1、面向对象的概念
1.1、面向对象和面向过程的区别
面向过程和面向对象是两种不同的编程范式,它们各有优缺点。
-
面向过程:将问题分解成步骤,然后按照步骤实现函数,执行时依次调用函数。数据和对数据的操作是分离的。面向过程的优点是性能比面向对象高,因为不需要进行对象的实例化。但是,面向过程的代码不易于维护、复用和扩展;
-
面向对象:将问题分解成对象,描述事物在解决问题的步骤中的行为。对象与属性和行为是关联的。面向对象的优点是具有封装、继承、多态的特性,因此代码易于维护、复用和扩展,可以设计出低耦合的系统。但是,由于需要实例化对象,因此面向对象的性能比面向过程低。
在 Java 中,面向对象的三大特性是:
-
封装:封装是将对象的状态(属性)和行为(方法)包装在一起的过程。封装可以隐藏对象的内部实现细节,只暴露出需要的信息。这样可以保护对象的内部状态,防止外部直接访问对象的内部数据;
-
继承:继承是从已有的类派生出新的类的过程。新的类(子类)可以继承父类的属性和方法,并可以添加新的属性和方法,也可以重写父类的方法。继承可以提高代码的复用性,使得子类可以拥有父类的所有功能;
-
多态:多态是指允许一个接口使用多种实际类型的能力。多态可以使得代码更加灵活和可扩展。在 Java 中,多态主要体现在接口的多实现和类的多重继承。
1.2、面向对象的一般步骤
面向对象编程的一般步骤如下:
-
提炼问题领域中的对象:这一步主要是通过分析问题,找出其中涉及的名词,这些名词通常就是我们需要创建的对象;
-
对象描述:这一步是对找出的对象进行描述,明确这些对象应该具备哪些属性和行为。这些属性和行为在编程中通常体现为对象的变量和方法;
-
对象实例化:这一步是通过
new
关键字创建对象的实例。每个对象实例都有自己的属性和行为; -
调用对象功能:这一步是通过对象实例调用其功能,也就是执行对象的方法。
以上就是面向对象编程的一般步骤。
2、关于封装
2.1、封装的概念
封装的基本思想是将对象的属性和行为隐藏起来,只对外暴露必要的接口。这样可以保护对象的内部状态,防止外部代码随意修改对象的属性,保证对象的完整性和一致性。
举个例子,计算机是一种复杂的设备,但对用户来说,只需通过一些简单的操作,如开关机、键盘输入、鼠标操作等,就可以与计算机交互。计算机内部的复杂硬件和工作原理被封装在一个壳子里,用户无需了解这些细节,只需使用提供的接口进行操作。
在 Java 中,封装就是将数据和操作数据的方法结合在一起,隐藏对象的属性和实现细节,只对外提供必要的接口进行交互。
2.2、访问限定符
Java 通过类和访问权限来实现封装。类可以将数据和操作数据的方法结合在一起,而访问权限控制方法和字段的可见性和访问范围。Java 提供了四种访问限定符:public
、protected
、default
(默认)和 private
。
- public:公共的,可以被任何其他类或对象访问;
- protected:受保护的,只能被相同包或其子类中的类或对象访问;
- default(默认):没有显式指定访问限定符时,默认为包级私有,只能在同一个包内访问;
- private:私有的,只能在定义该成员的类内部访问。
访问权限修饰符是一种强制机制,用来保证封装性,防止外部代码破坏对象的内部状态。
2.3、封装的优点
封装具有以下优点:
-
安全性:通过封装,可以隐藏对象的内部实现细节,防止外部代码随意访问和修改对象的属性,提高系统的安全性;
-
可读性和可维护性:封装使得对象的属性只能通过特定的方法访问和修改,修改逻辑集中在这些方法中,提高代码的可读性和可维护性;
-
易用性:封装可以对外部隐藏不必要的细节,只暴露必要的接口,使得对象的使用更加简单和直观,减少调用者的迷惑和错误。
下面是一个示例,展示了如何在 Java 中实现封装:
public class Person {// 私有属性private String name;private int age;// 公共构造方法public Person(String name, int age) {this.name = name;this.age = age;}// 公共的 getter 和 setter 方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {if (age > 0) {this.age = age;} else {System.out.println("年龄必须是正数");}}// 其他公共方法public void displayInfo() {System.out.println("Name: " + name + ", Age: " + age);}public static void main(String[] args) {// 创建对象并使用公共方法访问私有属性Person person = new Person("Alice", 25);person.displayInfo();person.setAge(30);person.displayInfo();}
}
在这个例子中,Person
类的属性 name
和 age
被封装为私有,只能通过公共的 getter
和 setter
方法访问和修改。同时,setter
方法中还添加了逻辑检查,确保年龄是正数,从而保证了对象的状态一致性和安全性。
通过以上示例,可以看到封装不仅保护了对象的内部状态,还提供了对外统一的访问接口,提高了代码的安全性、可读性和可维护性。
3、Java 内部类
Java 内部类是定义在另一个类内部的类。内部类主要用于封装逻辑和行为,使代码更易读、易维护,并且可以更好地实现封装。Java 提供了几种不同类型的内部类,每种都有其特定的用途和特性。
内部类有以下几个主要用途:
-
封装:内部类可以访问外部类的所有成员(包括私有成员),因此,我们可以使用内部类来隐藏复杂的实现细节,提供简单的接口;
-
增强封装性和可读性:内部类可以将相关的类组织在一起,这样可以使代码更易于阅读和维护;
-
支持多重继承:Java 不支持多重继承,但我们可以使用内部类来模拟多重继承;
-
实现回调:内部类常常用于实现回调。在 GUI 编程和多线程编程中,我们经常需要在某个特定的时间点执行某个特定的任务,这时我们就可以使用内部类。
内部类是一种高级特性,它可以使我们的代码更加整洁、灵活和易于维护。我们可以将内部类分为四种:成员内部类、静态内部类、方法内部类和匿名内部类。
3.1、成员内部类(Member Inner Class)
成员内部类是定义在另一个类的成员位置的类。成员内部类可以访问外部类的所有成员,包括私有成员。
示例:
public class OuterClass {private String outerField = "Outer field";/** 成员内部类 */public class InnerClass {public void display() {System.out.println("Outer field: " + outerField);}}public static void main(String[] args) {OuterClass outer = new OuterClass();OuterClass.InnerClass inner = outer.new InnerClass();inner.display();}
}
在这个例子中,InnerClass
是 OuterClass
的成员内部类,可以访问 OuterClass
的 outerField
。
3.2、静态内部类(Static Nested Class)
静态内部类是使用 static
修饰的内部类。静态内部类不能访问外部类的非静态成员,但可以访问外部类的静态成员。
示例:
public class OuterClass {private static String staticOuterField = "Static Outer field";/** 静态内部类 */public static class StaticInnerClass {public void display() {System.out.println("Static Outer field: " + staticOuterField);}}public static void main(String[] args) {OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();staticInner.display();}
}
在这个例子中,StaticInnerClass
是 OuterClass
的静态内部类,可以访问 OuterClass
的静态成员 staticOuterField
。
3.3、局部内部类(Local Inner Class)
局部内部类是在方法或代码块内部定义的类。局部内部类只能在其定义的范围内使用,通常用于实现一些临时性的功能。
示例:
public class OuterClass {public void outerMethod() {final String localVar = "Local variable";/** 局部内部类 */class LocalInnerClass {public void display() {System.out.println("Local variable: " + localVar);}}LocalInnerClass localInner = new LocalInnerClass();localInner.display();}public static void main(String[] args) {OuterClass outer = new OuterClass();outer.outerMethod();}
}
在这个例子中,LocalInnerClass
是定义在 outerMethod
方法内部的局部内部类,可以访问方法的局部变量 localVar
。
3.4、匿名内部类(Anonymous Inner Class)(涉及接口)
匿名内部类是一种没有名字的内部类,它通常用于只需要使用一次的场合。
匿名内部类通常用于以下两种类型的场合:
-
实现接口:匿名内部类可以在定义一个类的同时实现一个接口。例如,我们可以在创建一个线程时使用匿名内部类来实现 Runnable 接口;
-
继承类:匿名内部类可以在定义一个类的同时继承一个类。例如,我们可以在创建一个图形界面的按钮时使用匿名内部类来继承 ActionListener 类。
匿名内部类的语法格式如下:
new 父类名或接口名() {// 方法重写@Overridepublic void method() {// 执行语句}
}
匿名内部类是一种简洁的语法,它可以让我们的代码更加简洁和易于阅读。但是,由于匿名内部类没有名字,所以它只能在定义的地方使用,不能在其他地方引用,这限制了它的使用范围。
示例:
public class OuterClass {public void createThread() {/** 匿名内部类 */Thread thread = new Thread() {public void run() {System.out.println("Anonymous Inner Class Thread running");}};thread.start();}public static void main(String[] args) {OuterClass outer = new OuterClass();outer.createThread();}
}
在这个例子中,匿名内部类继承了 Thread
类并重写了 run
方法。
4、关于继承
4.1、什么是继承
继承(Inheritance): 从一个已知的类中派生出一个新的类,新类可以拥有已知类的行为和属性,并且可以通过覆盖/重写来增强已知类的能力,子类共性的方法或者属性直接采用父类的,而不需要自己定义,只需要扩展自己的个性化。
继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
继承的优点:提高代码的复用性、提供了多态的前提、为多态做铺垫等
继承的初始化顺序:
父类的静态代码块 -> 子类的静态代码块 -> 父类的构造代码块 -> 父类的无参构造方法 -> 子类的构造代码块 -> 子类的无参构造方法
4.2、子类和超类
4.2.1、子类
子类是继承自另一个类的类。子类不仅继承了父类的所有属性和方法,还可以添加自己的属性和方法,或者重写父类的方法以提供特定的实现。子类通过使用 extends
关键字来实现继承。
例如,定义一个 Dog
类作为 Animal
类的子类:
public class Dog extends Animal {String breed;@Overridepublic void makeSound() {System.out.println("Dog barks");}public void fetch() {System.out.println("Dog fetches the ball");}
}
在这个例子中,Dog
类继承了 Animal
类的所有属性和方法,并添加了一个新的属性 breed
以及一个新的方法 fetch()
。同时,它重写了 makeSound()
方法,以提供狗特有的实现。
4.2.2、超类
超类是被其他类继承的类。超类提供了子类可以重用的通用属性和方法。在上面的例子中,Animal
类就是 Dog
类的超类。
4.3、this
和 super
关键字
this
和 super
是 Java 中的两个特殊关键字,它们在处理类和对象时非常有用。
-
this
关键字:this
是一个引用变量,它指向当前对象。在实例方法或构造函数中,this
通常用于引用当前对象的变量或方法。当类的成员变量与局部变量重名时,我们可以使用this
来区分它们。此外,this
还可以用于在一个构造函数中调用另一个构造函数; -
super
关键字:super
是一个引用变量,它指向当前对象的父类。我们可以使用super
来访问父类的变量和方法。当子类需要调用父类的构造函数或者需要访问父类的方法时,我们可以使用super
。此外,如果子类重写了父类的方法,我们也可以通过super
来调用父类的原始方法。
4.4、子类中方法的重写
在子类中,可以重写(override)父类的方法,以提供特定于子类的实现。重写方法时,方法名、返回类型和参数列表必须与父类方法一致。使用 @Override
注解可以帮助编译器检查方法是否正确重写。
方法重写的规则如下:
- 方法名和参数列表必须相同:只有当子类方法的方法名和参数列表与父类方法完全相同时,才能被视为重写;
- 返回值类型:
- 如果方法的返回值是基本数据类型,那么子类重写的方法的返回值类型必须与父类相同;
- 如果方法的返回值是引用数据类型,那么子类重写的方法的返回值类型可以是父类方法返回值类型的子类型(协变返回类型);
- 访问权限:子类重写的方法的访问权限不能小于父类方法的访问权限。例如,父类的方法是
protected
,子类的重写方法可以是protected
或public
,但不能是private
; - 异常:子类重写的方法抛出的异常类型必须是父类方法抛出的异常类型或其子类型。
final
方法:被final
修饰的方法不能被重写。private
方法:被private
修饰的方法不能被重写。- 静态方法:静态方法不能被重写,如果子类中定义了与父类中静态方法相同的方法,那么这个方法不是重写父类的方法,而是隐藏了父类的方法。
以下是一个示例,展示了继承和方法重写的应用:
class Parent {public String name = "Parent";// 父类方法public void showMessage() {System.out.println("This is the parent class.");}// 父类静态方法public static void staticMethod() {System.out.println("Static method in parent class.");}// final 方法public final void finalMethod() {System.out.println("Final method in parent class.");}
}class Child extends Parent {public String name = "Child";// 重写父类方法@Overridepublic void showMessage() {System.out.println("This is the child class.");}// 子类静态方法,隐藏父类静态方法public static void staticMethod() {System.out.println("Static method in child class.");}// 尝试重写 final 方法会导致编译错误// public void finalMethod() {// System.out.println("Cannot override final method.");// }public void displayNames() {System.out.println("Name in child class: " + name);System.out.println("Name in parent class: " + super.name);}
}public class Main {public static void main(String[] args) {Child child = new Child();child.showMessage(); // 输出 "This is the child class."child.displayNames(); // 输出子类和父类的 name 属性child.finalMethod(); // 输出 "Final method in parent class."// 调用静态方法Parent.staticMethod(); // 输出 "Static method in parent class."Child.staticMethod(); // 输出 "Static method in child class."// 父类引用指向子类对象Parent parent = new Child();parent.showMessage(); // 输出 "This is the child class."parent.staticMethod(); // 输出 "Static method in parent class."}
}
代码解析:
- 成员变量调用:
Child
类中定义了一个与Parent
类同名的成员变量name
。在displayNames
方法中,使用super.name
访问父类的name
变量; - 方法调用和重写:
- 子类重写了父类的
showMessage
方法。调用child.showMessage()
时,输出 “This is the child class.”; - 静态方法
staticMethod
在子类中定义后隐藏了父类的静态方法。调用Parent.staticMethod()
和Child.staticMethod()
时,分别输出不同的信息;
- 子类重写了父类的
final
方法:子类无法重写父类的finalMethod
方法,尝试重写会导致编译错误。
5、Object
类
Object
类是所有类的超类:在 Java 中,所有的类都直接或间接继承自 Object
类。Object
类是 Java 类层次结构的根类,它提供了一些通用的方法,这些方法可以被所有类使用或重写。
5.1、Object
类的重要方法
以下是 Object
类提供的一些重要方法:
equals(Object obj)
:用于比较两个对象是否相等。默认实现是比较对象的引用地址,但可以在子类中重写这个方法来比较对象的内容。
@Override
public boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null || getClass() != obj.getClass()) {return false;}MyClass myClass = (MyClass) obj;return this.field.equals(myClass.field);
}
hashCode()
:返回对象的哈希码。哈希码用于哈希表,如HashMap
。如果重写了equals
方法,也应该重写hashCode
方法,以确保相等的对象具有相等的哈希码。
@Override
public int hashCode() {return Objects.hash(field);
}
toString()
:返回对象的字符串表示。默认实现返回对象的类名和哈希码,可以在子类中重写这个方法以提供更有意义的字符串表示。
@Override
public String toString() {return "MyClass{" +"field='" + field + '\'' +'}';
}
clone()
:创建并返回当前对象的副本。需要实现Cloneable
接口,并重写clone
方法。
@Override
protected Object clone() throws CloneNotSupportedException {return super.clone();
}
finalize()
:对象被垃圾回收器回收之前调用的方法。通常不需要重写这个方法,依赖于垃圾回收器来管理资源。
@Override
protected void finalize() throws Throwable {super.finalize();
}
getClass()
:返回对象的运行时类。
Class<?> clazz = obj.getClass();
notify()
、notifyAll()
和wait()
:用于线程间通信。这些方法与对象的监视器相关联,用于协调线程间的协作。
synchronized (obj) {obj.notify();
}
5.2、Object
类的使用示例
以下是一个示例,展示了如何使用 Object
类的这些方法:
import java.util.Objects;public class MyClass {private String field;public MyClass(String field) {this.field = field;}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null || getClass() != obj.getClass()) {return false;}MyClass myClass = (MyClass) obj;return Objects.equals(field, myClass.field);}@Overridepublic int hashCode() {return Objects.hash(field);}@Overridepublic String toString() {return "MyClass{" +"field='" + field + '\'' +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public static void main(String[] args) throws CloneNotSupportedException {MyClass obj1 = new MyClass("value");MyClass obj2 = new MyClass("value");System.out.println("Equals: " + obj1.equals(obj2)); // 输出 trueSystem.out.println("HashCode obj1: " + obj1.hashCode()); // 输出 obj1 的哈希码System.out.println("HashCode obj2: " + obj2.hashCode()); // 输出 obj2 的哈希码System.out.println("ToString: " + obj1.toString()); // 输出 obj1 的字符串表示MyClass obj3 = (MyClass) obj1.clone();System.out.println("Clone: " + obj3.toString()); // 输出 obj3 的字符串表示synchronized (obj1) {obj1.notify();}}
}
6、特性:多态
6.1、多态概述
多态是面向对象编程中的一个重要概念,主要有以下几个特点和优点:
-
多种形态:多态是指一个对象可以有多种形态。在 Java 中,一个子类的对象既可以作为子类的引用,也可以作为父类的引用。这就是多态的体现,也就是父类引用变量可以指向子类对象。
-
多态的定义格式:在 Java 中,多态可以通过以下三种方式来定义:
- 普通类:
父类 变量名 = new 子类();
- 抽象类:
抽象类 变量名 = new 抽象类子类();
- 接口:
接口 变量名 = new 接口实现类();
- 普通类:
-
优点:多态可以提高代码的可维护性和扩展性。通过多态,我们可以编写出更加通用的代码,这些代码对于不同的对象可以有不同的行为。
6.2、注意事项
在 Java 中使用多态时,需要注意以下几点:
-
多态的类型:Java 中的多态主要是运行时多态,也就是在运行时才确定具体调用哪个对象的方法;
-
继承或实现关系:多态必须在有继承或实现关系的类之间才能实现。也就是说,一个父类的引用可以指向它的子类对象,或者一个接口的引用可以指向它的实现类对象;
-
方法重写:在多态中,同一个父类的方法可能会被不同的子类重写。当调用这个方法时,实际调用的是各个子类重写后的方法;
-
成员访问:在多态中,成员变量的访问遵循“编译看左边,运行看左边”的原则。也就是说,编译时参考的是引用变量的类型(左边),运行时调用的也是引用变量类型对应的方法,如果子类中没有重写这个方法,那么就调用父类的方法。
6.3、编译时多态与方法签名
编译时多态,也被称为方法重载(Overload),是指在同一个类中定义多个同名但参数列表不同的方法。编译器会根据方法的签名(方法名和参数列表)来确定具体调用哪个方法。
示例:
public class OverloadExample {public void print() {System.out.println("No parameters");}public void print(String s) {System.out.println("String parameter: " + s);}public static void main(String[] args) {OverloadExample example = new OverloadExample();example.print(); // 调用无参数的方法example.print("Hello"); // 调用有一个字符串参数的方法}
}
6.4、运行时多态
运行时多态,也被称为动态绑定或方法重写(Override),是指在运行时才确定具体调用哪个对象的方法。
示例:
class Animal {public void makeSound() {System.out.println("Animal makes a sound");}
}class Dog extends Animal {@Overridepublic void makeSound() {System.out.println("Dog barks");}
}class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("Cat meows");}
}public class PolymorphismExample {public static void main(String[] args) {Animal myAnimal = new Dog(); // 向上转型myAnimal.makeSound(); // 输出 "Dog barks"myAnimal = new Cat(); // 向上转型myAnimal.makeSound(); // 输出 "Cat meows"}
}
6.5、向上转型
向上转型是 Java 中多态的一种表现形式,将子类对象赋值给父类引用,这个过程也被称为隐式转型或自动转型。
示例:
Animal myAnimal = new Dog(); // Dog 对象被赋值给 Animal 类型的引用
myAnimal.makeSound(); // 调用 Dog 的 makeSound 方法
6.6、向下转型
向下转型是将已经向上转型的父类引用转换为子类引用,这个过程需要使用强制类型转换。注意,直接创建的父类对象是无法向下转型的。
示例:
Animal myAnimal = new Dog(); // 向上转型
Dog myDog = (Dog) myAnimal; // 向下转型
myDog.makeSound(); // 调用 Dog 的 makeSound 方法
需要注意的是,在进行向下转型时,可能会出现 ClassCastException
类型转换异常。因此,在进行向下转型之前,必须进行类型判断,可以使用 instanceof
关键字来判断。
6.7、instanceof
关键字
instanceof
是 Java 中的一个关键字,主要用于判断一个对象是否是某个类的实例,或者一个引用变量是否是某个类型的引用。
示例:
if (myAnimal instanceof Dog) {Dog myDog = (Dog) myAnimal;myDog.makeSound();
}
在这个例子中,只有当 myAnimal
是 Dog
的实例时,才会进行向下转型,避免了 ClassCastException
异常。
相关文章:

Java 面向对象 -- Java 语言的封装、继承、多态、内部类和 Object 类
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 007 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…...

【C++】和【预训练模型】实现【机器学习】【图像分类】的终极指南
目录 💗1. 准备工作和环境配置💕 💖安装OpenCV💕 💖安装Dlib💕 下载并编译TensorFlow C API💕 💗2. 下载和配置预训练模型💕 💖2.1 下载预训练的ResNet…...

HTML5 Web SQL数据库:浏览器中的轻量级数据库解决方案
在HTML5时代,Web开发迎来了一系列创新特性,其中之一便是Web SQL数据库。尽管Web SQL标准已被W3C废弃,转而推荐IndexedDB作为替代,但了解Web SQL对于学习Web存储技术的演进历程仍有其价值。本文将详细介绍Web SQL数据库的基本概念、…...

C++ const关键字有多种用法举例
C const关键字有多种用法 可以用来修饰变量、指针、函数参数、成员函数等。可以看到const在C中有多种用法,主要用于保证数据的不可变性,增强代码的安全性和可读性。在实际编程中,根据需要选择适当的const用法,可以有效避免意外修…...

Makefile-快速掌握
引用 本文完全参照大佬的文档写的,写这篇文章只是为了梳理一下知识 https://github.com/marmotedu/geekbang-go/blob/master/makefile/Makefile%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md 介绍 Makefile是一个工程文件的编译规则,描述了整个工程的编译…...

定个小目标之刷LeetCode热题(20)
这题与上一题有一点不同,上一题是判断链表是否存在环,这题是寻找入环的第一个节点,有一个规则是这样的,在存在环的情况下,运用快慢指针判断是否有环结束时,把快指针指向头结点,慢指针不变&#…...

短剧分销小程序:影视产业链中的新兴力量
一、引言 在数字化浪潮的推动下,影视产业正迎来一场深刻的变革。短剧分销小程序作为这场变革中的新兴力量,正以其独特的魅力和价值,逐渐在影视产业链中崭露头角。本文将探讨短剧分销小程序在影视产业链中的新兴地位、其带来的变革以及未来的…...

使用fvm切换flutter版本
切换flutter版本 下载fvm 1、dart pub global activate fvm dart下载fvm 2、warning中获取下载本地的地址 3、添加用户变量path: 下载地址 终端查看fvm版本 fvm --version 4、指定fvm文件缓存地址 fvm config --cache-path C:\src\fvm(自定义地址&…...

python通过selenium实现自动登录及轻松过滑块验证、点选验证码(2024-06-14)
一、chromedriver配置环境搭建 请确保下载的驱动程序与你的Chrome浏览器版本匹配,以确保正常运行。 1、Chrome版本号 chrome的地址栏输入chrome://version,自然就得到125.0.6422.142 版本 125.0.6422.142(正式版本) (…...

【C++】开源项目收集
C 是一种强大的、静态类型的通用编程语言,它的开源生态系统非常丰富,拥有众多高质量的项目。以下是一些知名的C开源项目: Boost: 这是一个庞大的库集合,提供了大量的实用工具和组件,如文件系统、网络编程、智能指针等&…...

爬虫相关面试题
一,如何抓取一个网站? 1,去百度和谷歌搜一下这个网站有没有分享要爬取数据的API 2, 看看电脑网页有没有所需要的数据,写代码测试调查好不好拿,如果好拿直接开始爬取 3,看看有没有电脑能打开的手机网页&a…...

Spring Cloud Netflix 之 Ribbon
前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言前言1、负载均衡1.1、服务端负载均衡1.2、客户端负载均衡 2、Ribbon实现服务…...

C语言怎样记住那么多的颜⾊?
一、问题 ⾚、橙、⻩、绿、⻘、蓝、紫,如此之多的颜⾊,数字不好记,英⽂看程序还可以, 直接写也不好写。那么怎样记住那么多的颜⾊呢? 二、解答 颜⾊枚举值如下: enum COLORS {BLACK, /*O⿊*/BLUE, …...

LabVIEW软件开发任务的工作量估算方法
在开发LabVIEW软件时,如何准确估算软件开发任务的工作量。通过需求分析、功能分解、复杂度评估和资源配置等步骤,结合常见的估算方法,如专家判断法、类比估算法和参数估算法,确保项目按时按质完成,提供项目管理和资源分…...

【已解决】引入 element 组件无法使用编译错误 ERROR Failed to compile with 1 error
如果大家使用这个vue 配合 element 框架不熟练,当你顺利按照文档安装好 vue 和 element 的时候想要使用element 的组件时候确无法展示出来,甚至报错。不妨看看是不是这个问题, 1.首先使用element 的时候,前提是把必须要的 elemen…...

Prometheus的四种指标类型
目录 一、Counter 计数器 1.1Counter 是计数器类型 1.2Counter 类型示例 二、Gauge 仪表盘 2.1Gauge是测量器类型 2.2Gauge 类型示例 三、Histogram 累积直方图 3.1Histogram 作用及特点 3.2使用 histogram 柱状图 四、Summary 摘要 一、Counter 计数器 1.1Counter …...

FastDFS SpringBoot 客户端 Demo搭建,支持文件上传下载
一、准备 fastdfs-client-java 依赖包 1、从 Git 下载 FastDFS java client SDK 源码 https://github.com/happyfish100/fastdfs-client-java.git<fastdfs-client-java 源码见附件> 2、使用ant从源码构建 ant clean package3、使用maven从源码安装 mvn clean instal…...

十大成长型思维:定位思维、商业思维、时间管理思维、学习成长思维、精力管理思维、逻辑表达思维、聚焦思维、金字塔原理、目标思维、反思思维
一、定位思维 定位思维是一种在商业和管理领域中至关重要的思维模式,它涉及到如何在顾客心智中确立品牌的独特位置,并使其与竞争对手区分开来。以下是关于定位思维的清晰介绍: 1、定义 定位思维是一种从潜在顾客的心理认知出发,通…...

GraphQL(9):Spring Boot集成Graphql简单实例
1 安装插件 我这边使用的是IDEA,需要先按照Graphql插件,步骤如下: (1)打开插件管理 在IDEA中,打开主菜单,选择 "File" -> "Settings" (或者使用快捷键 Ctrl Alt S …...

vue3+ Element-Plus 点击勾选框往input中动态添加多个tag
实现效果: template: <!--产品白名单--><div class"con-item" v-if"current 0"><el-form-item label"平台名称"><div class"contaion" click"onclick"><!-- 生成的标签 …...

唯美仙侠手游【九幽仙域】win服务端+GM后台+详细教程
资源下载地址:九幽仙域搭建-...

Qt creator day2练习
使用手动连接,将登录框中的取消按钮使用第二种方式,右击转到槽,在该函数中,调用关闭函数,将登录按钮使用Qt4版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为“admin”,密…...

哪里有海量的短视频素材,以及短视频制作教程?
在当下,短视频已成为最火爆的内容形式之一,尤其是在抖音上。但很多创作者都面临一个问题:视频素材从哪里来?怎么拍摄才能吸引更多观众?别担心,今天我将为大家推荐几个宝藏网站,确保你素材多到用…...

文章MSM_metagenomics(三):Alpha多样性分析
欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2 介绍 本教程使用基于R的函数来估计微生物群落的香农指数和丰富度,使用MetaPhlAn prof…...

Web前端与其他前端:深度对比与差异性剖析
Web前端与其他前端:深度对比与差异性剖析 在快速发展的前端技术领域,Web前端无疑是其中最耀眼的明星。然而,当我们谈论前端时,是否仅仅指的是Web前端?实际上,前端技术还包括了许多其他细分领域。本文将从四…...

AI 客服定制:LangChain集成订单能力
为了提高AI客服的问题解决能力,我们引入了LangChain自定义能力,并集成了订单能力。这使得AI客服可以根据用户提出的问题,自动调用订单接口,获取订单信息,并结合文本知识库内容进行回答。这种能力的应用,使得…...

【计算机毕业设计】242基于微信小程序的外卖点餐系统
🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板ÿ…...

java程序监控linux服务器硬件,cpu、mem、disk等
实现 使用Oshi和Hutool工具包1、pom依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.github.oshi</groupId>&l…...

高考报志愿闲谈
当你的朋友在选择大学和专业时寻求建议,作为一名研究生并有高考经验的人,你可以提供一些有价值的见解和建议。 兴趣与职业目标: 首先询问他对哪些工科领域感兴趣,如机械工程、电子工程、计算机科学等。探讨他的职业目标。了解他将…...

面试官考我Object类中的所有方法及场景使用?我...
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java 知识点啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯&a…...