Java变量详解

一、Java程序基本结构

1.1 基本结构

Java程序基本结构示例代码:

/**
* 这里是文档注释
* 这是一个HelloWorld程序
*/
public class HelloWorld {
    public static void main(String[] args) {
        // 向控制台输出文本:
        System.out.println("Hello, world!");
        /* 
         这里是多行注释
         注释内容
        */
    }
} 

1.2 结构解析

1、Java是面向对象的语言,一个程序的基本单位就是class,class是关键字,这里定义的class名字就是HelloWorld,类的概念,会在后面的面向对象部分学习。这里我们可以认为,所有的Java程序,必须写在一个类里。

2、public是访问修饰符,表示该class是公开的。

3、{...}类名HelloWorld后面的大括号,是类的内容。大括号要前后对应。

4. 在class内部,可以定义若干方法(method),方法定义了一组执行语句,方法内部的代码将会被依次顺序执行。
这里的方法名是main,返回值是void,表示没有任何返回值。在java中main()表示程序的执行入口;

5、我们注意到public除了可以修饰class外,也可以修饰方法。而关键字static是另一个修饰符,它表示静态方法,后面我们会讲解方法的类型,目前,我们只需要知道,Java入口程序规定的方法必须是静态方法,方法名必须为main,括号内的参数必须是String数组。

6、java编译器为每个类生成一个字节码文件(也就是后缀名为class的文件),且文件名与类名相同,同名的类有可能发生冲突。为了解决这一问题,java提供包来管理类名空间,什么是包呢,实际就是文件夹。相同的名字的类,在不同的包下,就像是同样的东西,放在不同的抽屉中一样.

7、一个java源文件,可以有多个类,但是只能有一个公共类(由public修饰的类),而且经过编译之后,会生成与类名对应的字节码文件(有几个类就有几个字节码文件)。

二、Java关键字和保留字

        正确识别java语言的关键字(keyword)和保留字(reserved word)是十分重要的。
    
        Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等。保留字是为java预留的关键字,他们虽然现在没有作为关键字,但在以后的升级版本中有可能作为关键字。
    
        识别java语言的关键字,不要和其他语言如c/c++的关键字混淆。

2.1 关键字(keyword)

        定义:被Java语言赋予了特殊含义,用做专门用途的单词。在给类、变量等命名是不能使用。
    
        特点:所有字母都小写。(在很多编程软件中会显示出一种颜色)。

        官方地址:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html

用于定义数据类型的关键字:

关键字含义描述
class用来声明新的 Java类,该类是相关变量和/或方法的集合。类是面向对象的程序设计方法的基本构造单位。类通常代表某种实际实体,如几何形状或人。类是对象的模板。每个对象都是类的一个实例。要使用类,通常使用 new 操作符将类的对象实例化,然后调用类的方法来访问类的功能。
interface接口用来声明新的 Java 接口,接口是方法的集合。接口是 Java 语言的一项强大功能。任何类都可声明它实现一个或多个接口,这意味着它实现了在这些接口中所定义的所有方法。 实现了接口的任何类都必须提供在该接口中的所有方法的实现。一个类可以实现多个接口。
enum枚举枚举类型,可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。这句话是个什么意思呢? 你比如说季节类,它只能有春夏秋冬四个对象;星期类,他只有周一到周天七个对象。诸如这种对象的个数有限的,我们都可以用枚举实现它。
byte字节型Java 原始类型。byte 可存储在 [-128, 127] 范围以内的整数值。
short短整型Java 原始类型。short 变量可以存储 16 位带符号的整数。
int整型Java 原始类型。int 变量可以存储 32 位的整数值。
long长整型Java 原始类型。long 变量可以存储 64 位的带符号整数。
float单精度浮点型Java 原始类型。float 变量可以存储单精度浮点值。 使用此关键字时应遵循下列规则: Java 中的浮点文字始终默认为双精度。要指定单精度文字值,应在数值后加上 f 或 F,如 0.01f。
double双精度浮点型Java 原始类型。double 变量可以存储双精度浮点值。
char字符型Java 原始类型。char 变量可以存储一个 Unicode 字符。
boolean布尔型Java 原始类型。boolean 变量的值可以是 true 或 false。 boolean 变量只能以 true 或 false 作为值。boolean 不能与数字类型相互转换。
void无返回值void 可以用作方法的返回类型,以指示该方法不返回值。

