个人Java开发初学笔记 2020.5.22更新

个人Java开发初学笔记 2020.5.22更新

java开发

编写java的步骤
  1. 写源文件,源文件的扩展名是.java

  2. 对源文件进行编译

    1. 不带包名的编译

      rem
      目录:>javac HelloWorld.java
      
    2. 带包名的编译

      rem
      目录:>javac  -d .  HelloWorld.java   //.就是当前文件夹
      
  3. 对编译生成的.class文件做执行

    1. 不带包名的执行

      目录:>java HelloWorld
      
    2. 带包名的执行

      目录:>java cn.edu.tit.core.java.test.HelloWorld
      

规范
  1. 类名每个单词首字母都大写

  2. 方法名首字母小写,后面首字母大写,构造方法首字母大写和类名一样

  3. 变量名、属性名首字母小写,后面首字母大写,驼峰Camel命名法

  4. 项目、包名名全小写

  5. 接口名以 I 开头

  6. 运算符" = “左右加空格” "

  7. 方法、属性前都要加注释(方法名、形参[param]、返回值[return]都要注释) ** /+Enter 文档注释

    public class Student {
    	/**学生姓名*/
    	private String name;
    		/**
    		 * 学生根据课程名称选课
    		 * @param courseName 学生选择的课程
    		 * @return 如果选课成功返回true,否则饭后false
    		 */
    	public boolean selectCourse(String courseName) {// course课程
    		System.out.println("我选择了课程:" + 	courseName);
    			return true;
    		}
    }
    
  8. API文档:(JavaDoc文档)项目的说明文档:Project>Generate Javadoc

    • C:\Program Files\Java\jdk1.8.0_241\bin\javadoc.exe
    • -encoding utf-8 -charset utf-8

杂货
  • void :为空 与return互斥
  • C语言里的结构体 ~ C++和Java的类
  • C++的构造函数 = Java的构造方法
  • int小写 String大写
  • 最好加一个无参数的构造方法
  • 程序执行必须要有主方法main
  • 返回值只能有一个。但是返回的可以使任和的对象。所以你可以吧你想要的多个值分装到一个javaBean中。获取后直接返回这个javaBean。然后用get方法取出来就可以了
  • a*1.0 将整数int a 变为小数float a
  • 整数除0报错 3.0/0 正确 3/0 错误

固定代码
获取输入值
//用sc对象接收键盘数据
Scanner sc = new Scanner(System.in);
System.out.println("请您输入出生年份");
//接收用户在键盘上输入的整数
int birthyear = sc.nextInt();//控制回车输入

sc.next()//不吸取字符前/后的空格/Tab键,直到遇到空格/Tab键/回车截止吸取
sc.nextLine()//吸取字符前后的空格/Tab键,回车键截止
获取随机数
Math.random()		//获取(0,1]之间的随机小数
Math.random()*50	//获取(0,50]之间的随机小数
(int)(Math.random()*50)	//强制转换为整数
浮点数保留小数点后n位
//四舍五入
java.text.DecimalFormat   df=new   java.text.DecimalFormat("0.00");//保留2位
double   d=3.148;  
System.out.println(df.format(d)); //输出3.15

//全部舍去  得导入import java.math.BigDecimal包
BigDecimal bd = new BigDecimal(3.148);
bd = bd.setScale(2,BigDecimal.ROUND_FLOOR); //保留2位
System.out.println(bd); //输出3.14

//小数点后全部舍去,并保留小数点一位0
double d = 13.4324;  
d=((int)(d*100))/100;//输出13.0  因为d还是double型
退出程序
System.exit(0)

