当前位置: 首页 > news >正文

类和对象(5)——抽象类和接口

目录

1. 抽象类

1.1 抽象类的概念

1.2 抽象类语法:abstract关键字

1.3 抽象类的特性

1.4 抽象类的作用

2. 接口

2.1 接口的概念

2.2 接口语法:interface关键字

2.3 接口的实现:implements关键字

2.4 接口的特性

2.5 实现多个接口

2.6 接口间的继承

2.7 接口的多态性

2.8 再谈instanceof

2.8.1 检查接口的实现

2.8.2 类型可见性问题

2.8.3 易混淆的可见性

3. 抽象类与接口的区别


1. 抽象类

1.1 抽象类的概念

在面向对象的概念中,所有的对象都是通过类来描绘的;但是反过来,并不是所有的类都是用来描绘对象的,如果 一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

  • 抽象类是一种不能被实例化,只能用作其他类的父类的类。它通常用于定义一组具有共同特征和行为的子类的基础框架,这些共同特征和行为以抽象方法的形式呈现,子类需要提供这些抽象方法的具体实现。

1.2 抽象类语法:abstract关键字

那么在java语言中,抽象类要如何表示呢?

java提供了一个abstract关键字,被该关键字修饰的类就是抽象类。

抽象类的语法:

(其他修饰词)  abstract  class 抽象类名{

        ……

}

abstract除了可以修饰类,还可以修饰成员方法使其成为抽象方法。需要注意的是,抽象方法只能存在于抽象类当中

抽象方法的语法:

(其他修饰词)  abstract  class 抽象类名{

        ……

        (其他修饰词)  abstract  返回值类型  抽象方法名 (参数表);   //抽象方法无具体实现

        ……

}

例如:

public abstract class Animal {private String name;private int age;//抽象方法abstract public void eat();
}

1.3 抽象类的特性

抽象类具有很多的特性和使用要求,我在下面一一列举出来。

1. 抽象类不能被直接实例化成对象。

以上面抽象类Animal为例:

其实这样的要求也很好理解,因为抽象类的产生就不是为了描述对象的,它也没有包含足够的信息来描绘一个具体的对象,必须由它的非抽象子类来实例化对象。


2. 抽象类被继承后,其子类要重写父类中的抽象方法否则子类也必须设为抽象类,被abstract修饰。

子类Dog没有重写抽象方法,且没有设为抽象类而报错:

package demo3;    //包名:demo3
//抽象父类Animal
public abstract class Animal {public String name;public int age;//抽象方法abstract public void eat();
}
//Dog类继承自抽象类
public class Dog extends Animal{public void bark(){System.out.println(name+"在汪汪叫");}
}

补充:非抽象子类需要重写的抽象方法都来自其直接父类的抽象方法

假如有A、B、C三个类,A是B的直接父类,B是C的直接父类;A和B都是抽象类,C是普通类。如果B重写了A中的部分抽象方法,那么C要重写的抽象方法有 A剩下的抽象方法 B新增加的抽象方法

例如:

​//抽象类Animal
public abstract class Animal {public String name;//2个抽象方法abstract public void eat();abstract public void sleep();
}
//抽象类Dog
public abstract class Dog extends Animal{//重写了抽象方法eat()public void eat(){System.out.println(name+"在吃狗粮");}//新增1个抽象方法walk()abstract public void walk();
}
//普通类 柯基
public class Corgi extends Dog{//报错:没有重写抽象方法sleep()和walk()
}

这里Dog继承自Animal,所以Dog包含成员变量name、父类方法eat和sleep 以及自己新增的抽象方法walk。

又因为Dog重写了抽象方法eat,eat方法在Dog类已经不是抽象方法,所以Dog类中只有sleep和walk两个抽象方法。

由于非抽象子类需要重写的抽象方法都来自其直接父类的抽象方法,所以柯基Corgi类必须要重写sleep和walk这两个直接来自Dog类的抽象方法。


3. 抽象方法不能被private、final和static修饰,因为抽象方法要被子类重写。


4. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量。


5. 抽象类中不一定有抽象方法,但是抽象方法只能存在于抽象类当中

无抽象方法的抽象类:

报错·含抽象方法的普通类:

1.4 抽象类的作用

抽象类本身不能被实例化,要想使用,只能创建该抽象类的子类。 然后让子类重写抽象类中的抽象方法。

有些同学可能会说了, 普通的类也可以被继承呀, 普通的方法也可以被重写呀, 为啥非得用抽象类和抽象方法呢?

确实如此. 但是使用抽象类相当于多了一重编译器的校验.

使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类 了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.

很多语法存在的意义都是为了 "预防出错", 例如我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不 就相当于常量嘛? 但是加上 final 能够在不小心误修改的时候, 让编译器及时提醒我们. 充分利用编译器的校验, 在实际开发中是非常有意义的

2. 接口

2.1 接口的概念

在现实生活中,接口的例子比比皆是,比如:笔记本上的USB口,电源插座等。

电脑侧面的USB口上,可以插:U盘、鼠标、键盘...所有符合USB协议的设备

电源插座的插孔上,可以插:电脑、电视机、电饭煲...所有符合规范的设备