用于定义流程控制的关键字:

关键字含义描述
if如果指示有条件地执行代码块。条件的计算结果必须是布尔值。 if 语句可以有可选的 else 子句,该子句包含条件为 false 时将执行的代码。 包含 boolean 操作数的表达式只能包含 boolean 操作数。
else否则,或者总是在 if-else 语句中与 if 关键字结合使用。else 子句是可选的,如果 if 条件为 false,则执行该子句。
switch开关用于基于某个表达式选择执行多个代码块中的某一个。
case返回开关里的结果用来标记 switch 语句中的每个分支。 case 块没有隐式结束点。break 语句通常在每个 case 块末尾使用,用于退出 switch 语句。 如果没有 break 语句,执行流将进入所有后面的 case 和/或 default 块。
default默认用来标记 switch 语句中的默认分支。 default 块没有隐式结束点。break 语句通常在每个 case 或 default 块的末尾使用,以便在完成块时退出 switch 语句。 如果没有 default 语句,其参数与任何 case 块都不匹配的 switch 语句将不执行任何操作。
while当什么的时候用于指定一个只要条件为真就会重复的循环。
do运行用于指定一个在每次迭代结束时检查其条件的循环。 do 循环体至少执行一次。 条件表达式后面必须有分号。
for满足三个条件时用于指定一个在每次迭代结束前检查其条件的循环。
break跳出循环用于提前退出 for、while 或 do 循环,或者在 switch 语句中用来结束 case 块。 break 总是退出最深层的 while、for、do 或 switch 语句。
continue继续用来跳转到 for、while 或 do 循环的下一个迭代。 continue 总是跳到最深层 while、for 或 do 语句的下一个迭代。
return返回会导致方法返回到调用它的方法,从而传递与返回方法的返回类型匹配的值。 如果方法具有非 void 的返回类型,return 语句必须具有相同或兼容类型的参数。 返回值两侧的括号是可选的。

用于定义访问权限修饰符的关键字:

关键字含义描述
private私有的可以应用于类、方法或字段(类中声明的变量),只能在声明的类内部中引用这些类、方法或字段,在外部或者对于子类而言是不可见的,类的默认访问范围是package访问,除非存在特殊的访问控制修饰符。可以从一个包中的任何类访问类成员
protected受保护的应用于类、方法或字段(类中声明的变量),可以在声明 protected 类、方法或字段的类、同一个包中的其他任何类以及任何子类(无论子类是在哪个包中声明的)中引用这些类、方法或字段。
public公有的应用于类、方法或字段(在类中声明的变量)的访问控制修饰符。 可能只会在其他任何类或包中引用 public 类、方法或字段。

用于定义类,函数,变量修饰符的关键字:

关键字含义描述
abstract声明抽象可以修改类或方法。abstract类可以扩展(增加子类),但不能直接实例化。abstract方法不在声明它的类中实现,但必须在某个子类中重写。采用 abstract方法的类本来就是抽象类,并且必须声明为abstract。
final最终的不可被改变的方法和类都可以用final来修饰。final修饰的类是不能被继承的 修饰的方法是不能被子类重写。常量的定义:final修饰的属性就是常量。
static静态的属性和方法都可以用static修饰,直接使用类名.属性和方法名。 只有内部类可以使用static关键字修饰,调用直接使用类名.内部类类名进行调用。 static可以独立存在。静态块
synchronized线程,同步可以应用于方法或语句块,并为一次只应由一个线程执行的关键代码段提供保护。 可防止代码的关键代码段一次被多个线程执行。

用于定义类与类之间关系的关键字:

关键字含义描述
extends继承用在 class 或 interface 声明中,用于指示所声明的类或接口是其名称后跟有 extends 关键字的类或接口的子类。子类继承父类的所有 public 和 protected 变量和方法。 子类可以重写父类的任何非 final 方法。一个类只能扩展一个其他类。
implements实现在 class 声明中使用,以指示所声明的类提供了在 implements 关键字后面的名称所指定的接口中所声明的所有方法的实现。类必须提供在接口中所声明的所有方法的实现。一个类可以实现多个接口。

用于定义建立实例及引用实例,判断实例的关键字:

关键字含义描述
new新建、实例化用于创建类的新实例。 new 关键字后面的参数必须是类名,并且类名的后面必须是一组构造方法参数(必须带括号)。
this当前类的对象用于引用当前实例。 当引用可能不明确时,可以使用 this 关键字来引用当前的实例。
super调用父类的用于引用使用该关键字的类的超类。
instanceof实例判断用来确定对象所属的类。

用于异常处理的关键字:

关键字含义描述
try捕获异常用于包含可能引发异常的语句块。 每个 try 块都必须至少有一个 catch 或 finally 子句。
catch处理异常用来在 try-catch 或 try-catch-finally 语句中定义异常处理块。
finally最终的,有没有异常都执行用在异常处理的最后一个语句块,无论是否产生异常都要被执行。finally是对异常处理的最佳补充使代码总要被执行,使用finally可以维护对象的内部状态,并可以清理非内存资源。
throw抛出一个异常对象用于引发异常。
throws声明一个异常可能被抛出可以应用于方法,以便指出方法引发了特定类型的异常。throws 关键字将逗号分隔的 java.lang.Throwables 列表作为参数。

用于包的关键字:

关键字含义描述
package定义包的关键字指定在 Java 源文件中声明的类所驻留的 Java 包。 package 语句(如果出现)必须是 Java 源文件中的第一个非注释性文本。 例:java.lang.Object。 如果 Java 源文件不包含 package 语句,在该文件中定义的类将位于“默认包”中。
import引入包的关键字使一个包中的一个或所有类在当前 Java 源文件中可见。

其他修饰符关键字:

关键字含义描述
native本地以指示该方法是用 Java 以外的语言实现的。Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
strictfp严格,精准strictfp的意思是FP-strict,也就是说精确浮点的意思。
transient短暂可以应用于类的成员变量,以便指出该成员变量不应在包含它的类实例已序列化时被序列化。
volatile易失用于表示可以被多个线程异步修改的成员变量。volatile 的目标用途是为了确保所有线程所看到的指定变量的值都是相同的。Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;
assert断言表示断言,如果为true,则程序继续执行,如果为false,则程序抛出AssertionError并终止运行。

用于定义数据类型值的字面值:

关键字含义描述
true表示 boolean 变量的两个合法值中的一个。
false代表 boolean 变量的两个合法值之一。
null表示空值。 将 null 赋给非原始变量相当于释放该变量先前所引用的对象。

2.2 保留字

        保留字(reserved words):是语言已经定义过的字,一些保留字可能没有相对应的语法,考虑到扩展性,为了向后兼容不能再将其作为变量名。

        const和goto是java的保留字。 

三、Java标识符及命名规范

3.1 标识符概述

        应该说命名规范是一种约定,也是程序员之间良好沟通的桥梁。良好的命名规范可以为团队合作开发推波助澜,无论在项目开发,还是产品维护上都起到了至关重要的作用。

        Java 对各种变量、方法和类、接口等要素命名时使用的字符序列称为标识符(在Java里面,所有可以自己起名字的地方都叫标识符)。

3.2 标识符命名规则

1、由字母(含大小写)、数组、下划线“_”、美元符“$”组成
2、不能以数值开头。
3、不可以是Java的关键字和保留字,但能包含关键字和保留字。
4、严格区分大小写,且长度无限制。
5、见名之意。
6、驼峰原则:首字母小写,多个单词组成的话,首个单词的首字母小写,之后每个单词的首字母都大写