快捷代码操作
  • \ 转义字符,让后面字符失去特殊的含义
  • \t 制表符,tab,补全当前字符串长度到8的整数倍,最少1个最多8个空格
  • \n 换下一行,不换列 next
  • \r 回车,回到当前行的行首,不换行
  • /**+Enter 文档注释
  • // 单行注释
  • /* 多行注释
  • main 生成主方法
  • { } 游离语句块
  • @Override 注解

.java命名规则
package cn.edu.tit.core.java.test01;

//如果在一个java文件里有多类,保存文件的时候,要求:文件名和被public修饰的类名一致
//所以在一个java文件里最多有一个public类

public class Animal{
	//public类名Animal 应该与文件Animal.java一致
}

class Dog{
	
}

class Cat{
	
}//生成了三个.class文件

开发java的IDE
  1. Eclipse (汉语意思:日食) (Free) [www.eclipse.org]
  2. IDEA (charge)
  3. NetBeans (Oracle出品,Free)

Windows系统,不区分大小写,别的区分

Eclipse
设置
  1. 设置编码为UTF-8:Window>Preference>General-Workspace-Text file encoding-Other-UTF-8
  2. 设置自动提示:Window>Preference>Java>Editor>Content Assist
  3. 切换工作空间:File>Switch Workspace
  4. *不要汉化!!!
  5. 安装插件
    1. 关闭eclipse
    2. eclipse>plugins>.jar插件复制进来即可
快捷键
  • 单行注释——Ctrl+/
  • 多行注释——Ctrl+Shift+/
  • 取消多行注释——Ctrl+Shift+\
  • 格式化代码——Ctrl+Shift+F
  • 移动代码行——Alt+↑/↓
  • 复制代码行——Ctrl+Alt+↑/↓
  • 选择代码行——Shift+方向键
  • 快速定位行——Ctrl+L
  • 跳到最后编辑的位置——Ctrl+Q
  • 重命名文件——Alt+Shift+R
  • 批量重命名变量——Alt+Shift+R
  • 捕获异常——Alt+Shift+Z -> try/catch
  • 放大还原代码区——Ctrl+M
  • 运行——Ctrl+F11
  • 查看全部快捷键——Ctrl+Shift+L
  • 关闭全部窗口——Ctrl+Shift+W
  • 关闭当前窗口——Ctrl+W
  • 切换窗口——Ctrl+E Alt+←/→
  • 向下添加空行——Shift+Enter
  • 向上添加空行——Ctrl+Shift+Enter
  • 快捷封装——Alt+Shift+S–>Generate Getters and Setters
  • 快捷创建构造方法——Alt+Shift+S–>Generate Constuctor Using Field
  • 快捷重写hushCode和equals方法——Alt+Shift+S–>Generate hushCode() and equals()
  • 菜单栏选择——Alt+下划线字母
  • 当前光标位置菜单栏选择——Alt+Shift+下划线字母
操作
生成doc文档

在这里插入图片描述

导出jar包

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

一直点下一步,点Finish,生成jar包

在这里插入图片描述

.jar本质是java语言的压缩格式

在这里插入图片描述

导入jar包

在项目目录里导入jar包

在这里插入图片描述

在这里插入图片描述


基础知识
  • JDK、JRE、JVM关系是什么?

    答:JDK(Java Development Kit)-Java开发工具

    ​ JRE(Java Runtime Environment)-Java运行环境

    ​ JVM(Java Virtual Machine)-Java虚拟机

    ​ JDK开发工具包括JRE运行环境(JVM虚拟机+Java系统类库)和Java工具

  • Java程序的执行过程?

    答:编写.java源程序,用javac编译(compile)产生.class文件,用java命令执行.class文件,显示相应的效果

在这里插入图片描述

  • .class文件是什么文件?
答:**字节码(*bytecode*)**文件
  • .class文件中是什么内容?

    答:JVM能够识别的字节码,内容是16进制

  • .class文件是平台相关or无关?

    答:平台无关/跨平台

    ​ #Java语言唯一跨平台

  • .class文件可以看到吗?

    答:可以看到

    ​ #UE(UltraEdit)文本编辑器 16位字节码 第一行是CA FE BA BE(咖啡宝贝)

  • JVM是平台相关or无关?

    答:平台相关,不同OS(operating system)有不同JVM

在这里插入图片描述

  • JVM的作用是什么?

    答:将字节码文件翻译成特定平台的机器指令

    ​ #机器语言(机器码/原生码)->汇编语言->高级语言

  • Java平台的划分?

    1. Java SE平台标准版
    2. Java EE平台企业版#J2EE
    3. Java ME 平台微型版#手机
    4. #Java Card 卡式版本
  • Java语言有什么特点?

    • 平台无关
    • 面向对象
    • #一共十个特点
  • Java语言是编译型or解释型?

    答:二者结合

  • C/C++/Java的区别?

    答:C:硬件编程、算法(与数学有关)、操作系统级编程(与硬件有关)

    C++:面向对象,但不是纯正的OOP,在C基础上加入了OOP的内容

    ​ 算法、图形图像软件、嵌入式QT、通讯软件、工业控制软件等

    Java:纯OOP,纯面向对象,开发B/S结构的大型Web应用、教务系统、12306、Android APP;Java大数据开发 #平台无关

    ​ C#:和Java类似,是微软的技术,开发的软件只能在Windows执行,VR、U3D,极少人

    ​ Go:

    ​ Python:

  • HelloWorld面试题:

在这里插入图片描述

public去掉:可以编译,不能执行

static去掉:可以编译,不能执行

void去掉:不能编译

String去掉:可以编译,不能执行

String[] args去掉:可以编译,不能执行

args改变:可以执行

[]改变:可以执行

public static->static public:可以执行

static void->void static:不能编译

…->void main(){}:可以编译,不能执行

#保存后出现红波浪线则不可以编译

  • javac和java面试题

    • wins平台下,javac编译不区分大小写,其他OS严格区分
    • wins平台下,java执行区分大小写

面向对象编程——设计并使用类
面向对象程序设计OOP(Object Oriented Programming

一种编程方式,也是一种编程思想(就是思考问题的方式)

P.S. 编程方式有哪些?

  1. 面向过程编程:C
  2. 面向对象编程:Java、C++、C#、Python
  3. 面向组件编程
  4. 面向服务编程(高级):前后端分离,微服务
类与对象

P.S.软件开发的流程是什么?

  1. 招投标
  2. 签合同
  3. 建立项目组:PM项目经理(Project Manager)——TL组长(Team Leader )——码农
  4. 需求调研与分析:需求分析工程师/需求管理工程师
  5. 数据库设计:DBA数据库管理员(Database Administrator
  6. 架构设计:架构师
  7. 详细设计:系统分析师
  8. 编码(开发):研发工程师(初、中、高)
  9. 测试:测试工程师
  10. 部署实施:实施工程师
  11. 甲方验收
  12. 维护:技术支持工程师/售后
OOP开发主线(三步走)

写类——创建对象——对象调用方法(属性)

在这里插入图片描述

Q:先设计,根据设计写代码,先技术谁?A:类

  1. 写类

    • 类:类型的简称 同一类型抽象的概念

      类=属性+方法

      设计类:ULM设计工具 统一建模语言(Unified Modeling Language) 用来设计软件的语言,不是编程,是图形符号

    • 方法(操作/函数):可见性(visibility)[pubilic/private]、返回类型、方法名、形式参数、方法体

      可见性 返回类型 方法名(参数类型 形式参数){方法体}

      方法不能嵌套

      • 构造方法:名字和类名相同,没有返回类型

        一个类可定义多个构造方法

        构造方法的作用?

        1. 给对象属性赋值
        2. new配合创建(初始化)对象
        public class Teacher {
        	private String teacherName;//属性	
        //给对象的属性赋值:没有返回值:*构造方法↓   方法名和类名相同
        	public Teacher(String name) {
        [前面属性定义类型]teacherName = name;
        	}
        //不是构造方法,有返回类型void,是一般方法↓
        

      public void Teacher{}
      //不是构造方法,名字大小写不一样
      public teacher{}
      //无参构造方法
      public Teacher{}

      
      **在JAVA中如果不写构造方法的话,会默认加上一个无参数的构造方法**,但是如果已经有了一个有参数的构造方法,那么无参数的构造方法就不会默认被加上.
      
      如果Hello类中已经有了一个有参数的构造方法,这时再使用 Hello hello = new Hello();来创建对象的时候就会出错,这就是为什么书上要强调写了有参数的构造方法就**最好加一个无参数的构造方法**.
      
      **构造方法的重载**:方法名相同,但参数不同的多个方法,调用时会自动根据不同的参数选择相应的方法。
      
      ```java
      Hello hello = new Hello()//调用无参构造方法
      Hello hello = new Hello("h")//调用有参构造方法
      
    • 属性可见性 类型 属性名;

      可以自定义初值

      属性都有默认初值,对象默认为null,数字默认为0

      public class Teacher {//在类开头建属性
      	private int age = 30;//30
      	private int telnumber;//0
      	private String name;//null
      }
      
      • 显式赋值和默认赋值

        String name ="tit";		//显式赋值
        int age;				//默认赋值
        
      • 属性赋值过程如何? 父类->子类

        1. 默认赋值

        2. 显式赋值

        3. 构造方法赋值

          String name = "tit";
          new Student ("nuc");
          //name值变化过程如何?
          //null-->tit-->nuc
          
  2. 建对象(放在堆区)

    • 对象:具体,世间万物皆对象

      拥有所属类的全部属性

      类 对象名 = new 构造方法() //建对象

    • 建变量:类型 变量名

      每个变量都有确定的类型

  3. 对象调属性

    • 对象.属性 //用对象的属性
  4. 对象调方法

    • 对象.方法(实际参数)
  5. 代码:

    public class Student {//写类
    	/**学生姓名*/
    	private String name;//写属性
    	public void bite(String name) {
    			System.out.println(name + "被咬了!");//写方法
    		}
    }
    public static void main (String[] args) {
    		Student lizeya = new Student();//创建对象,使用new新建对象
        
    		lizeya.bite("图灵");//对象调用方法,完成功能
    	}
    >>>图灵被咬了!
    
  • Q&A

    • 什么是OOP?

      A:面向对象程序设计

      面向:按照,强调,针对

    • 类和对象有什么区别?

      A:类是抽象的,对象是具体的,类是对具有共同特性的概括

    • 面向对象和面向过程的区别?

      1. 面向过程:代表语言C,强调过程,过程不正确,结果就不正确;编程有严格的先后次序;以函数为单位编程。
      2. 面向对象:强调是结果,编程单位是类。
    • 面向对象(OOP)的特征?

      1. 封装
      2. 继承
      3. 多态
      4. (抽象)