通过上述例子可以看出:接口就是公共的行为规范标准。大家在实现时,只要符合规范标准,就可以通用

我们知道,在编程上我们用类来描述对象,像电脑、鼠标、U盘这些对象都可以用类来描述。自然的,我们也会有编程上的接口。

在Java中,接口可以看成是多个类的公共规范,也是一种引用数据类型。

2.2 接口语法:interface关键字

接口的语法格式 与 类的语法格式类似,将 class关键字 换成 interface关键字,就定义了一个接口。

接口的语法格式:

(其他限定词)  interface  接口名{

        ……

}

例如:写一个图形接口,规范是要实现画图形方法draw。

public interface IShape {void draw();    //画一个图形
}

注意:

  • 接口的命名采用大驼峰命名法。
  • 接口的命名一般以大写字母 I 开头,它的后一个字母也要大写。

2.3 接口的实现:implements关键字

接口不能直接使用,必须要有一个"实现类"来"实现"该接口。而实现指的是:重写接口中的所有抽象方法。(在接口中定义的方法都是抽象方法)

在java中,提供一个关键字implements来让我们完成对接口的实现

实现的语法:

(其他限定词) class 类名 implements 接口名{

        ……

        //重写的接口方法

}

例如:

//接口
public interface IShape {void draw();    //画一个图形
}//实现类
public class Flower implements IShape{@Overridepublic void draw() {System.out.println("画一朵花……");}
}//测试
public class Test {public static void main(String[] args) {IShape iShape = new Flower();//向上转型iShape.draw();}
}

可以看到,实现了接口,可以通过向上转型的方式来调用接口函数,这是接口多态性的一种体现。

2.4 接口的特性

1. 与抽象类一样,接口虽是一种引用类型,但是不能直接new接口的对象

例如:


2. 接口中的成员变量都是被“ public static final ”修饰的。

也就是说,接口中的成员变量是一种静态全局常量。无论是无修饰(default),还是显式用public修饰、static修饰或final修饰,它们最终都是由“ public static final共同修饰

以下面的USB接口为例:

public interface USB {double brand = 10;
}


3. 接口中的方法都是由“ public abstract ”修饰。

无论是无修饰(default),还是显式用public修饰或abstract修饰,接口方法都是由public abstract共同修饰。也就是说接口方法都是公共的抽象方法,必须要求实现类进行方法重写,这体现了接口作为公共规范的作用

例如:

// 接口IShape

// Flower类

Flower类没有重写IShape接口的draw方法,由于接口方法都是抽象的,所以会报错。

补充:如果实现类没有重写接口的所有抽象方法,那么该实现类要设为抽象类


4. 由于接口的变量和方法都有固定的修饰符修饰,所以不能用其他修饰符 修饰接口的变量和方法。(比如private、protected)

错误例子:

补充:接口的变量和方法都有默认修饰符,一般建议接口的变量和方法前面都不写任何修饰符


5. 接口中不能有静态代码块动态代码块构造方法

静态代码块一般用来初始化静态变量,动态代码块和构造方法一般用来初始化成员变量,但是接口中的变量都是常量,不能修改。

错误例子:

public interface USB {int BRAND = 10;static {//静态代码块}{//实例代码块}USB(int brand){BRAND = brand;}
}


6. 实现类重写接口方法时,重写的方法的包访问权限不能比接口方法的权限要低。即:不能是无修饰词(default)、不能是protected、不能是private

例如:

【补充:其实 实现类的重写方法的访问权限在一种情况可以是无修饰词(default)的,这种情况我在第8点说】


7(小知识). 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class


8(拓展). 从Java8版本开始,接口中可以定义default方法(默认方法)。它允许在接口中为方法提供默认的实现。

default方法在接口中的定义方式:

