JAVA学习*接口
接口
在生活中我们常听说USB接口,那接口是什么呢?
在Java中,接口相当于多个类的一种公共规范,是一种引用数据类型。
定义接口
public interface IUSB {public static final String SIZE = "small";public abstract void openDevice();void closeDevice();public static void test() {System.out.println("调用静态方法test()");}public default void test1() {System.out.println("调用default修饰的test1");}
}
上述代码定义了IUSB接口。
创建接口如下:

基本语法:
public interface 接口名 {}
接口类中的成员
在接口中
1、定义成员变量:
public static final 数据类型 成员变量名 = 初始化;
编译器会默认加上public static final,所以不写这个也可以。
数据类型 成员变量名 = 初始化;
但要注意:一定要初始化,因为有final关键字
2、定义成员方法:
//抽象类方法
public abstract 返回类型 方法名();
编译器会默认加上public abstract,所以不写这个也可以。
返回类型 方法名();
一般成员方法定义为抽象方法。
由于是抽象方法,所以在接入接口的类中一定要重写抽象方法!
但接口中的方法也可以具体实现的(有两种方法)。
//1、使用static修饰
public static void test1() {}
//要调用的话,就直接 接口名.方法名
IUSB.test();
//2、使用default修饰
public default void test2() {}
//要调用的话,可以通过类的对象访问
public default void test1() {//接口中System.out.println("调用default修饰的test1()");
}
Screen screen = new Screen();//Screen是实现接口的类
screen.test1();//没有报错//要调用的话,也可以重写方法
@Override//在Screen中重写
public void test1() {System.out.println("调用重写的test1()方法");
}
Screen screen = new Screen();//Screen是实现接口的类
screen.test1();//调用
3、在接口类中,没有静态代码块和构造方法
接口的使用
基本语法:
public class 类名 implements 接口名{
}
1、接口不能直接使用,实例化对象。