11种基本数据类型
两大类
  1. 8种内置数据类型(简单数据类型)【放在栈区】
  2. 3种引用数据类型(复合数据类型)【放在堆区,栈区放堆的地址】
八种基本数据类型
  • 四种整型数

    1. byte字节型:

      长度1个字节,8位,范围-128~127

    2. short短整型:

      长度2个字节,16位,范围-32768~32767

    3. int整型(整数默认):一般地整型变量默认为 int 类型

      长度4个字节,32位,范围-2,147,483,648~2,147,483,647

    4. long长整型:

      长度8字节,64位,范围-2(n-1)~2(n-1)-1

      2,147,483,648L L/l必须有,不建议用l

      2,147,483,647 当小于等于int最大值,可以不加L/l

  • 其他

    1. char字符型:(汉字2字节)

      【字符用单引号' ',字符数不用】

      长度2个字节,16位,范围:0~65535。本质是数字

      一般输出为字符,97'\u0097'都输出a

      转义字符

      Java用Unicode编码

      • UTF-8【Unicode基础,世界,英1B,汉3B】
      • ISO-8859【ASCII+,1B】
      • GBK【中文,中英都是2B】
      • GB2312【GBK+,中文2B】
      • ASCII【英文1B】
    2. float浮点型: 十进制浮点数->二进制浮点数 可能产生精度损失

      1 - 0.9 = 0.09999999999999998

      长度4个字节,32位

      1.8F F/f必须有 1.8错!

      .8F = 0.8 8.F = 8.0

    3. double双精度浮点型(小数默认):

      长度8个字节,64位

    4. boolean布尔型:

      长度无精确定义,取值是true/false 不能是1/0

    5. String不是内置类型,只是API应用程序接口(Application Program Interface)中的一个类

  • Q:Java语言各种数据类型长度如何?数据类型的长度会不会随平台变化?

    A:不会!

金额数据类型
  • 我们可以使用BigDecimal来表示金额,或者是通过将金额的单位变小用整数来表示金额。
三种引用数据类型(复合类型)

(引用类型以对象形式存在,有属性和方法)

  1. 类:class
    1. Address addr;(自己编写的类)
    2. String name;
  2. 接口:interface
  3. 数组:array
数据类型的转换
  • boolean不参与

  • byte1,short2,char2—> int4 —> long8—> float4 —> double8

  • 低级给高级,自动转换

    高低给低级,强制转换

    int num1 = 90;
    double num2 = 100;
    num1 = (int) num2;  //强制转换,失去位数
    
默认值

属性都有默认值,对象类型默认值为null,整数为0,浮点数为0.0,字符型为0,布尔型为false

面试题
  1. 什么是标识符?命名规则是什么?

    A:标识符就是名字,以 _、$、文字开头,后面可以是数字、_、文字、数字(长度不限)

  2. 什么是关键字?特点?

    A:保留字,有特殊含义,全大写,标识符不能用

    null/true/false不是关键字,也不能起名字

  3. 局部变量和成员变量的区别?

    A:属性就是成员变量,有默认值

    方法内定义的变量、形参是局部变量,无默认值,必须明确赋值

    当局部变量和成员变量名字相同时,局部变量会覆盖成员变量

    如何区分——看定义的位置

  4. 内存逻辑划分?各部分作用?

    • :先进后出,压着

      存放局部变量:由OS管理:用于频繁的数据交互

    • :存放new出来的对象【大于栈】

    • 全局数据区:存放全局变量

    • 代码段:存放程序代码

  5. java中的垃圾回收机制(GC机制[Garbage Collection])?

    A:垃圾:无用对象

    Java语音采取自动垃圾回收机制

    有一个垃圾回收的线程,在扫描内存中的无用对象,无指向的对象,自动回收

    目的:减轻程序员的负担,减少了内存泄漏

  6. 能不能通过编程手段强迫JVM进行垃圾回收?

    A:不能。 System.gc()也不行,仅仅建议JVM进行垃圾回收

    finalize()回收前最后一个运行一次的方法

  7. Java回收中是否有可能存在内存泄漏?

    A:有可能存在


