java1

在继承中,创建子类对象,访问成员方法的规则:

创建的对象是谁,就优先用谁,没有再向上找

注意:无论是成员变量还是成员方法,

如果没有都是向上找父类,不会向下找子类

继承的特点:子类可以拥有父类的内容,此处子类还可以拥有自己独有的内容(成员变量和方法)

定义继承的格式:(至少需要三个类:父类、子类、主类)

父类的格式:(普通的类定义) 子类的格式:

public class 父类名{ public class 子类名 extends 父类名{

//属性: //继承的父类的属性和方法

//方法; //自己独有的属性和方法

} }

java继承三大特性:

1.一个父类可以有多个子类

2.一个子类只能有一个父类

3.Java中的继承可以是多级继承

父类对象只能访问父美里的属性和方法不能访问于类里独有的属性和方法。

于类对象既能访问火类里的属性和万法,也能访问于关里独有的属性和方法。

若父类和子类里的成员变量重名,则创建子类对象时,访问有两种方式:

直接通过子类对象访问成员变量:优先子类内容,没有就向上找

间接通过成员方法访问成员变量:方法属于谁就优先用谁,没有就向上找

继承中,父类、子类构造方法的访问特点:

1.子类构造方法中有一个默认的super() 方法,

所以创建子类对象时先要调用父类的构造方法,再调用子类的构造方法

2.子类的构造方法可以通过super关键字来调用父类重载的构造方法。

3.super的父类构造方法调用时必须是子类构造方法的第一句,

不能一个子类构造方法同时调用多个super语句

方法的重写:发生在继承关系中,方法名称一样,参数列表也一样

重写:override 方法名称一样,参数列表【也一样】。覆盖、覆写

重载:overload 方法名称一样,参数列表【不一样】

注:

1.父子类之间的方法名相同,参数列表相同;

2.为了检测是不是有效的重载。可以在重写的方法前写上:@Override

3.子类重写的方法的返回值类型<=父类方法的返回值类型

4.子类重写的方法的访问权限>=父类方法的访问权限

public>protect>default(什么也不写)>private

super的三种用法:(跟父类相关)

1.在子类的成员方法中访问父类的成员变量;

区分局部变量、本类成员变量、父类成员变量重名时的使用:

局部变量:直接写变量名 num

本类的成员变量:this.变量名

父类的成员变量:super.变量名

2.在子类的成员方法中访问父类的成员方法;

3.在子类的构造方法中访问父类的构造方法

final关键字的几种用法:

1.修饰方法:不能被覆盖重写 public final void speak(){}

2.修饰类:不能被继承,不能有子类。(很少使用) public final class A{}

3.修饰成员变量:需赋值,且不可改变------常量。final double a = 2.14;

4.修饰接口

抽象方法:不确定具体地实现细节的时候,就可以用抽象方法。

在方法前加上abstract关键字,去掉花括号,分号结束。

抽象类:抽象方法的类必须是一个抽象类。即在class之前加上abstract

如何使用抽象类和抽象方法:

1.不能直接创建(new)抽象类的对象;

2.必须要有一个子类来继承此抽象的父类;

3.子类必须重写抽象父类中的抽象方法。

重写:去掉abstract关键字,补上方法体的{},写上方法体的内容(具体的实现细节)

4.创建子类对象来调用。

抽象类的特点:

1.和普通的类相比,abstract类里可以有abstract方法。也可以没有。

但是abstract方法所在的类必须是abstract类。

2.对于abstract类,不能使用new运算符创建该类的对象,只能产生其子类,由子类创建对象。

3.如果一个非abstract是abstract类的子类,它必须具体实现父类的所有的abstract方法,

重写的时候去掉abstract关键字,并给出方法体;

4.如果一个abstract类是abstract类的子类,那么他可以重写父类的abstract方法,

也可以继承父类的abstract方法。

5.对于abstract方法,不允许使用final修饰abstract方法,

也不允许使用static和priva

面向过程:当需要实现一个功能的时候,强调具体的实现细节和步骤,第一步干什么,第二步在干什么。

//面向过程:强调的是具体的实现细节,第一步。。。

System.out.print("[");

面向对象:当需要实现一个功能的时候,不关心具体的实现细节,而是找一个已经有该功能的东西来替我完成。