3.3 标识符命名规范

java采用匈牙利命名规范,它的基本原则是名称要有明确的意义。具体要求为:
        类名/接口名:首字母大写,如果包含多个单词,每个单词首字母都大写:XxxYyyZzz
        变量名/方法名:首字母小写,如果包含多个单词,每个单词首字母都大写:xxxYyyZzz
        常量名:全部大写,多个单词组成,则每个单词由_分割:XXX_YYY_ZZZ
        包名:全部小写,多单词组成时所有字母都小写:xxxyyyzzz。
                我们在项目中,包名一律使用这种方式:[cn.]com.公司名.项目名.模块名

注:java采用unicode字符集,因此标识符也可以使用汉字声明,但是不建议使用。

四、Java变量

4.1 变量的概念

        在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量。
                程序运行过程中会发生改变的量,叫变量
                程序运行过程中不允许发生改变的量,叫常量

        变量的本质:其实就是内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化,不同数据存入具有不同内存地址的空间,相互独立。    

        变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值

        变量的作用:用于在内存中保存数据

内存如何存放数据:

        电脑使用内存来记忆程序运行所使用的数据(程序中所有的数据都是存储在内存里面)

        内存如何存储数据?
                1、开房间(单人间、双人间、总统套间)     
                2、入住

        内存像旅馆
                数据各式各样,要先根据数据的需求(即类型)为它申请一块合适的空间

        已经将数据存入内存,但是:怎么找到存入的数据?

        内存地址不好记,怎么办?
                通过内存中房间的别名找到数据存储的位置。

        通过变量名可以简单快速地找到它存储的数据。

4.2 变量的定义与使用

要声明一个变量,需要指明变量的类型和变量名称。
        语法为:数据类型 变量名称
        例如:int var;
    
变量的赋值可以通过=,可以在先声明后赋值,也可以在声明变量时直接赋值。
        语法为:变量名称 = 值
        例如:var = 10;

声明并赋值变量。
        语法为:数据类型 变量名 = 初始化值
        例如:int var = 10;
    
使用变量,只需要使用变量名,就可以得到该变量的值。
        例如:System.out.println(var);

变量赋值后,可以改变。

Java变量示例代码:

// 声明变量,即“根据数据类型在内存申请空间” 数据类型 变量名;  
int num;

// 赋值,即“将数据存储至对应的内存空间”
num = 100;

// 使用变量,即“取出数据使用”
System.out.println(num);

//声明变赋值语法
int age = 100;

//重新赋值
age = 200;
age = 250;
String name = "张三";

使用变量注意事项:

1、Java中每个变量必须先声明,后使用
2、使用变量名来访问这块区域的数据
3、变量的作用域:其定义所在的一对{ }内 变量只有在其作用域内才有效
4、同一个作用域内,不能定义重名的变量

4.3 变量的分类

按数据类型划分:

        对于每一种数据都定义了明确的具体数据类型(强类型语言),在内存中分配了不同大小的内存空间。

 按声明的位置划分:

        在方法体外,类体内声明的变量称为成员变量。

        在方法体内部声明的变量称为局部变量,局部变量必须先声明并赋值才可以使用;        

        注意:类外面(类对应的大括号外面)不能有变量的声明不能有任何代码出现。

 局部变量、成员变量、静态变量的区别:

        局部变量定义在方法内部或语句块内部; 成员变量定义在方法外部,类内部; 静态变量定义在方法外部,类内部,由static修饰;
        局部变量没有初始值,必须先赋值才能使用; 成员变量和静态变量都由默认的初始值;
        局部变量通过变量名调用; 成员变量通过对象调用; 静态变量既可以通过对象调用,也可以通过类名调用;
        局部变量在栈内存; 成员变量在堆内存; 静态变量在方法区;
        局部变量的生命周期: 与方法共存亡; 成员变量的生命周期: 与对象共存亡; 静态变量的生命周期: 与类共存亡;