语句和运算符
package包
  • 包名字命名规则

    1. 目的:多人开发,不同人不同包,避免类名相同引发的冲突

    2. 全小写,不建议使用数字

    3. 域名倒写+系统名+模块名字+层次名
      cn.edu.tyust.项目代号.模块代号

      cn.edu.tyust.hr.emp;

      package cn.edu.tit.jobtrace.student.vo//层次名
      package cn.edu.tit.jobtrace.student.service
      package cn.edu.tit.jobtrace.student.dao
      
  • 导入包

    import java.util.Scanner;	//导入包内一个类
    import java.util.*;			//导入包内所有类
    
    • 常用包

      java.lang 核心包,直接可用,自动导入

      .lang.reflect 反射相关(不支持嵌套导入)

      .io 输入输出包,文件读写

      .util 工具包

      .Math 数学包

      .text 文本处理

      .sql 数据库

    • 基础包:java开头

    • 扩展包:javax开头

    • 第三方包:org/com开头

    • 自定义包:自己编写的

运算符
  • 算数运算符

    • 前缀自增自减法(++a,–a): 先进行自增或者自减运算,再进行表达式运算。
    • 后缀自增自减法(a++,a–):先进行表达式运算,再进行自增或者自减运算
  • 关系运算符

    • == != > < >= <=
    • 判断,返回true/false
  • 逻辑运算符

    • && 逻辑与
    • || 逻辑或
    • ! 逻辑非
  • 位运算符

    • 八位二进制,第一位为符号位,0是正,1是负

    • & | ^ ~ << >> >>>

    • A = 0011 1100	//60
      B = 0000 1101	//13
      -----------------
      A & B = 0000 1100		
          //&:与(乘),对应位都为1,则结果为1,否则为0
      A | B = 0011 1101	
          //|:或(加),对应为都为0,则结果为0,否则为1
      A ^ B = 0011 0001	
          //^:异或,对应位相同,则结果为0,否则为1
      ~A= 1100 0011		
          //~:取反
      A << 2->240,即 0011 1100->1111 0000
          //按位左移运算符,低位补0
      A >> 3->7,0011 1100->0000 0111
          //按位右移运算符,高位补符号位
      A >>> 2->15,0011 1100->0000 1111
          //无符号右移,按位右移补零操作符,高位补0
      
  • 赋值运算符

    • += -= *= /= %= &= |= ^= >>= <<=

    • i += 1 运算速度快于 i = i +1 没有开辟新存储单元

    • short a = 1;

      a = a + 1 错误!! 其中1默认是int型,高级->低级 错误!

      a += 1 正确!! a = (short)(a + 1) 正确!!!

    • ↑ byte,char,short类型在运算的时候自动变成int,或者说是JVM把它们以int来考虑。只要右侧的值不超范围就对。

  • 补充:

    • (/整除时舍去全部小数)
语句

if , if else , for , while , do while , switch , break , continue

  • 条件语句

    1. Q:switch()中的变量可以是什么类型?

      A:String,byte,short,int,枚举

      (长整型long,布尔型boolean,浮点数不可以!)

--------------------swtich case语句-----------------------
switch(expression变量){
        //判断一个变量与一系列值中某个值相等,每个值称为一个分支
    case value://跟冒号:,value是常量
        //语句
        break;//可选,break跳出整个switch语句
    case value:
        //语句
        break;//可选
    case 1:
    case 2://12可用同一个break,不能用||break;
    //你可以有任意数量的case语句
    default://默认可选,Java关键字,没有顺序
        //语句
}
-----------------------if else语句------------------------
if(布尔表达式){
    //如果布尔表达式的值为true
}
else{//可选
    //如果布尔表达式的值为false
}//可以嵌套if语句
-----------------if...else if...else语句------------------
if(布尔表达式 1){
   //如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
   //如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
   //如果布尔表达式 3的值为true执行代码
}else {
   //如果以上布尔表达式都不为true执行代码
}	//if 语句至多有 1 个 else 语句
  • 循环语句
------------------------while语句-------------------------
while( 布尔表达式 ) {//为true被执行,false终止
  //循环内容
}
--------------------do...while语句------------------------
do {
   //代码语句
}while(布尔表达式);//为true被执行,false终止
------------------------for语句---------------------------
for (初始化;boolean表达式;循环更新){//为true被执行,false终止
    循环语句		//↑表达式可为空  
    //循环更新语句在循环语句后执行
}
----------------------for each语句------------------------
for(声明语句int x : 表达式intArray)
{
   System.out.print( x );//代码句子
}//输出12345678
---------------------死循环-----------------------------
for(;;){}
while(ture){}
while(1){}

数组Array

总结:数组是一种线性(类型单一)数据结构,不能在一个数组里存放不同类型的数据。数组的长度在new的时候指定。不能越界取值或赋值。有默认值

声明数组变量
声明数组变量
dataType类型[] arrayRefVar数组名;   // 首选的方法,[]放中间
int [] intArray;
或
dataType arrayRefVar[]; //效果相同,但不是首选方法,C/c++是这样
创建数组
  • 使用new,在new的时候在右边[ ]指定长度

    int [] score = new int[4];
    //长度4,即0~3四个元素,不可省略
    
初始化(赋值)数组元素
  • 静态初始化

    • 声明时赋值

      int [] intArray = {34,45,21,90};
      //错误!!! intArray = {34,45,21,90}
      //错误!!! int [4] intArray = {34,45,21,90}
      
    • 元素默认初值,随类型默认值,int 为 0

    • new创建时赋值

      int [] sa = new int[] {10,20,30};//逗号隔开
      //不能写长度
      
    • 直接赋值

      int [] score = new int[4];
      score [0] = 10;
      score [1] = 20;
      //错误!! score [4] = 50;  第5个元素>数组长度4
      
  • 动态初始化

    int [] roommateNum = new int[8];
    		for (int i = 0; i < roommateNum.length; i++) {	roommateNum [i] = i+1 ;	}//java不允许跨界取值
    ystem.out.println(roommateNum[7]);//输出8
    
  • 面试题

    1. length和length()什么区别?

      A:length是数组的属性,代表数组长度;length()是String类的方法。

    2. 数组是不是引用类型

      A:是。引用类型有三种:类,接口,数组。

      引用类型以对象形式存在。所以放在堆区。