System.out.println(Arrays.toString(array));

定义一个类,用来模拟学生事物

属性(静态的,状态信息)

姓名,年龄

行为(动态的,能做什么)

学习

对应到Java里

成员变量(属性):

String name;

int age;

成员方法(行为):无static

public void eat(){}

public void sleep(){}

public void study(){}

注:

1.成员变量直接定义在类当中,方法外

2.成员方法不要写static关键字,调用必须实例化(创建对象,由对象来调用)

3.普通方法要有static关键字,调用有三种方式(单独调用,打印调用,赋值调用)

如果两个对象具有相同的引用/地址,那么这两个对象就完全相同,

一个发生改变,另一个也会发生相应的改变,

类和数组一样,都是属于引用型的数据类型。

使用类:通常情况下,一个类不能直接使用,需要根据类创建一个对象来使用

类的作用:把这个类里的属性和行为封装到一个类里,用到什么调用什么

1. 导包:指出用到的类在什么位置 格式:import 包名.类名

但是对于和当前类属于同一个包的情况,可以省略导包语句

2. 创建对象:类名 对象名 = new 类名();

3. 使用成员变量和成员方法

成员变量:对象名.成员变量名

成员方法:对象名.成员方法名()

即 用谁 就 对象名.谁

注:成员变量若没有赋值,那么他是有默认值的,规则和数组里的一样

成员变量和局部变量的区别:

1.定义位置不一样

成员变量:类里方法外 局部变量:方法里

2.作用范围不一样

成员变量:整个类里都可以使用 局部变量:方法中可用,出了方法就失效

3.默认值不一样

成员变量:有默认值,规则和数组一样 局部变量:无默认值,要想使用必须赋值

4.生命周期不一样

成员变量:随着对象的诞生而产生,对象被回收而消失

局部变量:随着方法的产生而产生,方法执行完局部变量失效

5.内存位置不一样

成员变量:堆 局部变量:栈

结论:

1.当局部变量和成员变量名字相同的时候,优先使用的是局部变量

2.要想使用成员变量,需要使用this关键字。格式:this.成员变量名

private 关键字的使用:

要想阻止一些不合理的数据输入------private关键字

但是一旦使用private修饰的成员变量在能在本类中访问,超出本类范围不能直接访问,

间接访问:定义一对getter和setter方法(成对出现)

并且定义的时候必须叫setXxx/getXxx:

setXxx:无返回值,有参数,且参数类型要和成员变量相对应

getXxx:有返回值,无参数,且参数类型要和成员变量相对应

构造方法:专门用来创建对象的方法,也就是说当new创建对象的时候,就是在调用构造方法。

格式:

public 类名 (参数类型 参数名1, 参数类型 参数名2,。。。){

方法体

}

注意:

1.构造方法的名称和类名一模一样,包括大小写也一样

2.构造方法无返回值类型,void也不写

3.构造方法不能return具体的返回值

4.若没编写构造方法,那么编译器会默认赠送一个构造方法:无参数,无方法体,什么也不做。 public Student(){}

5.构造方法是可以重载的

6.一旦编写了至少一个构造方法,那么编译器将不再赠送默认的构造方法。

为什么使用构造方法?构造方法有什么好处:

1.在创建对象的时候,会调用构造方法,完成对象的实例化,即为对象的属性赋予了初值,确保对象在使用之前就具有正确的状态。

2.避免了手动赋值的繁琐

Java里的标准类,应满足以下4个条件:

1.所有的成员变量都要使用private关键字来修饰(外部类不能访问本类中的成员变量,就不会去随意的改值,起到一个保护成员变量的作用)

2.为每一个成员变量编写一对儿getter和setter方法

3.要编写一个无参的构造方法

4.要编写一个全参的构造方法

这样标准的类叫JavaBean。

static 用法三:静态代码块

格式:

public class 类名{

sttic{

若干行代码;

Api--String:程序当中所有双引号括起来的字符串都是String类的对象

1.属于Java.lang 包里,可以省略导包语句

2.特点:

(1) 字符串的内容一旦定义就不可以改变,所以字符串可以共享使用

(2) 效果上相当于char[]字符数组(char是一个字符,但是String好几个字符串起来)

底层原理相当于byte[]字节数组。

3.创建字符串的常见3+1种方式:

三种构造方法:

public String():创建的是一个空白字符串,不含内容

public String(char[] array):根据字符数组内容,创建对应的字符串

public String(byte[] array):根据字节数组内容,创建对应的字符串

一种直接创建:String str = "hello";

注:不管new不new ,只要写上双引号就是字符串对象

String类中与截取相关的方法:

1.public String substring(int index):截取从参数的索引位置到末尾的新字符串

2.public String substring(int begin,int end)::截取从索引为begin到end中间的字符串【)

public String replace(旧字符串,新字符串):将所有出现的旧字符串替换成新字符串,并返回

String类中与获取相关的方法:

1.public int length():获取字符串的长度

int length = "asjhfhkgjldg".length();

System.out.println("长度: "+length);

2.public String concat(String):将当前字符串和参数字符串拼接为新字符串

3.public char charAt(int index):获取指定索引位置的单个字符

4.public int indexoOf(String str):查找参数字符串在本字符串首次出现的索引位置,若找不到,则返回-1

字符串的比较:

  1. ==

基本数据类型:比较的是数值

引用数据类型:比较的是地址

2.比较字符串的内容:equals()

public boolean equals(任何对象):参数必须是一个字符串,且内容相同才返回true,否则都是false

public boolean equalsIgnoreCase(String str):忽略大小写比较

字符串常量池:程序当中直接写上双引号的字符串,都在常量池中,而new的String对象不在常量池中

注意:

1.equals方法具有对称性,即a.equals(b) b.equals(a)一样的

2.若比较的双方有一个常量一个是变量,通常把常量字符串写到前面。

Array:数组类,java.lang包,导包语句可省略。

特点:一个基本的存储结构,提供大量创建数组和访问数组的方法

Arrays类:java.util包,需要导包语句;

特点:实现数组常见的操作,含大量静态方法,所以可以直接通过类名来调用

1.public static String toString(数组):将参数数组变成字符串固定格式输出:【元素1,元素2,元 素3】

2.public static void sort(数组): 按升序对数组元素排列

数值:从小到大;字符串:字母升序

Math类:与数学运算相关的操作,提供了大量的静态方法和静态成员变量

1.public static double PI;

2.public static double E;对数的底数e

3.public static double abs(double num):取绝对值(也可以是int,short,long,byte,float)

4.public static double ceil(double num):向上取整(也可以是float)

5.public static double floor(double num):向下取整

6.public static long round(double num):四舍五入

7.public static double max(double a ,double b):求两个数的最大值

7.public static double min(double a ,double b):求两个数的最小值

继承的特点 : 子类可以拥有父类的内容,此外子类还可以拥有自己独有的内容 ( 成员变量和方法 )

* 定义继承的格式 :( 至少需要三个类 : 父类、于类、主类 )

* 父类的格式 :( 普通的类定义 ) 子类的格式 :

*publicclass 父类名 {publicclass 子类名 extends 父类名 {

// 继承的父类的属性和方法自己独有的属性和方法

*// 属性 ;// 自己独有的属性和方法

*// 方法

*

* 父类对象只能访问父类里的属性和方法,不能访问子类独有的属性和方法

* 子类对象既能访问父类里的属性和方法,也能访问子类里独有的属性和方法。

继承中,父类、子类构造方法的访问特点:

*1. 子类构造方法中有一个默认的 super() 方法

* 所以创建子类对象时先要调用父类的构造方法,在调用子类的构造方法

*2. 子类构造方法可以通过 super 关键字来调用父类重载的构造方法

*3.super 的父类构造方法调用时必须是子类构造方法的第一句,

* 不能一个子类构造方法同时调用 super 语句

方法的重写:发生在继承关系中,方法名称一样,参数列表也一样

* 重写 :override 方法名称一样,参数列表【也一样】,覆盖,覆写

* 重载: overload 方法名称一样,参数列表【不一样】

* 注:

*1. 父子类之间的方法名相同,参数列表相同

*2. 为了检测是不是有效的重载,可以在重写的方法前写上: @Override

*3. 子类重写的方法的返回值类型 <= 父类方法的返回值类型

*4. 子类重写的方法的访问权限 >= 父类方法的访问权限

*public>protect>default( 什么也不写 )>private

Super 的三种用法:(跟父类相关)

*1. 在子类的成员方法中访问父类的成员变量;

* 区分局部变量、本类成员变量、父类成员变量重名时的使用;

* 局部变量:直接写变量名 num

* 本类的成员变量: this. 变量名

* 父类的成员变量: super 。变量名

*

*2. 在子类的成员方法中访问父类的成员方法;

*3. 在子类的构造方法中访问父类的构造方法

*

抽象方法:不确定具体的实现季节的时候,就可以用抽象方法

* 在方法前加上 abstract 关键字,去掉花括号,分号结束

* 抽象类:抽象方法所在的类必须是一个抽象类。即在 class 之前加上 abstract

* 如何使用抽象类和抽象方法:

*1. 不能直接创建( new )抽象类的对象

*2. 必须要有一个子类来继承此抽象父类;

*3. 子类必须重写抽象父类中的抽象方法。

* 重写:去掉 abstract 关键字,补上方法体的 {} 写上方法体的内容(具体的实现细节)

*4. 创建子类对象来调用

*

* 抽象类的特点:

*1. 和普通的类相比,抽象类可以有 abstract 方法,也可以没有

* 但是 abstract 方法所在的类必须是 abstract

*3. 如果一个非 abstract 类是 abstract 类的子类,它必须具体实现父类的所有的 abstract 方法

* 重写的时候去掉 abstract 关键字,并给出方法体

*4. 如果一个 abstract 类是 abstract 类的子类,那么他可以重写父类的 abstract 方法

* 也可以继承父类的 abstract 方法

*5. 对于 abstract 方法不允许使用 final 修饰 abstract 方法

* 也不允许使用 static private 修饰 abstract 方法

接口**:在** java 中是一种引用的数据类型,里面最主要的内容介绍抽象方法

格式:

Publiciinterface 接口名 {

// 接口内容

}

注:接口编译生成的文件仍然是 .class 的后缀文件,源文件也仍然是 .java 的源文件

接口里的内容;

1. 常量( java7 及以上的版本支持)

格式:【 public 】【 static 】【 final 】数据类型变量名 = 数据值;

1 )接口中的变量必须赋初值;( 2 )接口中的常量使用时尽量全部大写,多个单词用 _ 分割

2. 抽象方法( Java7 及以上的版本构成)

格式:【 public 】【 abstract 】返回值类型方法名(参数)

1 )接口当中的抽象方法修饰符必须是用 publicabstract 来修饰

2 )方法的三要素可以随意定义,只要符合规范即可