2、必须要有类来接入接口。通过重写抽象方法来实现接口中的抽象方法。
public class Screen implements IUSB {@Overridepublic void openDevice() {System.out.println("打开显示屏");}@Overridepublic void closeDevice() {System.out.println("关闭显示屏");}public void show() {System.out.println("开始显示");}
}
public class Keyborad implements IUSB{@Overridepublic void openDevice() {System.out.println("启动键盘");}@Overridepublic void closeDevice() {System.out.println("关闭键盘");}public void inPut() {System.out.println("输入数据");}}
public class Computer {public void openComputer() {System.out.println("打开电脑");}public void closeComputer() {System.out.println("关闭电脑");}public void useDevice(IUSB usb){usb.openDevice();usb.test1();if(usb instanceof Screen) {Screen screen = (Screen)usb;screen.show();}if (usb instanceof Keyborad keyborad){keyborad.inPut();}usb.closeDevice();}
}
public class Test {public static void main(String[] args) {Computer computer = new Computer();computer.openComputer();computer.useDevice(new Keyborad());computer.useDevice(new Screen());computer.closeComputer();System.out.println("-----------");IUSB.test();Screen screen = new Screen();screen.test1();}
}
3、根据重写规则,重写的方法访问权限修饰符一定是public。
4、代码中的向上转型和向下转型。
发生向上转型:
computer.useDevice(new Keyborad());
computer.useDevice(new Screen());
发生向下转型:
if(usb instanceof Screen) {Screen screen = (Screen)usb;//强制类型转换screen.show();
}
if (usb instanceof Keyborad keyborad){keyborad.inPut();
}
向下转型的时候不知道实际指向是哪个引用的,这时候需要if语句来判断。
两种if的写法都是可以的。
第一种,先通过 instanceof 判断类型,再手动强制转换并声明变量。
第二种,在 instanceof 表达式中直接完成类型判断和变量声明,keyborad 会被自动推导为 Keyborad 类型,无需手动强制转换。
上述代码输出:
打开电脑
启动键盘
调用default修饰的test1()
输入数据
关闭键盘
打开显示屏
调用重写的test1()方法
开始显示
关闭显示屏
关闭电脑
-----------
调用静态方法test()
调用重写的test1()方法
实现多个接口
一个类虽然不能继承多个类,但可以使用多个接口
public class Animal {public String name;public int age;
}
public interface ISwimming {void swim();
}
public interface IRunning {void run();
}
public class Dog extends Animal implements ISwimming, IRunning {@Overridepublic void run() {System.out.println("狗在跑步");}@Overridepublic void swim() {System.out.println("狗会狗刨");}
}
public class People implements IRunning{@Overridepublic void run() {System.out.println("人在跑步");}
}
public class Test {public static void main(String[] args) {Dog dog = new Dog();dog.run();dog.swim();People people = new People();people.run();}
}
上述代码输出:
狗在跑步
狗会狗刨
人在跑步
对于Dog类来说,继承了Animal类,并使用了ISwimming和IRunning两个接口。这时候Dog类中要重写两个抽象方法。
注意:
我们此外还定义了People类,来实现IRunning接口。这时候我们并没有注重类型,而是专注于某个类具体的实现功能、能力。
在前面继承的时候说过,继承是 is - a 的关系。而接口就是 can - do 的关系,用于定义一组行为规范,一个类实现某个接口意味着它具备了该接口所定义的行为能力。
接口中的继承
public interface IRunAndSwim extends ISwimming,IRunning{void test();
}
public interface ISwimming {void swim();
}
public interface IRunning {void run();
}
public class Dog extends Animal implements IRunAndSwim {@Overridepublic void run() {System.out.println("狗在跑步");}@Overridepublic void swim() {System.out.println("狗会狗刨");}@Overridepublic void test() {System.out.println("重写test()抽象方法");}
}
接口可以继承多个接口,使用 extends 关键字。
接口中的继承有点像将一些接口拼合起来了
使用现成的接口
对象之间进行大小关系比较
使用Comparable接口
代码展示:
//定义学生类实现接口Comparable
public class Student implements Comparable<Student>{public String name;public int age;public double score;public Student(String name, int age, double score) {this.name = name;this.age = age;this.score = score;}//重写输出方法@Overridepublic String toString() {return "Student1{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//重写compareTo比较方法@Overridepublic int compareTo(Student o) {if(this.age>o.age) {return 1;}else if(this.age<o.age){return -1;}else return 0;//可以简写语句,效果是一样的//return Integer.compare(this.age, o.age);//return this.age - o.age;}
}
public class Test {public static void main(String[] args) {test1();}public static void test1() {Student student1 = new Student("zhangsan",18,99);Student student2 = new Student("lisi",20,60);if (student1.compareTo(student2) > 0) {System.out.println("student1.age > student2.age");}else if(student1.compareTo(student2) < 0) {System.out.println("student1.age < student2.age");}else System.out.println("student1.age = student2.age");}
}
输出:
student1.age < student2.age
代码解释:
1、 当我们查看Comparable接口时:
public interface Comparable<T> {public int compareTo(T o);
}
T代表泛型,里面写谁就比较谁。
根据接口知识,这时候我们需要重写compareTo方法了。
需要注意的是,其方法返回类型为int,在写返回值的时候需要注意。
2、 重写方法中的this表示调用这个方法的对象的调用。
3、 对于这个接口,是有缺点。当我们重写了compareTo方法就不能同时再重写compareTo方法来实现其他的比较(eg.比较成绩、比较姓名)
4、 为了解决这个接口的缺点,我们可以使用Comparator接口,来定义一些比较器来供我们使用。
使用Comparator接口
代码展示:
import java.util.Comparator;
//年龄比较器
public class AgeCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.age - o2.age;}
}
import java.util.Comparator;
//成绩比较器
public class ScoreCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.score,o2.score);}
}
import java.util.Comparator;
//姓名比较器
public class NameCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.compareTo(o2);//return String.CASE_INSENSITIVE_ORDER.compare(o1.name,o2.name);}
}
public class Test {public static void main(String[] args) {test2();test3();test4();}public static void test2() {Student student3 = new Student("zhangsan",21,99);Student student4 = new Student("lisi",20,60);AgeCompare ageCompare = new AgeCompare();if(ageCompare.compare(student3,student4)>0){System.out.println("student3.age > student4.age");}else if(ageCompare.compare(student3,student4)<0) {System.out.println("student3.age < student4.age");}}public static void test3() {Student student5 = new Student("zhangsan",21,91.1);Student student6 = new Student("lisi",20,91.2);ScoreCompare scoreCompare = new ScoreCompare();if(scoreCompare.compare(student5,student6)>0){System.out.println("student5.score > student6.score");}else if(scoreCompare.compare(student5,student6)<0) {System.out.println("student5.score < student6.score");}}public static void test4() {Student student7 = new Student("zhangsan",21,91.1);Student student8 = new Student("lisi",20,91.2);NameCompare nameCompare = new NameCompare();if(nameCompare.compare(student7,student8)>0){System.out.println("student7.name > student8.name");}else if(nameCompare.compare(student7,student8) < 0) {System.out.println("student7.name < student8.name");}}
}
输出:
student3.age > student4.age
student5.score < student6.score
student7.name > student8.name
代码解释:
1、 当我们查看Comparator接口时:
public interface Comparator<T> {int compare(T o1, T o2);
}
根据接口知识,这时候我们需要重写compare方法了。
(注意:Comparator接口中不只有这一个抽象方法,但现在我们只需要用这一个抽象方法)
还需要注意的是,其方法返回类型为int,在写返回值的时候需要注意。
2、 通过这个Comparator接口,我们可以实现多个比较器。当我们需要比较谁,就调用那个比较器就可以了。
3、 对于比较String类型的比较时,我们不能像比较int类型样的,返回相减的值。这时候可以调用String类中自己提供的比较方法,也可以调用compareTo方法。
这时候有人要问了,为什么可以调用compareTo方法来比较字符串大小,这不是在Comparable接口中有的吗?
当我们查看String类时,发现其实现了Comparable<T>的接口。