数组排序方式
  1. 冒号排序

    public void sort (int [] beforeArray) {
        //形参beforeArray已被排序
    		int temp = 0;
    		for (int i = 0; i < beforeArray.length-1; i++) {
    			//单次冒泡,比较次数i越来越少
    			for (int j = 0; j < beforeArray.length-i-1;j++) {
    				//如果左边大于右边,位置互换
    
    				if (beforeArray[j] > beforeArray[j+1]) {
    					temp = beforeArray[j];
    					beforeArray [j] = beforeArray[j+1];
    					beforeArray [j+1] = temp;
    				}
    			}
    		}
    	}
    	public static void main(String[] args) {
    		BubbleSort bubbleSort = new BubbleSort();
    		int [] score = {100,90,80,70,60,50,40,30,20,10,0};
            //实参score已被排序,不用赋值		
    		bubbleSort.sort(score);
    		for (int x: score) {
    		System.out.println(x);
    		}
    	}
    
  2. 利用Java API对数组进行排序

    import java.util.Arrays;//从小到大排序
    Arrays.sort(数组);
    

OOP面向对象——封装

private修饰的属性,只有在本类、当前类中使用或可见。

如何实现封装?(在别的类中使用其他类中private属性)
  • 封装的目的:保护数据。
  • 如何实现:属性私有,提供公共方法使用属性。
  • 快捷封装——Shift+Alt+S–>Generate Getters and Setters

OOP面向对象——继承

对类的复用(重用)

语法规则:class 子类名 extends 父类名

Object类是所有类的定级父类
父类的属性和方法(一般方法)可以被继承
  • 不一定全部可以继承
  • 访问控制符
  • 构造方法不能被继承
  • **创建子类对象时,父类的无参构造方法会被自动调用。**先执行父类的构造方法,后执行子类的构造方法
  • 继承关系是自下而上。构造次序是自上而下。
public class Food (int n){//有参构造方法
	int prize;
	String color;
}
class Banana extends Food{
    super(20);//用super调用父类的有参构造方法
	char vitamin;
}
面试题
  1. java中支持多重继承吗?

    A:不支持。java中使单继承。

    ​ 一个类只能有一个直接父类

  2. 父类没有无参构造方法,还能创建子类对象吗?

    A:可以。只不过我们需要改变程序的默认行为,明确指明调用哪个构造方法(因为默认没有无参方法)

    使用super()关键字调用父类的有参构造方法,必须放在构造方法的第一行

  3. 子类方法中如何调用父类的一般方法?

    A:super.父类方法() 或者直接调用 父类方法()

  4. 子类方法中如何使用父类的同名属性?

    A:super.父类属性 直接调用的话,因为就近原则,调用子类属性

方法的重写 Override规则

父类的方法无法满足子类的需要,子类可以对父类的方法进行重写

本质就是改变方法体

  • 构造方法不能重写 因为不能被继承

  • 规则:方法名相同、参数列表相同(不考虑形参的名字)、返回类型相同、访问控制符相同或范围更广。

    public class Person(){
        String name;
        protected void speak(String t,int a){
            System.out.println("Person");
        }
    }
    class Student extends Person {
        int score;
        public void speak(String h,int b){//重写
            System.out.println("haha");
        }
    }
    
  • 父类中的equals()无法实现正确的比较,我们就可以重写他。

方法的重载 Overload规则

在一个类里有多个同名方法。就构成了方法的重载

  • 规则:方法名字相同,参数列表必须不同,返回类型和修饰符不限

  • 重载发生在一个类的内部,重写发生在有继承关系的两个类之间。

  • 构造方法可以重载

  • 如何在本类的一个构造方法中调用另一个构造方法?

    使用this()这种写法,必须在方法的第一行

    this代表当前类,本类对象

protected void speak(String a,int b){}
public void speak(){
    this("哈哈",23);//调用第一个构造方法
}
  • this和super用于构造方法的时候,不能同时使用,因为他们都要在第一行
创建子类对象时,程序的执行过程?
  • 父类子类只有无参的构造方法,父->子
  • 父类子类中有属性赋值动作,父->子,默认赋值->显示赋值->构造方法赋值
  • 父类子类中有游离块,看位置

OOP面向对象——抽象

如果一个类里有抽象方法,那么这个类一定是抽象类

抽象类(模板设计模式)
  • abstract修饰的class类 【可在修饰符前后,一般在public后】
  • 目的:被子类继承,达到类的复用
  • 抽象类不能建立对象,有构造方法
抽象方法
  • abstract修饰 且 没有方法体【没有{ }】 的方法
  • 目的:被子类重写

OOP面向对象——多态

多态:多种形态,多种状态。一个对象被多种称谓。

ps:非洲无毛狗<狗<动物;

他们之间有继承关系,因此多态发生的话,前提条件是有继承关系或实现关系存在。

多态的代码表现

子类对象被声明为父类类型=左右两边类型不同,左父右子。

子类能调用父类方法,父类不能调用子类方法

多态发生的情形
  1. 继承关系
  2. 实现关系(接口和类)
HairlessDog dog1 = new HairlessDog();//不是多态
Dog d = new HairlessDog();//是多态,d的类型是Dog
Animal a = new HairlessDog();//是多态
Animal a2 = new Dog();//是多态
-----------------------------------------------------
PersonImpl person1 = new PersonImpl();//不是多态
Iperson person2 = new PersonImpl();//是多态
person2.eat();//接口对象可以调用实现类的接口方法
多态的作用

增强代码的复用性;在这个例子里,增强方法的适应能力,形参可以接收很多对象了。

关键字instanceof

用于判断对象类型,返回值是boolean

instance:实例(对象),创建对象(实例化)

Animal a = new HairlessDog();
System.out.println(a instanceof Animal);//Ture
System.out.println(a instanceof Animal);//Ture
System.out.println(a instanceof Animal);//Ture
虚方法调用

与方法重写有关系

在多态情况下,如果子类重写了父类的方法,方法调用以子类为准。

//虚方法调用
IPerson person = new PersonImpl();
person.speak();//以PersonImpl子类为准
person.eat();//以PersonImpl子类为准

接口 interface

接口是java中引用类型之一(类、数组、接口)

作用
  • 作用:解耦。(降低耦合,结合起来) 为了软件容易维护

  • 高内聚,低耦合(在一个模块内部内聚行越高越好,不同模块之间耦合度越低越好,没关系最好)

    耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量

    解耦字面意思就是解除耦合关系,减低耦合度