使用:

1 )接口中的抽象方法要想使用,必须有一个实现类来实现( implements )接口,因为接口不能直接创

建对象使用

2 )接口的实现必须要重写(去掉 abstract 关键字,加上 {} 和方法体)接口中的所以的抽象方法

格式: publicclass 实现类 implements 接口名 {

// 重写接口中的所以抽象方法

}

若实现类没有重写接口中的任一抽像方法,那这个实现类必须是抽象类

3 )主类中创建实现类的对象进行使用(实现类最主要的一个作用,就是为了创建对象来使用接口中的各种方法)

3. 默认方法( Java8 及以上的版本构成)

4. 静态方法( Java8 及以上的版本构成)

5.private 方法( Java9 及以上的版本支持

1.接口中的内容:

(1)常量:【public】【static】【final】数据类型常量名=赋值;

(2)抽象方法:现实类必须重写接口中的所有抽象方法

【public】【abstract】返回值类型方法名(参数)

(3)默认方法:可被现实类"继承"过来也可以被重写

【public】default返回值类型方法名(参数){方法体}

(4)静态方法:能通过接口名来直接调用

【public】static返回值类型方法名(参数){方法体}

(5)私有方法:只能在接口中使用,出了接口不能被访问

1)普通私有方法

private返回值类型方法名(参数){方法体}

2)静态私有方法:

privateststic返回值类型方法名(参数){方法体}

2.接口中的注意事项

(1)接口中不能有构造方法,也不能有静态代码块

(2)一个类的直接父类是唯一的(单继承),但是一个类可以同时去实现多个接口

punlicclassAextendsBimplementInterfaceA,InterfaceB{}

(3)如果实现类所实现的多个接口中,存在重复的抽象方法,那么只需重写一次

(4)如果实现类未重写接口中的任一抽象方法,那么必须把该类定义为一个抽象类