4.4 变量的数据类型

        Java语言是一门强类型语言,也就是说,每个变量或者符号常量甚至一个方法都必须有明确的数据类型或者是返回值类型。在 Java 中,数据类型分为两种,分别是基本类型和引用类型。
    
        基本类型一共有四大类八种基本数据类型,它们是:四种整型,两种浮点型,一种字符型和一种布尔型。
        引用类型有类,接口和数组等

基本数据类型

Java八种基本数据介绍:
        1、boolean:数据值只有true或false,适用于逻辑计算,占一字节
        2、byte:byte型(字节型)数据在内存中占用1个字节,表示的存储数据范围为:-128~127,因为第一位是符号位。
        3、char:char型(字符型)数据在内存中占用2个字节。char型数据用来表示通常意义上的字符。
        4、short:short型(短整型)数据在内存中占用2个字节
        5、int:int型(整型)数据在内存中占用4个字节。
        6、long:long型(长整型)数据在内存中占用8个字节。
        7、float:float型(单精度浮点型)数据在内存中占用4个字节。
        8、double:double型(双精度浮点型)数据在内存中占用8个字节。

1、整数类型

        从小到大取值范围分别是:byte、short、int、long。
    
        Java各整数类型有固定的表述范围和字段长度,不受具体 OS 的影响,以保证 java 程序的可移植性。
    
        Java 的整型常量默认为 int 型,声明 long 型常量须后加 ‘l’ 或 ‘L’

        1个字节 = 8bit,每一个bit都有两种情况 0 或 1,所以就存在2的8次方种组合,就可以存储256个数,语言规定一半正,一半负,但是因为存在0,所以规定是-128 - 127。

        表数范围公式:-2^位数-1次幂 ~ 2^位数-1次幂 - 1

 Java整数类型示例代码:

// 定义byte类型变量
byte b1 = 100;

// 定义short类型变量
short s1 = -100;

// 定义int类型变量
int i1 = 100000;

// 定义long类型变量
lonf l1 = 123456789L;

2、浮点类型

        与整数类型类似,Java 浮点类型也有固定的表数范围和字段长度,不受具体OS的影响。
    
        浮点型常量有两种表示形式:
                十进制数形式:如:5.12 512.0f 
                科学计数法形式:如:5.12e2 512E2 100E-2
    
        float:单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求。
        double:双精度,精度是float的两倍。通常采用此类型。

        Java 的浮点型默认为 double 型,声明 float 型变量,须后加 ‘f’ 或 ‘F’。

为什么float 4个字节比long 8个字节所表示的数值范围还大?

        为了方便说明,这里借用维基百科中【单精度浮点数】定义中的一张图。

        其中,左边第一位为符号位,0表示正,1表示负。上图中sign为0,所以为正数。

        中间8bit表示指数,但是这里和byte不同,byte型也是8bit,表示的数值范围是-27到27-1,即-128到127。这里exponent的8bit表示的则是-127到128。在IEEE 754(IEEE二进制浮点数算术标准)中规定,在指数的实际值上要加上一个固定的值,目的是为了方便浮点数的计算,该固定值为2e-1-1,其中e表示存储指数的bit的长度。在单精度浮点数中,e的值为8,所以固定值是127。所以,exponent中存储的数值是0(-127+127)到255(128+127),共256个数。在上图中,指数部分存储的是01111100,转换为十进制是124,124减去127(加的固定值)即为实际指数值,即-3。

        在小数部分中,最左侧省略了一个1,上图中的小数部分为01,其实就是1.01(二进制),转换为十进制就是1+2-2(这里看不懂的话去复习二进制小数转十进制)。
        所以,最终上图所表示的数值为(-1)sign × \times× fraction × \times× 2exponent = (+1) × \times× (1 + 2-2) × \times× 2-3 = 0.15625。

        不过还没有结束,关于浮点数其实还分为零、非规约形式,规约形式、无穷以及NaN,以4字节单精度浮点数为例,具体如下:

形式指数小数部分
0(实际-127)0
非规约形式0(实际-126)大于0小于1
规约形式1到254(实际-126到127)大于等于1小于2
无穷255(实际128)非0
NaN255(实际128)非0

        规约形式的浮点数就是指数大于0小于等于2e-2(e为8时值为254),fraction最高位省略了1。“规约”就是指用唯一确定的浮点形式去表示一个值。

        如果指数部分的值为0(实际-126,为什么不是0-固定值127 = -127?因为IEEE 754规定非规约形式的浮点数的指数偏移值比规约形式的浮点数的指数偏移值小1),小数部分不为0,那么这个浮点数就是非规约形式的浮点数,这个时候最高位省略的就不是1了,而是0了,所以小数部分是大于0小于1的。所有的非规约浮点数比规约浮点数更加接近0。

        下面列出了单精度浮点数各种极值的情况:

        我们常说的float型的表示范围其实说的是单精度浮点数最大的规约数的范围。

        回到这个问题,我想你已经有答案了。
                就是float型它有指数部分,规约数的指数可以表示到2127,差不多是1038这么大。

3、字符类型

        char 型数据用来表示通常意义上“字符”(2字节)。
    
        Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符。

        字符型变量的三种表现形式:
        字符常量是用单引号(‘ ’)括起来的单个字符。
                例如:char c1 = 'a'; char c2 = '中'; char c3 = '9';
        Java中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。
                例如:char c3 = ‘\n’; // '\n'表示换行符
        直接使用 Unicode 值来表示字符型常量:‘\uXXXX’。其中,XXXX代表一个十六进制整数。如:\u000a 表示 \n。

        char类型是可以进行运算的。因为它都对应有Unicode码。

        注:window cmd窗口的默认字符集是GBK,为了不乱码,Java文件应该以ANSI(window10没有GBK可选)。

4、布尔类型

        boolean 类型适于逻辑运算,一般用于程序流程控制:
                if条件控制语句; 
                while循环控制语句;
                do-while循环控制语句;  
                for循环控制语句;
    
        boolean类型数据只允许取值true和false,无null。
                不可以使用0或非 0 的整数替代false和true,这点和C语言不同。
                Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达所操作的boolean值,在编译之后都使用java虚拟机中的int数据类型来代替:true用1表示,false用0表示。

引用数据类型

        引用数据类型:类、接口、数组;
    
        String不是基本数据类型,属于引用数据类型。
    
        使用方式与基本数据类型一致。例如:String str = “abcd”;
    
        一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据。例如:
                String str = "qq";
                str = str + “xyz” ;
                int n = 100;
                str = str + n;
        
        注:我们暂且讲解String,其他内容在后面讲解。

4.5 基本数据类型转换

1、自动类型转换

容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:

        将一种类型的变量赋给另一种类型的变量时,只要满足以下条件,就会发生自动类型转换。
                两种类型兼容;
                目标类型大于源类型;

        有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。

        byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。

        boolean类型不能与其它数据类型运算。

        当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。

        注:这里的容量大小指的是表示数的范围的大小。比如float容量要大于long的容量。

2、强制类型转换

        自动类型转换(隐式转换)的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(),但可能造成精度降低或溢出,格外要注意。

        通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。
                例如: String a = “43”; int i = Integer.parseInt(a);

        boolean类型不可以转换为其它的数据类型。

判断是否能通过编译:

short s = 100;
s = s-1; //判断:no

byte b = 10;
b = b + 4; //判断:no
b = (byte)(b+4); //判断:yes

char c = 'a';
int i = 5;
float d = .314F;
double result = c+i+d; //判断:yes

byte b = 5;
short s = 3;
short t = s + b; //判断:no

3、类型转换对于表达式

        如果一个操作数为 long 型,则整个表达式提升为 long 型。
        如果一个操作数为 float 型,则整个表达式提升为 float 型。
        如果一个操作数为 double 型,则整个表达式提升为 double 型。
        在整个运算表达式中找到最大的类型,这个类型及是表达式运算后的类型。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是波哩个波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值