这时候我们可以调用compareTo方法,来实现字符串比较。
使用Comparable接口来实现自定义类型数组排序
基本数据类型的排序
public static void test() {int[] array = new int[]{1,2,3,4,3,2,6,3,8,4};Arrays.sort(array);System.out.println(Arrays.toString(array));
}
public static void main(String[] args) {People[] people = new People[3];people[0]= new People(18,"zhangsan");people[1] = new People(10,"lisi");people[2] = new People(22,"wangwu");System.out.println(Arrays.toString(people));Arrays.sort(people);//此时编译器不知道比较的那个成员变量,报错
}
这时候报错了。
这时候我们进入sort的底层逻辑代码

这时候我们发现把数组的元素强转为Comparable接口,这时候我们需要实现Comparable接口,重写compareTo方法。
实现上述代码功能
重写compareTo方法
public class People implements Comparable<People>{public int age;public String name;@Overridepublic String toString() {return "People{" +"age=" + age +", name='" + name + '\'' +'}';}public People(int age, String name) {this.age = age;this.name = name;}@Overridepublic int compareTo(People o) {return Integer.compare(this.age,o.age);}
}
import java.util.Arrays;public class Test {public static void test2() {People[] people = new People[3];people[0]= new People(18,"zhangsan");people[1] = new People(10,"lisi");people[2] = new People(22,"wangwu");System.out.println(Arrays.toString(people));Arrays.sort(people);System.out.println("-------------");System.out.println(Arrays.toString(people));}public static void main(String[] args) {test2();}
}
输出:
[People{age=18, name=‘zhangsan’}, People{age=10, name=‘lisi’}, People{age=22, name=‘wangwu’}]
-------------
[People{age=10, name=‘lisi’}, People{age=18, name=‘zhangsan’}, People{age=22, name=‘wangwu’}]
当然此代码还是存在Comparable接口中的问题,不能同时再重写compareTo方法来实现其他的比较。
使用Comparator接口,传入比较器,来进行比较
public class People implements Comparable<People>{public int age;public String name;@Overridepublic String toString() {return "People{" +"age=" + age +", name='" + name + '\'' +'}';}public People(int age, String name) {this.age = age;this.name = name;}@Overridepublic int compareTo(People o) {return Integer.compare(this.age,o.age);}
}
public class NameCompare implements Comparator<People> {@Overridepublic int compare(People o1, People o2) {return String.CASE_INSENSITIVE_ORDER.compare(o1.name,o2.name);}
}
public class AgeCompare implements Comparator<People> {@Overridepublic int compare(People o1, People o2) {return Integer.compare(o1.age,o2.age);}
}
import java.util.Arrays;public class Test {public static void test3() {People[] peoples = new People[3];peoples[0]= new People(18,"zhangsan");peoples[1] = new People(10,"lisi");peoples[2] = new People(22,"wangwu");System.out.println("------原始顺序-------");System.out.println(Arrays.toString(peoples));NameCompare nameCompare = new NameCompare();Arrays.sort(peoples,nameCompare);System.out.println("------按姓名排序-------");System.out.println(Arrays.toString(peoples));System.out.println("------按年龄排序-------");AgeCompare ageCompare = new AgeCompare();Arrays.sort(peoples,ageCompare);System.out.println(Arrays.toString(peoples));}public static void main(String[] args) {test3();}
}
输出:
------原始顺序-------
[People{age=18, name=‘zhangsan’}, People{age=10, name=‘lisi’}, People{age=22, name=‘wangwu’}]
------按姓名排序-------
[People{age=10, name=‘lisi’}, People{age=22, name=‘wangwu’}, People{age=18, name=‘zhangsan’}]
------按年龄排序-------
[People{age=10, name=‘lisi’}, People{age=18, name=‘zhangsan’}, People{age=22, name=‘wangwu’}]
自己实现冒泡排序完成排序
import java.util.Arrays;
import java.util.Comparator;public class Test {public static void BubbleSort(Comparable[] comparables) {//发生向上转型for (int i = 0; i < comparables.length; i++) {for (int j = i; j <comparables.length-1 ; j++) {if(comparables[j].compareTo(comparables[j+1]) > 0) {Comparable temp = comparables[j];comparables[j] = comparables[j+1];comparables[j+1] = temp;}}}}public static void test4() {People[] people1 = new People[3];people1[0]= new People(18,"zhangsan");people1[1] = new People(10,"lisi");people1[2] = new People(22,"wangwu");BubbleSort(people1);System.out.println("------按年龄排序-------");System.out.println(Arrays.toString(people1));}public static void main(String[] args) {test4();}
}
输出:
------按年龄排序-------
[People{age=10, name=‘lisi’}, People{age=18, name=‘zhangsan’}, People{age=22, name=‘wangwu’}]
也可以使用传入比较器来实现冒泡排序
public static void BubbleSort(Comparable[] comparables,Comparator comparator) {for (int i = 0; i < comparables.length; i++) {for (int j = i; j <comparables.length-1 ; j++) {if(comparator.compare(comparables[j],comparables[j+1]) > 0) {Comparable temp = comparables[j];comparables[j] = comparables[j+1];comparables[j+1] = temp;}}}
}
public static void BubbleSort1(People[] people,Comparator<People> comparator) {for (int i = 0; i < people.length; i++) {for (int j = i; j <people.length-1 ; j++) {if(comparator.compare(people[j],people[j+1]) > 0) {People temp = people[j];people[j] = people[j+1];people[j+1] = temp;}}}
}
public static void test4() {People[] people1 = new People[3];people1[0]= new People(18,"zhangsan");people1[1] = new People(10,"lisi");people1[2] = new People(22,"wangwu");AgeCompare ageCompare = new AgeCompare();BubbleSort(people1,ageCompare);//或者BubbleSort1(people1,ageCompare);System.out.println("------按年龄排序-------");System.out.println(Arrays.toString(people1));
}
输出结果和上面一样
对象的拷贝
Cloneable接口
public interface Cloneable {
}
我们发现Cloneable接口是个空接口。当一个类实现了Cloneable接口表示当前这个类的对象是可以被克隆的。我们知道Object类是所有类的父类,Object类中有clone方法,这时候我们需要重写clone方法。

注意:其clone的返回类型为Object类
public class People implements Cloneable{//重写clone方法@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) {People people = new People();People people1 = people.clone();//报错了}
}

这时候我们需要加throws CloneNotSupportedException才能消除警告。
public class Test {public static void main(String[] args) throws CloneNotSupportedException{People people = new People();People people1 = people.clone();//还是报错了}
}

这时候需要强制类型转换,发生向下转型。
public class Test {public static void main(String[] args) throws CloneNotSupportedException{People people = new People();People people1 = (People) people.clone();}
}
这时候完成了拷贝。
总结:完成拷贝的步骤
1、实现Cloneable接口
2、声明异常throws CloneNotSupportedException
3、进行强制类型转换
代码演示:
public class People implements Cloneable{public int age;public String name;public People(int age, String name) {this.age = age;this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException{People people1 = new People(18,"lisi");People people2 = (People) people1.clone();System.out.println(people1.name);System.out.println(people1.age);System.out.println("------------");System.out.println(people2.name);System.out.println(people2.age);}
}
输出:
lisi
18
------------
lisi
18

深拷贝与浅拷贝
class Money {public double money = 99.99;
}public class People implements Cloneable{public int age;public String name;Money money = new Money();//组合public People(int age, String name) {this.age = age;this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException{People people1 = new People(18,"lisi");People people2 = (People) people1.clone();System.out.println(people1.name);System.out.println(people1.age);System.out.println(people1.money.money);System.out.println("------------");System.out.println(people2.name);System.out.println(people2.age);System.out.println(people2.money.money);System.out.println("------------");people1.age = 20;System.out.println(people1.age);System.out.println(people2.age);System.out.println("------------");people1.money.money = 10;System.out.println(people1.money.money);System.out.println(people2.money.money);}
}
输出:
lisi
18
99.99
------------
lisi
18
99.99
------------
20
18
------------
10.0
10.0
我们发现
1、people1.age = 20;只改变了people1.age 的值,没有改变people2.age 的值。
2、people2.money.money = 10;改变了people2.money.money的值和people1.money.money的值。这就是有关深拷贝与浅拷贝的问题了。
我们通过画图来展示:

上图是没有改变任何值的分布

上图是people1.age = 20;改变了people1.age 的值。

上图是people2.money.money = 10;改变了people2.money.money的值和people1.money.money的值。
上述我们就称之为浅拷贝。
浅拷贝会创建一个完全一样属性的新对象。但,当属性是引用类型时,拷贝的是同一个地址,也就是说它们共用一个对象。(例如:上述代码,money是引用类型数据,拷贝的都是0x22这个地址)当改变所指向的值时,其原对象的属性也会改变!(例如:上述代码,改变了money的值,当原对象和新对象的对应属性值也都发生变化,都变成10.0)
有了上述浅拷贝的概念,深拷贝就很好理解了。深拷贝要做的就是还要将引用类型属性再创建一个新的对象。

需要产生上图的效果,这时候people2.money.money = 10;只会改变people2.money.money的值。
那么深拷贝是如何实现的呢?
我们需要像浅拷贝一样,再进行克隆一次。中间创建临时变量来接收和调用引用类型变量。
代码演示:
class Money implements Cloneable{public double money = 99.99;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class People implements Cloneable{public int age;public String name;Money money = new Money();//组合public People(int age, String name) {this.age = age;this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {//return super.clone();People temp = (People) super.clone();temp.money = (Money) this.money.clone();return temp;}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException{People people1 = new People(18,"lisi");People people2 = (People) people1.clone();System.out.println(people1.name);System.out.println(people1.age);System.out.println(people1.money.money);System.out.println("------------");System.out.println(people2.name);System.out.println(people2.age);System.out.println(people2.money.money);System.out.println("------------");people1.age = 20;System.out.println(people1.age);System.out.println(people2.age);System.out.println("------------");people1.money.money = 10;System.out.println(people1.money.money);System.out.println(people2.money.money);}
}
输出:
lisi
18
99.99
------------
lisi
18
99.99
------------
20
18
------------
10.0
99.99
people2.money.money的值没有发生改变。这就完成了深拷贝。
通过画图再次理解拷贝过程:
执行
People temp = (People) super.clone();

执行:
temp.money = (Money) this.money.clone();
对这个代码进行拆分。
1、完成(Money)this.money.clone()

2、完成赋值

执行:
return temp;

这样就完成了深拷贝!!!
注意:
为了能拷贝引用类型指向的值,也需要对Money类实现Cloneable接口和重写clone方法。
相关文章:
JAVA学习*接口
接口 在生活中我们常听说USB接口,那接口是什么呢? 在Java中,接口相当于多个类的一种公共规范,是一种引用数据类型。 定义接口 public interface IUSB {public static final String SIZE "small";public abstract vo…...
Day11 动态规划入门
动态规划 就是 : 给定一个问题,我们把它拆成一个个子问题,直到子问题可以直接解决。然后把子问题的答案保存起来,以减少重复计算。再根据子问题答案反推,得出原问题解的一种方法. 记忆化搜索 暴力dfs 记录答案 动态规划入门思…...
WPF UI元素保存为图像文件
WPF UI元素保存为图像文件 实现功能示例代码使用示例关键代码说明WPF UI元素保存为图像文件 实现功能 将WPF界面元素(如控件、布局容器)的当前视觉内容保存为图像文件适用场景:截取控件的实时显示内容(如图表、界面快照);将动态生成的UI元素导出为图片用于分享、存档或打…...
指令型样本或偏好型样本有什么区别和联系
两者都是基于给定文本生成的训练样本,但侧重点和用途不同: 指令型样本(Instruction-based samples) 结构:通常是一个简单的指令和对应的回答,例如一对“问题-答案”或“指令-回答”。…...
neo4j-如何让外部设备访问wsl中的neo4j
WSL 运行在一个虚拟网络环境中,它的 IP 只能被宿主 Windows 访问,外部设备无法直接访问 WSL 的端口。你需要在 Windows 上转发端口,让外部设备可以访问 Windows 并映射到 WSL。 1. 获取 WSL 的 IP 地址 在 WSL 中运行以下命令获取其 IP 地址…...
Python实验:读写文本文件并添加行号
[实验目的] 熟练掌握内置函数open()的用法;熟练运用内置函数len()、max()、和enumerate();熟练运用字符串的strip()、ljust()和其它方法;熟练运用列表推导式。 [实验和内容] 1.编写一个程序demo.py,要求运行该程序后࿰…...
IDEA导入jar包后提示无法解析jar包中的类,比如无法解析符号 ‘log4j‘
IDEA导入jar包后提示无法解析jar包中的类 问题描述解决方法 问题描述 IDEA导入jar包的Maven坐标后,使用jar中的类比如log4j,仍然提示比如无法解析符号 log4j。 解决方法 在添加了依赖和配置文件后,确保刷新你的IDE项目和任何缓存ÿ…...
抖音用户视频批量下载工具开发全解析
一、逆向工程原理剖析 1.1 抖音Web端防护体系 抖音采用五层防御机制保护数据接口: graph LRA[浏览器指纹检测] --> B[请求参数签名]B --> C[Cookie动态验证]C --> D[请求频率限制]D --> E[IP信誉评级] 1.2 核心参数解密 参数名称作用原理生成方式有效期x-bogu…...
数据结构——顺序栈seq_stack
前言:大家好😍,本文主要介绍了数据结构——顺序栈 目录 一、概念 1.1 顺序栈的基本概念 1.2 顺序栈的存储结构 二、基本操作 2.1 结构体定义 2.2 初始化 2.3 判空 2.4 判满 2.5 扩容 2.6 插入 入栈 2.7 删除 出栈 2.8 获取栈顶元…...
LangChain其它五类组件详解(1)—— 文档加载器(Document loaders)
LangChain其它五类组件详解(1)—— 文档加载器(Document loaders) 前言本篇摘要15. LangChain其它五类组件详解15.1 文档加载器(Document loaders)15.1.1 文档加载概述15.1.2 加载Markdown1. 基本用法2. 保留元素参考文献前言 本系列文章主要介绍WEB界面工具Gradio。Gra…...
JVM常见面试总结
JVM(Java虚拟机)是Java程序运行的核心,掌握JVM相关知识对于Java开发者至关重要。以下是JVM常见的面试问题总结: 1. JVM内存模型 问题:JVM的内存结构分为哪些部分? 答案: 方法区(Met…...
美团Leaf分布式ID生成器使用教程:号段模式与Snowflake模式详解
引言 在分布式系统中,生成全局唯一ID是核心需求之一。美团开源的Leaf提供了两种分布式ID生成方案:号段模式(高可用、依赖数据库)和Snowflake模式(高性能、去中心化)。本文将手把手教你如何配置和使用这两种…...
python3.13.2安装详细步骤(附安装包)
文章目录 前言一、python3.13.2下载二、python3.13.2安装详细步骤1.查看安装文件2.启动安装程序3.安装模式选择4.自定义安装配置5.高级选项设置6.执行安装7.开始安装8.安装完成8.打开软件9.安装验证 前言 在数字化时代,Python 已成为不可或缺的编程语言。无论是开发…...
AI-Talk开发板之更换串口引脚
一、默认引脚 CSK6011A使用UART0作为Debug uart,AI-Talk开发板默认使用的GPIOA2和GPIOA3作为Debug uart的RX和TX,通过连接器CN6引出。 二 、更换到其它引脚 查看60xx_iomux_v1.0可以,UART0的tx和rx可以映射到很多管脚上。 结合AI-Talk开发板…...
深度解读DeepSeek:源码解读 DeepSeek-V3
深度解读DeepSeek:开源周(Open Source Week)技术解读 深度解读DeepSeek:源码解读 DeepSeek-V3 深度解读DeepSeek:技术原理 深度解读DeepSeek:发展历程 文章目录 整体流程模型初始化模型前向传播MoE https:/…...
JavaIO流的使用和修饰器模式(直击心灵版)
系列文章目录 JavaIO流的使用和修饰器模式 文章目录 系列文章目录前言一、字节流: 1.FileInputStream(读取文件)2.FileOutputStream(写入文件) 二、字符流: 1..基础字符流:2.处理流:3.对象处理流:4.转换流: 三、修饰器…...
爬虫入门re+bs4
目录 前言 1. 导入必要的库 2. 定义获取网页HTML内容的函数 get_html 3. 定义获取数据的函数 get_data 4. 定义获取文章正文内容的函数 content_text 5. 定义获取单条课程数据的函数 get_one_course_data 6. 定义保存数据的函数 save_data 7. 定义文件名合法化处理函数 sanitiz…...
【WebGL】texImage2D函数
参数 从像素数据加载纹理 gl.texImage2D(target, level, internalformat, width, height, border, format, type, source);从图像元素加载纹理 gl.texImage2D(target, level, internalformat, format, type, image);target gl.TEXTURE_2D(2D 纹理) T…...
北斗设备启动流程与时长解析
北斗卫星导航系统作为我国自主研发的全球卫星导航系统,广泛应用于交通、通信、农业等多个领域。今天,我们就来详细探讨一下北斗设备的启动流程以及不同启动方式下的时长。 一、北斗设备的启动流程 北斗设备的启动流程可以分为以下几个关键步骤…...
MySQL身份验证的auth_socket插件
在Ubuntu 20.04 LTS上,MySQL 8.0默认使用auth_socket插件进行身份验证,可能存在意想不到的情况。 一、auth_socket插件 在使用sudo mysql或通过sudo切换用户后执行任何MySQL命令时,不需要输入密码或错误密码都可以正常登入mysql数据库&…...
openstack安装部署
在OpenStack的安装和部署中,你需要按照一定的步骤来完成整个环境的搭建。OpenStack是一个开源的云计算平台,它提供了基础设施即服务(IaaS)的能力,包括计算、存储和网络等资源的管理。下面是一些基本的步骤来安装和部署…...
【日志库】—— log4cpp 部署套路
部署: 1、安装log4cpp,执行如下指令进行编译安装 log4cpp的官网是: http://log4cpp.sourceforge.net/ wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz tar xzvf log4cpp…...
使用Gitee Go流水线部署个人项目到服务器指南
使用Gitee Go流水线部署个人项目到服务器指南 前言!!! 本文解决的问题: 你有一台ECS服务器,你在上面部署了一个Java服务也就是一个jar,你觉着你每次手动本地打包,上传,在通过命令去…...
BlockChain.java
BlockChain 区块链,举个栗子 注意啦,列子里面的hashcode相等,但是字符串是不一样的哦,之前有记录这个问题 String.hashCode()-CSDN博客...
SystemVerilog 数据类型
1、内建数据类型 verilog有两种基本的数据类型:变量和线网,他们各自都可以有四种取值:0 1 z x; RTL代码使用 变量 来存放组合和时序值;变量可以是单bit或者是多bit的无符号数 reg [7:0] m, 32bit的有符号…...
【技术简析】触觉智能RK3506 Linux星闪网关开发板:重新定义工业物联新标杆
在工业智能化与物联网深度融合的今天,深圳触觉智能推出首款搭载瑞芯微RK3506芯片的Linux星闪网关开发板,为大家技术解析。 RK3506-国产芯的硬核实力 作为瑞芯微2024年第四季度推出的入门级工业芯片平台,RK3506以三核Cortex-A7(1.…...
YOLO-UniOW: 高效通用开放世界目标检测模型【附论文与源码】
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
面向对象(进阶)(‘封装‘,‘多态‘,‘对象属性‘,‘类属性‘,‘类方法‘,‘对象方法‘及其应用场景)
‘封装’,多态’及其应用场景 一, 封装及其应用场景 封装的定义 属于面向对象的三大特征之一, 就是隐藏对象的属性和现实细节, 仅对外提供公共的访问方式.(我们学的 函数, 类, 都是封装的体现). 封装的格式 __属性名 __属性名()封装的好处和弊端 好处 提高代码的安全性.…...
django如何配置使用asgi
以下是 Django 配置使用 ASGI 的完整指南: 一、配置前提 Django 版本:确保使用 Django 3.0(原生支持 ASGI)必要依赖:pip install daphne channels二、基础配置步骤 1. 创建/修改 ASGI 入口文件 在 Django 项目根目录…...
MongoDB 只能存储能够序列化的数据(比如字符串、数字等),而 Python 的 UUID 对象并不是直接可以存入数据库的格式。
1. UUID 对象是什么? UUID 是 “Universally Unique Identifier”(通用唯一识别码)的缩写,是一种 128 位的数字,用于在全局范围内生成一个唯一的标识符。它常用于数据库中的记录标识、分布式系统中的对象标识等场景。…...