(5)如果实现类实现的多个接口中,存在重复的默认方法,必须重写这个默认方法

方法的重载*:方法名称相同,参数列表不一样*

参数列表不一样:

1. 参数个数不同;

*2. 参数类型不同:比如 sum inta intb orsum doublea,doubleb

*3. 参数类型顺序不同:比如 sum(inta,floatb)orsum(floata,intb)

注:

*1. 方法重载和参数无关,比如 sum(inta,intb)orsum(intx,inty)

*2. 方法重载与返回值类型无关,比如 publicstaticintsum(inta,intb)

*publicstaticdoublesum(inta,intb)

*

*3. 方法重载与方法体内容无关

比较有参数和无参数*:*

* 有参数:方法()里面有内容,当一个方法需要一些数据输入才能完成任务的时候,就需要有参数。

* 比如计算两个数字相加,需要知道这两个数字具体值是多少。

* 无参数:方法()里内容,当一个方法不需要数据输入就能完成任务的时候

* 不需要参数。如打印固定十次 helloword

方法有返回值和无返回值的区别*:*

//* 题目要求:定义一个方法,【求出】两数之和:(翻译:定义一个方法,你帮我算两数之和,算完后告诉我结果,有返回值)

//* 题目变形:定义一个方法,【打印】两数之和;(翻译:定义一个方法,你帮我算两数之和,算完后你自己打印结果,无返回值)

//

// 重点:如果一个方法无返回值,那么方法名前面的 " 返回值数据类型 " 就是 void

// 如果一个方法无返回值,那么它只能使用单独调用,不能使用赋值调用和打印调用

数组:要存放多个数据,但是要求数据类型必须一致

特点

1.引用型数据类型;

2.数组中存放的数据类型必须一致;

3.数组的长度在运行期间是不可以改变的

格式:

动态初始化:指定数组的长度 数据类型[] 数组名=new 数据类型[36] ;

静态初始化:指定数组的内容 数据类型[] 数组名=new 数据类型[]{87,68,97,90...}

double[] arr = new double[36];//动态初始化

int[] arr2 = new int[]{87,68,97,90};//静态态初始化

注意:

1.静态初始化也是可以推算出数组的长度;

2.静态/动态初始化可以拆分成两个步骤写

3.静态初始化的省略格式不可以拆分成两个步骤写

4.若不确定数组的具体内容,建议使用动态初始化;否则,用静态初始化

要想输出数组中的元素值,用: 数组名[索引值]

索引值一般从0开始,直到数组的长度-1为止

System.out.println(arr[0]);

动态初始化的使用:

动态初始化因为没有指定具体的元素内容,所以是有默认值的;

若数组的数据类型为int:默认值是0;

float: 0.0

字符型: '\u0000'

布尔型: false;

引用型: null

结论:如果两个数组具有相同的引用,也就是具有相同的地址,则一定具有相同的数据元素

a=b;// 把b的引用/地址给了a之后,a和b 就是两个完全一样的数组

两个常见问题:

常见问题1:ArrayIndexOutOfBoundsException 索引越界

解决办法:检查数组的索引,看是否越界

索引值是从0开始,直到数组的长度-1为止

常见问题2:NullPointerException 空指针异常

数组在未初始化时不能使用

解决方法:正常对数组进行初始化

遍历数组:将数组里边的元素挨个儿输出

获取静态数组的长度:数组名.length

用for循环遍历数组:

for(int i =0;i<=a.length-1;i++){

System.out.println(a[i]);

}

二、二维

二维数组初始化的三种方式

int[ ][ ] a = new int[3][4];

int[ ][ ] b = new int[3][ ];

int[ ][ ] c = {{1,2},{2,3},{3,4,5}};

二维数组的数组名.length: 里面包含的一维数组的个数

int[][] a = new int[3][4];

a[0][0]=2;

a[2][3]=4;

a[1][2]=6;

System.out.println(a.length);//表示的是一维数组的个数

1.方法的定义:是一段封装了一系列语句的代码块,用于执行特定的任务和操作

作用:可以实现代码的复用,提高代码的可读性和可维护性(一次书写,多次使用)

参数:原料。进入方法的数据

返回值:产出物。执行完方法,从方法里出来的数据

把方法看作是一个工厂

蒙牛工厂:

原料:奶牛,饲料,水

产出物:奶制品

钢铁工厂:

原料:铁矿石,煤炭

产出物:钢铁建材

2.方法的格式

修饰符 返回值类型 方法名(参数类型 参数名字1,参数类型 参数名字2...){

方法体;

return 返回值;

}

修饰符:public static (目前固定)

返回值类型:方法最终的产出数据是什么类型的

方法名:小驼峰命名

参数类型:进入方法的数据是什么类型的

参数名:进入方法的数据的变量名字

方法体:方法要完成的功能,一般是一段代码(语句块)

return:1.停止当前方法;2.将返回值给了调用处

返回值:方法执行后最终的数据结果

注意:

1.参数若有多个,中间用 , 分隔

2.return 后面的返回值要和方法名前面的"返回值类型"相对应

方法要想有结果,必须要调用方法。光定义方法不调用,是没有结果的。

调用:

1.单独调用:方法名(参数); (只让方法执行,但不能拿到方法的结果)

sum(100,20);

2.打印调用:System.out.println(方法名(参数)); 将方法的结果打印显示出来

System.out.println(sum(100,20));

3.赋值调用:数据类型 变量名 = 方法名(参数); 将方法的结果赋给变量,再去操作变量

int num = sum(200,20);

System.out.println(num);

注意:1.public static void main(String[] args) {}也表示一个方法,只不过是固定的, 一个程序 的主方法。

2.方法里面不能嵌套方法

比较方法的有参数和无参数:

有参数:方法的()里有内容,当一个方法需要一些数据输入才能完成任务的时候,

就需要有参数。比如:计算两个数字相加,需知道这两个数字具体是多少。

无参数:方法的()里无内容,当一个方法不需要数据输入就能完成任务的时候,

就不需要有参数。比如:打印固定十次hello world(无参数)。

方法有返回值和无返回值的区别:

题目要求:定义一个方法,【求出】两数之和; (翻译:定义一个方法,你帮我算两数之和,算完之后告我结果,有返回值)

题目变形:定义一个方法,【打印】两数之和; (翻译:定义一个方法,你帮我算两数之和,算完之后你自己打印结果,无返回值)

重点:如果一个方法无返回值,那么方法名前面的"返回值数据类型"就是void

如果一个方法无返回值,那么它只能使用单独调用,不能使用赋值调用和打印调用

注意:

1)方法应该定义在类中,但是不能在方法中定义方法,不能嵌套;

2)方法定义的前后顺序无所谓;

3)方法定义后不会执行,要想让方法执行,必须要调用方法;

4)return后面的返回值类型必须和方法的返回值类型一致;

5)void类型的方法没有返回值,只能使用单独调用;

6)一个方法中可以有多个return语句,但每次只能执行一个return语句;

7)两个return语句不能连着写。

方法的重载:方法名称相同,但是参数列表不一样

参数列表不一样:

1.参数个数不同;

2.参数类型不同;比如 sum(int a,int b) or sum(double a,double b)

3.参数类型顺序不同:比如sum(int a,float b) or sum(float a,int b)

注:

1.方法重载和参数名无关,比如sum(int a,int b) or sum(int x,int y)

2.方法重载与返回值类型无关,比如public static int sum(int a,int b)

public static double sum(int a,int b)

3.方法重载与方法体内容无关

public static void open(){}//正确重载

public static void open(int a){}//正确重载

static void open(int a,int b){}//代码错误,和第8行冲突

public static void open(double a,int b){}//正确重载

public static void open(int a,double

相关推荐
信号处理学渣6 分钟前
matlab画图,选择性显示legend标签
开发语言·matlab
红龙创客6 分钟前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
jasmine s15 分钟前
Pandas
开发语言·python
装不满的克莱因瓶28 分钟前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗35 分钟前
常用类晨考day15
java
biomooc36 分钟前
R 语言 | 绘图的文字格式(绘制上标、下标、斜体、文字标注等)
开发语言·r语言
骇客野人38 分钟前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
black^sugar40 分钟前
纯前端实现更新检测
开发语言·前端·javascript
404NooFound1 小时前
Python轻量级NoSQL数据库TinyDB
开发语言·python·nosql
用余生去守护2 小时前
python报错系列(16)--pyinstaller ????????
开发语言·python