语法规则
  • I 开头命名 public interface IPerson
  • 接口中的方法有可能有方法体{ },可以是default,static方法(JDK 1.8 以后,接口里可以有静态方法和方法体了。
  • 接口中的属性必须明确赋值,是常量值不能更改(默认static修饰)
  • 方法默认被public abstract修饰
  • 属性默认被public static修饰
类实现接口

implements 实现接口的类名为****Impl 结尾

类在实现接口的时候,方法前的public是必须的,因为重写规则要求

  //类实现接口的时候,要把接口的抽象方法都要变成具体方法
  //如果没有全部具体化接口中的抽象方法,那么这个类就成了抽象类了
  public class PersonImpl implements IPerson{
      @Override  //类在实现接口的时候是对其中抽象方法的重写
      public void speak(){
          System.out.println("speak");
      }//接口中为public void speak(){}
  }
面试题
  • Q:接口是特殊的抽象类?

    A:不准确

  • Q:接口能建对象吗?

    A:不能,准确类才能

  • Q:接口如何用?

    A:被类实现,类Impl+implements+接口

    ​ 实现接口的类名为Impl 结尾

  • Q:一个类能否实现多个接口?

    A:可以,implements class1,calss2,calss3{}

    间接实现了多重继承

  • Q:一个类能否有多个直接父类?

    A:不能,单继承。Java里不支持多重继承

  • Q:接口之间的继承关系如何?

    A:接口之间可以继承 extends

    ​ 接口之间支持多重继承

    public interface IThird extends IFirst,ISecond{}
    
  • Q:接口与抽象类的区别?

    A:接口:

    ​ 接口是引用类型之一,接口中的方法是抽象的/是default/static的;

    ​ 属性默认被public,static,final修饰;

    ​ 接口作用是解耦;

    ​ 接口不能建对象;

    ​ 类来实现接口。 接口不是类,没有构造方法

    抽象类:

    ​ 被子类继承,为了类的重用(复用);

    ​ 抽象类中有构造方法,可以有具体方法;

    ​ 接口和抽象类是不同的数据类型

  • Q:抽象类中一定有抽象方法吗?

    A:不一定

  • Q:有抽象方法的类,一定是抽象类吗?

    A:一定是。

  • Q:抽象类能否实现接口?

    A:能

  • Q:抽象类能继承接口吗?

    A:不能

  • Q:接口能继承抽象类吗?

    A:不能,不是一种东西

  • Q:类能否实现多个接口?

    A:能

  • Q:接口能实现接口吗?

    A:不能,只能继承

  • Q:继承父类(较具体)和实现接口优先性?

    A:一个类可以先继承extends,再实现接口implements;

    ​ 不可以先实现接口,后继承


static和final
final作用及如何使用

final能够修饰:属性、变量、方法、类

  • 修饰属性、变量:值不能更改,也就是常量

  • 修饰方法:这个方法不能被重写

  • 修饰类:这个类不能被继承

  • 面试题:

    1. final修饰的属性,只能显式赋值,或者构造方法赋值,二选一。

    2. final修饰复合类型(对象),对象的属性可以修改。

    3. A:构造方法能否被final修饰?

      Q:不允许

    4. A:final和abstract能否同时修饰一个类?

      Q:不能,final不允许继承,abstract需要被继承

public class Doctor {
	final int age;//构造方法赋值
	public Doctor(int age) {
		this.age = age;//this为当前类对象
	}
}
----------------------------------------------
public class Doctor {
	final int age = 21;//显式赋值
		  int weight;//不被final修饰,之后可以修改
}
static作用及如何使用

static可以修饰:属性、一般方法、游离块static{ }、内部类

static{ }游离块在main之前就要执行。与类加载机制有关。在类加载的时候就执行了,静态static执行只有一次

  • static修饰称呼:

    1. static属性:静态属性、类变量。<类>.<属性>或者<对象>.<属性>
    2. static方法:静态方法、类方法。<类>.<方法>或者<对象>.<属性>
  • static属性和方法,可以用类名直接调用,可以不创建对象。当然,对象也能调用属性和方法

    new Student().eat();//没有对象名,匿名对象
    					//<对象>.<方法>
    Student.eat();		//类名直接调用
    eat();				//相当于当前类调用
    
  • static修饰属性:被所有对象和本类对象共享,在内存里只存储一个,全部对象的静态属性值一致。

    非静态属性每个对象拥有自己的一个。

    public class Student {
    	static int age;
    	public static void main(String[] args) {
    		Student s1 = new Student();
    		Student s2 = new Student();
    		s1.age = 11;
    		s2.age = 88;
    		System.out.println(s1.age);//88而不是11
    		System.out.println(s2.age);//88
    		Student.age = 100;//类直接调用属性
    		System.out.println(s1.age);//100
    	}
    }
    
  • static修饰方法:

    静态方法里不能用非静态属性,只能用静态属性。

    静态方法里可以用对象.eat()调用非静态方法,不能直接eat()调用。

    非静态方法可以用静态属性。

  • 面试题:

    1. Q:static能不能修饰外部类、局部变量和构造方法?

      A:不能

    2. Q:static属性存放在内存的哪个区域?

      A:全局数据区(全局区)

    3. Q:static变量何时加载?加载几次?加载次序如何?

      A:类被载入JVM的时候就加载了,在主方法之前;

      ​ 加载一次;

      ​ 按定义的先后次序加载。

    4. Q:static游离语句块何时加载?有何作用?加载次序如何?作用如何?

      A:类被载入JVM的时候就加载了,在主方法之前;

      ​ 加载一次;

      ​ 按定义的先后次序加载;

      ​ 作用:在主方法main初始化前,做初始化用。

    5. Q:static方法中能否调用非静态方法?非静态方法能否调用静态方法?

      A:static方法可以通过对象调用.speak()非静态方法,不能直接调用speak()

      ​ 非静态方法可以直接调用静态方法。

    6. Q:主方法main前static可以省略吗?

      A:不可省,因为方法调用需要类名.方法,否则主方法不能被调 用,死锁。static可以直接调用。

    7. Q:static语句块或方法中能否使用superthis

      A:不能,super和this属于实例变量(非静态变量)

    8. Q:static方法的虚方法调用有什么特点?

      A:虚方法调用对静态方法无效

      ​ 多态情况下,方法调用以父类为准,因为在类加载前就加载

    9. Q:完整的对象构造次序?

      A:父类静态->子类静态->父类的非静态->父类的构造方法->子类的非静态->子类的构造方法(相同则按前后顺序)

    public class Student {//stu是属性
    	Student stu = new Student();//反复执行报错
    	//static Student stu = new Student();第一执行
    	//加static输出aaa aaa
    	public Student() {
    		System.out.println("aaa");
    	}
    	public static void main(String[] args) {
    		new Student();//匿名对象 第二执行
    	}
    }
    
public class Student {//父类
	public static void eat() {
		System.out.println("Eat");
	}
	public void play() {
		System.out.println("Play");
	}
}
class HaoStudent extends Student{//继承
	public static void eat() {
		System.out.println("HaoEat");
	}
	public void play() {
		System.out.println("HaoPlay");
	}
	public static void main(String[] args) {
		Student stu = new HaoStudent();//多态
		eat();//输出HaoEat		static方法可以直接调用,相当于本类对象调用HaoStudent.eat()
		//play();//非静态方法不能直接调用,必须对象.方法()
		stu.play();//输出HaoPlay	非静态方法调用虚方法,以子类为准
		stu.eat();//输出Eat	静态方法调用虚方法,以父类为准
		//Student.play();//非静态方法,类名不能直接调用,需要创建对象
		Student.eat();//输出Eat	static方法有,可以用类名(匿名对象)直接调用
		//HaoStudent.play();//非静态方法不能直接调用,必须对象.方法()
		HaoStudent.eat();//输出HaoEat		static方法有,可以用类名(匿名对象)直接调用
	}
}

OOP设计原则

OOP方法论(高内聚、低耦合、易复用)

  1. OCP开放封闭原则(开闭原则):

    软件实体应该对扩展开放,修改封闭

  2. DIP依赖倒置原则(Spring大量使用)

  3. LSP替换原则

  4. ISP接口隔离原则:(利用接口解耦)

  5. SRP单一职责原则:(类的职责单一)

  6. CARP合成/聚合复用原则:(对象委托优于类继承,Spring大量使用)

  7. LoD迪米特原则/最少知识原则


设计模式

模式就是套路,就是一种通用方法或手段。

一般在框架里用的很多,比如:Spring框架

23种设计模式
  • 《Java与模式》《Head First设计模式》

    菜鸟教程 https://www.runoob.com/design-pattern/design-pattern-tutorial.html

  • 创建型模式:

    工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

  • 结构型模式:

    适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

  • 行为型模式:

    策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

模板方法模式
  1. 为什么使用模板方法模式?模板方法模式是什么?

    • 设计一个系统时知道了算法(逻辑)所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还不能确定,此时可以使用该模式。
    • 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变改算法结构的情况下重定义该算法的某些特定步骤。
  2. 代码实现:

    • 写一个抽象类,这就是模板类,里面有具体明确的方法,不明确的抽象方法
    • 创建子类,子类重写那个抽象方法
  3. 特点:

    • 他封装了代码不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
    • 它在父类中提取了公共的部分代码,便于代码复用
    • 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则(对扩展开放,对修改关闭)。
  4. 什么时候用?

    例如:Spring中 JDBCTemplate

单例模式(重要)
  1. Q:解决什么问题?

    A:一个类只能创建一个对象。

  2. Q:什么时候用?

    A:只需要单一对象的时候。比如:帮助->单个窗口

  3. 两种实现方式

    • 饿汉式:单例模式类被加载的时候,单例对象就已经被创建。线程安全、效率较高。
    public class Person{
        //一、private static属性,当前类类型,立即初始化(显式赋值)
        private static Person person = new Person();
        //二、private构造方法私有
        private Person(){}
        //三、提供public static方法,返回当前类对象
        public static Person getPersonInstance(){
            return person;
        }
    }
    
    • 懒汉式(饱汉式):当程序第一次访问单例模式对象时才进行创建。非线程安全、效率较低。
    public class Student {
        private static Student student;//默认为空
        private Student(){}
        public static Student getStudentInstance(){
            if(student == null){
                student = new Student();
            }
            return student;
        }
    }
    
    • 二者区别:

      创建单例对象的时间点不同,饿汉式早,懒汉式晚。

      饿汉是属性上直接赋值;懒汉在方法调用的时候创建对象。

工厂模式
  1. Q:什么是工厂模式?

    A:向用户屏蔽创建对象的细节,直接取对象即可。比如:买手机,不需了解手机如何生产。

  2. Q:最终目的?

    A:创建者和调用者的分离。

  3. 分类

    1. 简单工厂模式

      在这里插入图片描述

    2. 工厂方法模式

      在这里插入图片描述

    3. 抽象工厂模式

面试题
  1. Q:请列举几个java设计模式。

    A:单例模式(手写)、工厂模式(手写)、适配器模式、装饰模式、模板方法模式、观察者模式、MVC模式。

    ​ 脱离IDE,建议先画UML类图,再写代码。

在这里插入图片描述

//Employee抽象类
public abstract class Employee {
	/**
	 * 模板方法
	 */
	public void gotoWork() {
		comeToCompany();
		work();//具体方法无法确定,不同的员工有不同的工作
		leaveCompany();
	}
	public void comeToCompany() {
		System.out.println("来到公司打卡……");
	}
	/**
	 * 抽象方法,具体不同员工不一样
	 */
	public abstract void work();//抽象方法
	
	public void leaveCompany() {
		System.out.println("下班打卡离开公司……");
	}
}
//Hr类
public class Hr extends Employee {
	public void work() {
		System.out.println("查看简历……通知面试……");
	}
}
//Developer类
public class Developer extends Employee {
	public void work() {
		System.out.println("写代码……改Bug……");
	}
}
//Test测试类
public class Test {
	public static void main(String[] args) {
		Hr hr = new Hr();
		hr.gotoWork();
		
		System.out.println("----------------------");
		
		Developer developer = new Developer();
		developer.gotoWork();
	}
}
//执行Test类,输出
/**
*
来到公司打卡……
查看简历……通知面试……
下班打卡离开公司……
----------------------
来到公司打卡……
写代码……改Bug……
下班打卡离开公司……
*/

Java SE——API应用

Java SE(Java应用)

什么是API?

API(Application Programming Interface)应用编程接口

  • 应用:软件
  • 编程接口:我们写的或第三方的类或接口(属性、方法)
API分类
  1. JDK自带
  2. 第三方的
  3. 我们公司提供的
微服务
  • 给我公开接口,我来调用。
  • 微服务:小型系统或功能
  • 例如:短信验证码、支付宝、微信支付
微服务相关技术

Spring Boot、Spring Cloud

教务系统:教务管理、学历验证、支付、短信验证码、学生身份户籍信息。

  • 教务管理:开发人员根据需求开发
  • 学历验证:调用【学信网】的接口
  • 支付:调用【微信支付】的接口
  • 短信验证码:调用【网易】的接口
  • 学生户籍验证:调用【公安户籍管理】的接口
String类使用

提示:String不是关键字。也不是Java的内置类型。

链式编程风格:name.trim().equalsIgnoreCase(“鸭梨亚”)

int String = 90;//正确

面试题
  • Q:列举几个常用的被final修饰的类

    A:String,Math,System,Integer等

String_API
  • String(char[] c)//字符数组->字符串;

  • String(byte[] bytes,String charsetName);

    //处理中文乱码,用到了String构造方法
    String newName = new String(name.getBytes("ISO-8859-1"),"UTF-8");
    
  • char [] toCharArray()//字符串->字符数组;

  • boolean endsWith(String str)//返回字符串最后一位;

  • int length();//获取字符串长度

  • boolean equals(String str);//区分大小写比较

  • boolean equalsIgnoreCase(String str);//忽略大小写比较字符串

  • String trim();//去除字符串首尾的空格

  • indexOf();//获取首次出现的位置

  • lastIndexOf();//获取最后出现的位置

  • substring(2,4);//截取[2,4)

  • substring(3);//取3到结束

  • substring(1,1);//得""空字符串

  • split();//字符串的分割,需要转义,正则表达式

  • StringTokenizer();//强力分割,字符串分隔解析类型,不需转义

  • replaceAll("regex", "replacement")//替换

  • replace(char,newchar)//替换字符

  • charAt(int index)//返回最后一个字符

StringBuilder类和StringBuffer类
String和StringBuffer、StringBuilder区别
  • String是不可变字符串类,内容不可变
//不可变字符串类,指的是字符串的内容不可变
String str = "china";
str.toUpperCase();//str是china,没有改变,因为有返回值
String str2 = str.toUpperCase();//str是CHINA
  • StringBuffer和StringBuilder是可变字符串,内容是可变的
    StringBuffer线程安全的,StringBuilder非线程安全
//可变字符串类,指的是字符串的内容可变
StringBuffer str1 = new StringBuffer("china");//API
//StringBuffer str2 = "tit"错误,不能直接建对象
str1.append(" shanxi taiyuan tit cs").append(" math");
//str1变成了china shanxi taiyuan tit cs math
//"a"+"b"+"c"就是StringBuffer.append()

StringBuilder stringBuilder = new StringBuilder(oldTelNum);//String类型包装成StringBuilder类型
return stringBuilder.toString();//转为String类型
Sysrem类
  • System.currentTimeMillis()获得系统时间长整型long毫秒ms,
    end-begin得到程序运行时间
  • System.arraycopy(first, 1, second, 2, 3);从数值first的位置1开始,替换数值second的位置2,共替换3个
  • System.gc()建议(不强制)执行垃圾回收器,并不立刻回收
    Runtime.getRuntime().gc()更高效
  • System.exit(code状态码)退出程序
    非零状态码是非正常退出,零正常退出
Math类
  • PIE属性
  • Math.abs()取绝对值
  • Math.sin()正弦,角度范围在 -pi/2 到 pi/2 之间,即-180度 到 180度
  • Math.asin()返回弧度值,pi是360度
  • Math.ceil()向上取整数
  • Math.floor()向下取整数
  • Math.round()四舍五入【面试题】
  • Math.random()[0,1)随机小数double【面试题】
  • (int)(Math.random()*1000)生成[0~1000)的随机整数
Random类
//生成0~1000的随机整数
import java.util.Random;
Random rd = new Random();
System.out.println(rd.nextInt(1000));
Date、Calendar类(java.util.*)

不建议用Date,用Calendar(日历)代替

在这里插入图片描述

//用Date获取当前时间
Date date = new Date();
return date.toLocaleString();
>>>返回 2020-5-22 14:03:44
//用Calendar获取当前时间
Calendar calendar = Calendar.getInstance();
//MONTH从0开始记,所以要+1
return ""+calendar.get(Calendar.YEAR)+"-"+(calendar.get(Calendar.MONDAY)+1)+"-"+ calendar.get(Calendar.DAY_OF_MONTH)+" "+calendar.get(Calendar.HOUR_OF_DAY)+				":"+calendar.get(Calendar.MINUTE)+":"+calendar.get(Calendar.SECOND);
>>>返回 2020-5-22 14:3:44

访问控制符(修饰符)

可以修饰属性、构造方法、一般方法。

不能修饰局部变量,外部类。

  • private
  • “默认”
  • protected
  • public

在这里插入图片描述


Object类(所有类的顶级父类)
.equals()——String字符串比较
字符串比较用  equals()方法
psw1.equals(psw2);    //psw1和psw2字符完全相同则返回true
username.equals("henry");	//区分大小写
  • Q: equals 和 == 的区别?

    A: == 两个对象的地址是否相同;比较两个简单类型值是否相同

    ​ equals 比较两个对象的内容是不是完全一样

.toString()——变成字符串
public String toString() {//需要重写
	return "name = "+ name +"  age ="+ age;
}
System.out.println("张三",22);//toString()会被自动调用
//extendsdemo.Students@1915376      //包名.类名@hashCode
//             ↓
//name = 张三  age =22

细节
一、“==”与equals的区别
  1. ==代表比较双方是否相同:
    基本数据类型表示值相等。
    引用数据类型表示地址相等,即同一个对象。
  2. Object中的equals()方法:是否为同一个对象的引用,即对象的hashCode是否相同。
  3. Object继承类中equals()方法:不仅判断是否是同一个对象,还要判断对象的属性值是否相同。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值