  • 显示使用default关键字:在接口的方法签名前使用default关键字来定义一个默认方法。例如,default void methodName() {...}
  • 包含方法体:与接口中的抽象方法不同,默认方法是具体的方法实现,需要在接口中给出方法的具体代码逻辑

【注意】: 接口方法被default修饰后,就不能再被final和static修饰。

例如:

//图形·接口
public interface IShape {//抽象方法void draw1();//默认方法default  void draw2(){System.out.println("画两次图形");}
}
//圆形·类 :只重写抽象方法
public class Circle implements IShape{@Overridepublic void draw1() {System.out.println("画一个圆……");}
}
//花形·类:抽象方法和默认方法都重写了
public class Flower implements IShape{@Overridepublic void draw1() {System.out.println("画一朵花……");}@Overridepublic void draw2() {System.out.println("画两朵花");}
}public class Test {public static void main(String[] args) {Circle circle = new Circle();circle.draw1();circle.draw2();    //会使用接口的默认方法System.out.println("============================");Flower flower = new Flower();flower.draw1();flower.draw2();}
}

【这里的第8点特性属于拓展内容,了解即可】


2.5 实现多个接口

java中没有多继承,即一个子类不能继承自多个父类,但是一个类可以实现多个接口。

语法格式:(所有的接口都跟在implements的后面,每个接口之间用逗号隔开)

【无继承】

  class 实现类 implements 接口1,接口2,……,接口K{

          ……  //实现类的成员

  }

【有继承】(只能有一个父类) (“继承extends”要在“实现implements”前面)

  class 实现类 extends 父类名称 implements 接口1,接口2,……,接口K{

          ……  //实现类的成员

  }

下面演示如何用接口和继承来表示企鹅类:

先有父类Animal:

abstract public class Animal {protected String name;public Animal(String name){this.name = name;}
}

另外我们再提供一组接口, 分别表示 "会飞的", "会跑的", "会游泳的":

 interface IFlying {void fly();}interface IRunning {void run();}interface ISwimming {void swim();}

最后我们创建具体的动物——企鹅类(企鹅既能在路上走,也能在水中游

public class Penguin extends Animal implements IRunning,ISwimming{public Penguin(String name) {super(name);}@Overridepublic void run() {System.out.println(name+"用两只脚走路");}@Overridepublic void swim() {System.out.println(name+"用两只翅膀游泳");}
}

tips:在IDEA中使用 ctrl + i 可快速实现接口。

2.6 接口间的继承

类与类之间可以有继承关系,那接口与接口之间可以有继承关系吗?

接口与接口之间可以有继承关系,而且接口可以多继承,即一个接口可以继承自多个接口。

语法格式:(继承语法是extends,每个父接口之间用逗号隔开)

interface 子接口 extends 父接口1,父接口2,……,父接口k{

        ……

}

青蛙是两栖动物,我们用接口间的继承可以这样表示:

interface IRunning {void run();}interface ISwimming {void swim();}// 两栖的动物:既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {}class Frog implements IAmphibious {...}

2.7 接口的多态性

当实现类实现了接口,那么它就可以向接口类型进行向上转型。这体现了接口的多态性。

接口不仅仅是一种规范标准,它还是一种引用类型,这样的设计提高了代码的可重复性。

【实现多个接口】

实现类实现了多个接口,那么被实现的接口都可以接收实现类的向上转型。

例如:

//接口
public interface ISwimming {void swim();
}public interface IRunning {void run();
}
//实现类
public class Penguin implements ISwimming,IRunning{@Overridepublic void swim() {System.out.println("企鹅游泳");}@Overridepublic void run() {System.out.println("企鹅走路");}
}public class Dog implements IRunning{@Overridepublic void run() {System.out.println("狗在奔跑");}
}//多态方法
public class Test {public static void swim(ISwimming iSwimming){   //ISwimming接口类型作为多态类型参数iSwimming.swim();   //方法会根据动态绑定来使用}public static void run(IRunning iRunning){      //IRunning接口类型作为多态类型参数iRunning.run();}public static void main(String[] args) {Penguin penguin = new Penguin();swim(penguin);     //向上转型传参run(penguin);System.out.println("==============");Dog dog = new Dog();run(dog);}
}

这里的Penguin类实现了ISwimming接口和IRunning接口,所以swim方法和run方法可以完成对penguin的向上转型。


【接口间的继承】

如果子接口继承自父接口,而实现类“直接实现”的是子接口,那么父接口也可以接收实现类的向上转型

例如:

//IAmphibious接口继承自上面的ISwimming、IRunning接口
public interface IAmphibious extends ISwimming,IRunning{}//Penguin类直接实现IAmphibious接口
public class Penguin implements IAmphibious{@Overridepublic void swim() {System.out.println("企鹅游泳");}@Overridepublic void run() {System.out.println("企鹅走路");}
}public class Test {public static void swim(ISwimming iSwimming){   //ISwimming接口类型作为多态类型参数iSwimming.swim();   }public static void run(IRunning iRunning){      //IRunning接口类型作为多态类型参数iRunning.run();}public static void main(String[] args) {Penguin penguin = new Penguin();swim(penguin);     run(penguin);}
}

  • Penguin类实现了Imphibious接口,所以Penguin可以向Imphibious转型。
  • 而Imphibious继承自ISwimming接口和IRunning接口,所以Imphibious可以向ISwimming接口和IRunning接口转型。
  • 于是乎Penguin可以向ISwimming接口和IRunning接口向上转型

【注意】

如果子接口继承自父接口,实现类直接实现的也是这个父接口,那么该实现类不能向子接口进行向上转型。

错误例子:

//父接口
public interface IRunning {void run();
}//子接口:表示爬行类的动物
public interface ICreeping extends IRunning{
}//实现类:蜥蜴
public class Lizard implements IRunning{@Overridepublic void run() {System.out.println("蜥蜴在快速爬行");}
}//用子接口ICreeping接收实现类Lizard
public class Test {public static void run(ICreeping iCreeping){      iCreeping.run();}public static void main(String[] args) {Lizard lizard = new Lizard();run(lizard);        //报错:Lizard类型与ICreeping类型不兼容}
}


接口多态性与继承多态性的对比:

2.8 再谈instanceof

2.8.1 检查接口的实现

我在《类和对象(4)——多态》中讲解过instanceof关键字,当时说过“该关键字不仅能判断类,还能判断接口”。但当时还没学到接口,现在让我们看看instanceof对于接口的作用。

instanceof的作用:(对象  instanceof  类名/接口名)

  • 对于类:检查对象是否指定类型的实例,或该类型的子类实例
  • 对于接口:检查对象是否实现了指定接口,或该接口的父接口

为什么instanceof检查类的时候,可以检查其子类,而在检查接口的时候,却是可以检查其父接口呢?

这就不得不说一下instanceof检查的实际用途了:

类和instanceof的用途:确保向下转型的安全,从而让子类实例变量接收向下转型后的父类实例变量,使用子类特有的功能

接口和instanceof的用途:确保对象具有某类多态行为,从而调用该多态方法

类的举例和解析:

abstract public class Animal {public String name;public Animal(String name){this.name = name;}
}public class Dog extends Animal{public Dog(String name) {super(name);}public void eat(){System.out.println(super.name+"在吃狗粮");}
}public class Corge extends Dog{public Corge(String name) {super(name);}public void eat(){System.out.println(name+"在吃科技合成肉");}
}public class Test {public static void main(String[] args) {Animal animal1 = new Dog("小狗");if (animal1 instanceof Dog){    //检查为Dog类的实例Dog dog = (Dog) animal1;dog.eat();}Animal animal2 = new Corge("小柯基");if(animal2 instanceof Dog){     //检查为Dog类的子类实例Dog dog = (Dog) animal2;dog.eat();}}
}

  • Dog类和Corge类都有自己特有的eat方法
  • 在animal1中,由于对象的本质是Dog类的实例,故可以安全地将animal1向下转型成Dog类
  • 在animal2中,虽然对象的本质是Corge类的实例,但由于Corge类是Dog类的子类(即Corge类可以向上转型成Dog类),所以它也可以安全地将animal2向下转型成Dog类
  • 这就解释了:为什么instanceof能检查指定类型的子类

接口的举例和解析:

//父接口
public interface IRunning {void run();
}
public interface ISwimming {void swim();
}//子接口
public interface IAmphibious extends ISwimming,IRunning{}//实现类
public class Penguin extends Animal implements IAmphibious{@Overridepublic void swim() {System.out.println("企鹅游泳");}@Overridepublic void run() {System.out.println("企鹅走路");}
}//多态方法
public class Test {public static void run(IRunning iRunning){iRunning.run();}public static void main(String[] args) {Animal animal = new Penguin();  //向上转型if(animal instanceof IAmphibious){   检查到指定接口的父接口的run行为run( (IAmphibious)animal );         //此时调用的是Test类中的多态方法run//或写成((IAmphibious)animal).run();  此时调用的是自己的重写方法run}if(animal instanceof IRunning){      检查指定接口run((IRunning) animal);//或写成((IRunning)animal).run();}}
}

  • 子接口继承自多个父接口,实现类直接实现子接口 就相当于是 把所有父接口的行为都实现了一遍,那自然可以使用 以父接口类型为参数类型的多态方法
  • 这解释了:为什么instanceof能检查指定接口的父接口

小结:


2.8.2 类型可见性问题

如果我们将上面接口例子中Test类(含多态方法的那个)修改成下面这样会发生什么:

可以发现,我们把强制类型转换用的“(IAmphibious)”去掉后居然报错了。这是编译时类型对成员可见性的限制惹的祸。


要明白 “编译时类型对成员可见性的限制”,我们必需先了解编译时类型和运行时类型的概念。

编译时类型(也称 声明类型)

  • 变量在代码中声明的类型。(如" Parent parent;",此时实例变量parent的数据类型Parent就是编译时类型)(编译时类型也包括基础类型,如int、double)
  • 编译器仅根据此类型检查可访问的成员变量和方法。

运行时类型(也称 实际类型)

  • 对象实际所属的类型。(如“ new Child() ”)
  • 运行时动态决定,但编译时不可见

当用编译时类型的变量 访问 运行时类型的特有成员时,编译器检查发现该声明类型不具有访问特有成员的能力,直接触发了编译错误。这就是编译时类型对可见性的限制

  1. 强制转换的作用
    强制转换的本质是 告诉编译器,请按强转类型检查成员。编译器接受新的编译时类型,从而允许访问该类型定义的成员。

  2. 运行时验证
    强制转换可能在运行时失败(如 强转类型 与 对象实际类型 不符),因此需配合 instanceof 提前检查类型安全。


2.8.3 易混淆的可见性

上述发生的编译错误属于类型可见性的问题,而不是权限的问题。

成员可见性:

  • 在java中,权限指的就是各种访问修饰符
  • 成员可见性的控制机制是访问修饰符(比如public、protected),为每个成员变量和方法赋予权限。


类可见性:

  • 类可见性的控制机制也是访问修饰符,为类赋予访问权限。
  • 成员可见性是 成员变量和成员方法 被访问修饰符修饰,共有4种权限类可见性 被访问修饰符修饰,顶级类只有public类或默认类(default)2种
  • 类的可见性成员可见性的 前提。(如果顶级类是默认类,且内部所有成员都是public修饰的,那么不是同一个包的类就无法访问该顶级类及其所有成员。)

错误例子:

在包test1中有默认类Demo:

当我们在包test2中尝试使用Demo会报错:


包可见性:

  • 包可见性 = default 权限 = 包访问权限 = 仅包内可见。
  • 包可见性 包含于 成员可见性和类可见性当中。(包可见性是权限中的一种具体类型)

成员可见性和类的可见性通过访问修饰符定义,具体规则如下:


最终总结:

  1. 类可见性 和 成员可见性属于访问权限控制的同一维度(层级不同),且 类可见性是成员可见性的前提

  2. 包可见性是访问权限控制中的一种具体类型(默认修饰符),属于成员可见性和类可见性的一部分。

  3. 类型可见性是独立于访问控制的另一维度,属于编译时类型系统的限制。

3. 抽象类与接口的区别

核心区别: 抽象类中可以包含普通方法和普通字段,这样的普通方法和字段可以被子类直接使用(不必重写),而接口中不能包含普通方法(但是可以包含default方法),子类必须重写所有的抽象方法。

下面的表格是抽象类和接口不同的地方:

抽象类和接口的相同之处:

  1. 可以没有任何成员。(此时的接口被称作空接口或标记接口)
  2. 抽象方法不能被private、static、final修饰。
  3. 子类/实现类 重写方法的包访问权限不能更低。
  4. 子类/实现类 没有重写完所有的抽象方法时,必须设置为抽象类。
  5. 字节码文件的后缀都是.class。

本期分享完毕,感谢大家的支持Thanks♪(・ω・)ノ

相关文章:

类和对象(5)——抽象类和接口

目录 1. 抽象类 1.1 抽象类的概念 1.2 抽象类语法:abstract关键字 1.3 抽象类的特性 1.4 抽象类的作用 2. 接口 2.1 接口的概念 2.2 接口语法:interface关键字 2.3 接口的实现:implements关键字 2.4 接口的特性 2.5 实现多个接口 …...

海康摄像头IPV6模式,手动,自动,路由公告

海康摄像头DS-2DC7220IW-A 网络设置中的IPv6配置选项。IPv6是互联网协议(IP)的第六版,用于替代IPv4,提供更多的IP地址和改进的网络功能。图片中的选项允许用户选择如何配置设备的IPv6网络连接: 手动:用户可…...

LabVIEW与USB设备开发

开发一台USB设备并使用LabVIEW进行上位机开发,涉及底层驱动的编写、USB通信协议的实现以及LabVIEW与设备的接口设计。本文将详细介绍如何开发USB设备驱动、实现LabVIEW与USB设备的通信以及优化数据传输,帮助用户顺利完成项目开发。下面是一个详细的说明&…...

BY组态:工业自动化的未来,触手可及

在工业4.0的浪潮下,智能化、数字化已成为制造业发展的核心驱动力。作为工业自动化领域的重要工具,组态软件在实现设备监控、数据采集、流程控制等方面发挥着不可替代的作用。然而,传统的组态软件往往存在开发周期长、学习成本高、灵活性不足等…...

深入理解Python多进程编程 multiprocessing

深入理解Python多进程编程 multiprocessing flyfish Python 的 multiprocessing 模块允许创建多个进程,从而可以利用多核处理器的能力来并行执行任务。这意味着程序的不同部分可以在不同的CPU核心上同时运行,极大地提高了处理效率,特别是在…...

使用DeepSeek建立一个智能聊天机器人0.12

为了确保这段代码能够在Windows和Linux系统上都能正常运行,我考虑以下几个方面: 路径分隔符:在Windows和Linux中,文件路径的分隔符不同。Windows使用反斜杠(\),而Linux使用正斜杠(/)。我们可以使用 os.path.join 来处理路径,以确保跨平台兼容性。 消息框:tkinter.…...

基于VLC的Unity视频播放器(三)

关于UMP插件 UMP插件不更新了,我测试在Ubuntu24.04上编辑器和运行时都无法正常播放,在替换lib之后编辑器可以播放,但打包后不行……很奇怪 继续更新了一下UnityVLC 添加了对Linux的支持,勉强都可以播放了…… Win截图 Ubuntu2…...

每日一题——把数字翻译成字符串

把数字翻译成字符串 题目描述示例示例1示例2 题解动态规划代码实现复杂度分析 总结 题目描述 有一种将字母编码成数字的方式:‘a’->1, ‘b’->2, … , ‘z’->26。 现在给一串数字,返回有多少种可能的译码结果。 数据范围:字符串…...

基于状态观测器和物联网基础设施的智能电网高速孤岛检测

论文标题 中文标题&#xff1a; 基于状态观测器和物联网基础设施的智能电网高速孤岛检测 英文标题&#xff1a; High-Speed Islanding Detection in Smart Grids Using a State Observer and IoT Infrastructure 作者信息 Shahid Karim<sup>1,2, *</sup>, Prajo…...

FPGA的星辰大海

编者按 时下风头正盛的DeepSeek,正值喜好宏大叙事的米国大统领二次上岗就业,OpenAI、软银、甲骨文等宣布投资高达5000亿美元“星际之门”之际,对比尤为强烈。 某种程度上,,是低成本创新理念的直接落地。 包括来自开源社区的诸多赞誉是,并非体现技术有多“超越”,而是…...

【Black Mesa】黑山起源用服务器开服多人联机教程

1、登录服务器&#xff08;百度莱卡云游戏面板&#xff09; 进入控制面板后会出现正在安装的界面&#xff0c;安装大约10分钟&#xff08;如长时间处于安装中请联系我们的客服人员&#xff09; 2、修改端口 看到一下图片的界面时说明服务器已经安装完成&#xff0c;服务器需要…...

【学习笔记】深度学习网络-深度模型中的优化

​ 作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程&#xff0c;深度学习领域研究生必读教材),开始深度学习领域学习&#xff0c;深入全面的理解深度学习的理论知识。 在之前的文章中介绍了深度学习中…...

java八股文之Redis

1.Rdis常见的使用场景 缓存分布式锁&#xff08;redision&#xff0c;setnx&#xff09;计数器保存token消息队列延迟队列 2.说明一下缓存雪崩&#xff0c;缓存穿透和缓存击穿以及解决方式 1.缓存雪崩 定义&#xff1a; 缓存雪崩指的是当大量的缓存数据同时失效&#xff0c…...

ubuntu系统下KVM设置桥接网络(失败)

20250216 - 概述 因实验需求&#xff0c;需要设置KVM下的虚拟机采用桥接模式进行通信&#xff0c;这种方式将使虚拟机与主机类似使用同一网段的IP。实际上&#xff0c;为了实现这个功能&#xff0c;我已经在自己mac上VMware使用过&#xff0c;虚拟机获得了自己独立的IP。 但…...

CentOS 7操作系统部署KVM软件和创建虚拟机

CentOS 7.9操作系统部署KVM软件和配置指南&#xff0c;包括如何创建一个虚拟机。 步骤 1: 检查硬件支持 首先&#xff0c;确认您的CPU支持虚拟化技术&#xff0c;并且已在BIOS中启用&#xff1a; egrep -c (vmx|svm) /proc/cpuinfo 如果输出大于0&#xff0c;则表示支持虚拟…...

驱动开发系列38 - Linux Graphics 3D 绘制流程(一)- 创建画布

一:概述 当应用程序创建 OpenGL 上下文时,它通常需要申请帧缓冲(Framebuffer,即画布)。在 X11 体系下,应用程序不会直接向内核的 DRM 模块请求创建帧缓冲,而是通过 X 服务器进行申请。 虽然从技术上讲,应用程序可以直接使用 DRM 接口创建帧缓冲对象(BO),但为了将其与…...

Spring Boot过滤器链:从入门到精通

文章目录 一、过滤器链是什么&#xff1f;二、为什么需要过滤器链&#xff1f;三、Spring Boot中的过滤器链是如何工作的&#xff1f;&#xff08;一&#xff09;过滤器的生命周期&#xff08;二&#xff09;过滤器链的执行流程 四、如何在Spring Boot中定义自己的过滤器&#…...

QT 读写锁

一、概述 1、读写锁是一种线程同步机制&#xff0c;用于解决多线程环境下的读写竞争问题。 2、读写锁允许多个线程同时获取读锁&#xff08;共享访问&#xff09;&#xff0c;但只允许一个线程获取写锁&#xff08;独占访问&#xff09;。 3、这种机制可以提高并发性能&…...

C++中的智能指针

智能指针总结 智能指针其作⽤是管理⼀个指针&#xff0c;避免程序员申请的空间在函数结束时忘记释放&#xff0c;造成内存泄漏这种情况滴发⽣。使⽤智能指针可以很⼤程度上的避免这个问题&#xff0c;因为智能指针就是⼀个类&#xff0c;当超出了类的作⽤域是&#xff0c;类会…...

IntelliJ IDEA 接入 AI 编程助手(Copilot、DeepSeek、GPT-4o Mini)

IntelliJ IDEA 接入 AI 编程助手&#xff08;Copilot、DeepSeek、GPT-4o Mini&#xff09; &#x1f4ca; 引言 近年来&#xff0c;AI 编程助手已成为开发者的高效工具&#xff0c;它们可以加速代码编写、优化代码结构&#xff0c;并提供智能提示。本文介绍如何在 IntelliJ I…...

【R语言】非参数检验

一、Mann-Whitney检验 在R语言中&#xff0c;Mann-Whitney U检验&#xff08;也称为Wilcoxon秩和检验&#xff09;用于比较两个独立样本的中位数是否存在显著差异。它是一种非参数检验&#xff0c;适用于数据不满足正态分布假设的情况。 1、独立样本 # 创建两个独立样本数据…...

PyTorch 源码学习:阅读经验 代码结构

分享自己在学习 PyTorch 源码时阅读过的资料。本文重点关注阅读 PyTorch 源码的经验和 PyTorch 的代码结构。因为 PyTorch 不同版本的源码实现有所不同&#xff0c;所以笔者在整理资料时尽可能按版本号升序&#xff0c;版本号见标题前[]。最新版本的源码实现还请查看 PyTorch 仓…...

04运维实用篇(D4_日志)

目录 一、简介 二、代码中使用日志工具记录日志 1. 操作步骤 步骤1&#xff1a;添加日志记录操作 步骤2&#xff1a;设置日志输出级别 步骤3&#xff1a;设置日志组 2. 知识小结 三、优化日志对象创建代码 1. 实例 2. 总结 四、日志输出格式控制 1. 实例 2. 总结 …...

Linux文件管理:硬链接与软链接

文章目录 1. 硬链接的设计目的&#xff08;1&#xff09;节省存储空间&#xff08;2&#xff09;提高文件管理效率&#xff08;3&#xff09;数据持久性&#xff08;4&#xff09;文件系统的自然特性 2. 软链接的设计目的**&#xff08;1&#xff09;跨文件系统引用****&#x…...

【零基础学Mysql】常用函数讲解,提升数据操作效率的利器

以耳倾听世间繁华&#xff0c;以语表达心中所想 大家好,我是whisperrrr. 前言&#xff1a; 大家好&#xff0c;我是你们的朋友whisrrr。在日常工作中&#xff0c;MySQL作为一款广泛使用的开源关系型数据库&#xff0c;其强大的功能为我们提供了便捷的数据存储和管理手段。而在…...

小米平板怎么和电脑共享屏幕

最近尝试使用小米平板和电脑屏幕分屏互联 发现是需要做特殊处理的&#xff0c;需要下载一款电脑安装包&#xff1a;小米妙享 关于这个安装包&#xff0c;想吐槽的是&#xff1a; 没有找到官网渠道&#xff0c;是通过其他网络方式查到下载的 不附录链接&#xff0c;原因是因为地…...

宝藏软件系列 篇一:My APK(Android)

文章目录 系列文章官方网站特色功能同类软件 系列文章 官方网站 My APK 官方版本是在 谷歌商店 中上架的。 官方下载地址&#xff1a;Google Play 商店页面。&#xff08;需要外网&#xff09; 2025.2最新版本的CSDN本地下载地址&#xff08;因为是Android App Bundle&…...

本地 Ollama 部署 Deepseek R1 并使用 Spring AI Alibaba 构建 Chat 应用示例

本地部署 Deepseek R1 并使用 Spring AI Alibaba 构建 Chat 应用示例 Ollama 部署 Deepseek R1 官网&#xff1a;https://www.deepseek.com/ Github&#xff1a;https://github.com/deepseek-ai Ollama&#xff1a;https://ollama.com/ Docker Compose 部署一个 Ollama 和…...

centos8.0 docker ngnix

问题1&#xff1a;镜像拉取不下来&#xff0c;用DAO云加速器 问题2&#xff1a;ngnix镜像不能运行&#xff0c; 无法检索OCI运行时错误 在CentOS上使用Docker来运行Nginx是一个常见的做法&#xff0c;因为它提供了快速、一致的环境配置方式&#xff0c;并且可以很容易地扩展。…...

位运算在数据库中的运用实践-以MySQL和PG为例

目录 前言 一、两种不同的数据库设计 1、状态字段存储JSON 2、使用位运算 二、数据库中的位运算实践 1、MySQL中的位运算实践 2、PostgreSQL中位运算实践 三、总结 前言 最近在解决某用户的一个业务需求时&#xff0c;遇到一个很有意思的场景。首先先跟大家分享一下需…...

IoTDB 常见问题 QA 第五期

关于 IoTDB 的 Q & A 情人节之际&#xff0c;让 IoTDB Q&A 陪您一起共度解惑&#xff01;我们将定期汇总我们将定期汇总社区讨论频繁的问题&#xff0c;并展开进行详细回答&#xff0c;通过积累常见问题“小百科”&#xff0c;方便大家使用 IoTDB。 Q1&#xff1a;导入…...

【kafka系列】日志存储设计 消息写入、读取

目录 日志存储设计 1. 日志存储的目录结构 2. 日志内容格式设计 3. 日志索引设计 4. 设计优势 消息写入流程 示例 流程图 消息读取流程 示例 关键设计细节 流程图 日志存储设计 Kafka的日志存储是其高吞吐、持久化能力的核心设计&#xff0c;其结构包含目录组织、…...

Python实现语音识别详细教程【2025】最新教程

文章目录 前言一、环境搭建1. 下载 Python2. 安装 Python3 使用 pip 安装必要的库 二、使用 SpeechRecognition 库进行语音识别1.识别本地音频文件2.实时语音识别3. 使用其他语音识别引擎 注意事项 前言 以下是一份较为完整的 Python 语音识别教程&#xff0c;涵盖环境搭建、使…...

【一文读懂】HTTP与Websocket协议

HTTP协议 概述 HTTP (Hypertext Transfer Protocol)&#xff0c;即超文本传输协议&#xff0c;是一种用于在客户端和服务器之间传输超文本&#xff08;例如网页、图片、音频、视频等&#xff09;的通信协议。它是万维网&#xff08;WWW&#xff09;的基础&#xff0c;负责在浏…...

SpringBoot+微信小程序+数据可视化的宠物到家喂宠服务(程序+论文+讲解+安装+调试+售后等)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在经济高速发展、物质生活极大丰富的当下&#xff0c;人们的精神需求愈发凸显&#xff0…...

Windows逆向工程入门之堆栈结构与信息获取

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 1. 堆栈结构基础 堆栈的主要操作&#xff1a; 2. 代码功能解析 2.1 加载 ntdll.dll 2.2 获取 NtQueryInformationThread 函数指针 2.3 调用 NtQueryInformationThread 获取线程信息…...

springboot项目如何部署到tomcat中

1、使用springboot内部嵌入的tomcat 可以改一些tomcat的参数 2、可以把springboot项目打包为war包&#xff0c;然后部署到tomcat中去 Spring Boot 默认使用嵌入式 Tomcat 作为其 Web 容器&#xff0c;这使得 Spring Boot 应用可以作为一个独立的 JAR 文件运行。这种嵌入式服务…...

C语言之easyX

目录 概要 easyX整体架构 图形绘制 画布宽高 圆形 图片的贴图 加载图像 游戏框架 概要 easyX是一个轻量级的图形库&#xff0c;用于在Windows平台上进行简单的2D图形绘制。它提供了一组简单易用的函数&#xff0c;可以方便地绘制基本的图形元素&#xff0c;如线条、矩形、圆形…...

es6箭头函数和普通函数的区别

在JavaScript中&#xff0c;函数是执行特定任务的代码块。函数可以被定义并且随后被调用。JavaScript中有两种主要的函数定义方式&#xff1a;普通函数声明和箭头函数表达式。下面是这两种函数的定义方式及其区别和使用场景&#xff1a; 普通函数声明 普通函数可以通过函数声明…...

DeepSeek R1 32B 本地部署实战

#DeepSeek# DeepSeek是一款基于人工智能的智能助手&#xff0c;专为提升工作效率和信息获取能力而设计。它结合了自然语言处理、机器学习和大数据技术&#xff0c;能够快速理解用户需求并提供精准的答案或解决方案。 DeepSeek的核心功能 智能问答 DeepSeek可以回答各种问题&…...

八、SPI读写XT25数据

8.1 SPI 简介 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是一种同步串行通信协议&#xff0c;广泛用于嵌入式系统中连接微控制器与外围设备&#xff0c;如传感器、存储器、显示屏等。 主要特点 1. 全双工通信&#xff1a;支持同时发送…...

AIP-145 范围

编号145原文链接AIP-145: Ranges状态批准创建日期2020-05-28更新日期2020-05-28 服务通常需要表示具体值或连续值的范围。这些范围的含义存在诸多差异&#xff0c;也存在许多数据类型&#xff1a;整数、浮点数、时间戳等&#xff08;在此仅举几例&#xff09;。根据所讨论范围…...

(学习总结24)Linux 基本命令2

Linux 基本命令2 操作文件或目录命令更改文件或目录访问权限命令 chmod修改文件的所有者和所属组命令 chown修改文件或目录的所属组命令 chgrp更改文件或目录的属性命令 chattr创建文件和目录时的默认权限掩码命令 umask判断文件类型命令 file显示文件或文件系统状态命令 stat树…...

WPF-数据转换器

一、单值转换器 1.不传参数 转换器 当Value值大于100时返回红色 public class DataConverter : IValueConverter{/// <summary>/// 表示从源到目标数据转换/// </summary>/// <param name"value">数据源的值</param>/// <param name&q…...

STM32 I2C通信协议说明

目录 背景 I2C协议 数据的有效性 I2C通信开始和停止条件 I2C数据传输 发送 响应 正常情况&#xff1a; 异常情况&#xff1a; 主机结束接收 写寄存器的标准流程 读寄存器的标准流程 仲裁机制 时钟同步 SDA线的仲裁 程序 背景 对单片机的三大通信中的I2C通信进…...

网络工程师 (42)IP地址

一、定义与功能 IP地址是IP协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异。这种地址分配方式确保了用户在连网的计算机上操作时&#xff0c;能够高效且方便地从众多计算机中选出自己所需…...

Deepseek实用万能提问模板

一&#xff0c;背景需求约束条件 背景:提供与问题相关的时间、地点、人物、事件等信息&#xff0c;帮助 DeepSeek 更好地理解问题的情境。 需求:清晰明确地阐述你希望 DeepSeek完成的任务或提供的信息。 约束条件:可根据具体情况&#xff0c;对回答的范围、格式、字数等进行…...

强化学习笔记7——DDPG到TD3

前提&#xff1a;基于TD 的方法多少都会有高估问题&#xff0c;即Q值偏大。原因两个&#xff1a;一、TD目标是真实动作的高估。 二&#xff1a;自举法高估。 DDPG 属于AC方法&#xff1a;异策略&#xff0c;适合连续动作空间&#xff0c;因为他的策略网络直接输出的动作&#…...

传统混合专家模型MoE架构详解以及python示例(DeepSeek-V3之基础)

我们已经了解到DeepSeek-V3的框架结构基于三大核心技术构建:多头潜在注意力(MLA)、DeepSeekMoE架构和多token预测(MTP)。而DeepSeekMoE架构的底层模型采用了混合专家模型(Mixture of Experts,MoE)架构。所以我们先了解一下传统混合专家模型MoE架构。 一、传统混合专家模…...

开源协议深度解析:理解MIT、GPL、Apache等常见许可证

目录 前言1. MIT协议&#xff1a;自由而宽松的开源许可1.1 MIT协议的主要特点1.2 MIT协议的适用场景 2. GPL协议&#xff1a;自由软件的捍卫者2.1 GPL协议的核心理念2.2 GPL协议的适用场景 3. Apache License 2.0&#xff1a;开源与专利保护的平衡3.1 Apache License 2.0的主要…...