一、概述

1.1 内存

1Ghz = 1024Mhz = 1024^2Khz = 1024^3hz

1.1.2 DOS命令

dir md rd cd cd.. cd\ del cls exit
*echo javase>1.doc

Java之父:詹姆斯高斯林

1.2 特点

面向对象(三大特性:封装、继承、多态),健壮性,跨平台性(不同操作系统的JVM)

  • JDK:Java开发工具包,包含Java开发工具和JRE

  • JRE:java运行环境,包含JVM和JavaSE标准类库

1.3 编译

javac编译 java运行

二、基础语法

Windows不区分大小写,所以cmd运行java命令时对文件名大小写不严格区分

2.1 注释

单行://方便自己,方便别人
多行:/* */
文档注释:
/**
@author 作者名
@version v1.0版本
*/
文档注释调出方法javadoc -d 文件夹名 -author -version 类.java
//多行注释不可以嵌套使用

2.2 规范

一个源文件最多只能有一个可以声明为public类,且public类需与文件名相同

标识符identifier

  • 英文,数字,下划线,美元符号组成
  • //java使用Unicode字符集,可用汉字不建议使用

变量

  • 先声明后使用
  • //作用域:{代码块},同一定义域不允许重名变量声明

2.3 数据类型

2.3.1 基本数据类型

  • byte(1)
  • short(2)
  • int(4)
  • long(8)
  • float(4)
  • double(8)
  • char(2)
  • boolean(1)

2.3.2 引用数据类型

class interface []数组

2.3.3 数据类型规则

  • byte:8bit = 2^8 =-128~127

  • 整型常量默认int,long类型需要末尾增加’L’

  • 浮点型常量默认double,float类型需要末尾增加’F’

  • //float(4字节)表示数值要大于long(8字节)类型,字节存储内容不同

  • ‘\n’换行符 ‘\t’制表符 ‘\u0043’Unicode编码 "等于”

  • char类型必须存放一个字符

2.3.4 UTF-8编码

文件和控制台编码不同会导致乱码

2.3.5 类型转换

① 自动类型提升

byte,char,short->int->long->float->double
//容量大小指数的范围大小,当前三种变量做运算时结果为int型

② 强制类型转换

(低类型)高类型

2.3.6 进制转换

  • 0B二进制 十进制 0八进制 0X十六进制

  • 二进制内最高位0是正数1是负数

  • 反码:原码取反

  • 补码:反码+1

  • 正数:原码,反码,补码相同

  • 负数:原码符号位取1,反码为对原码除符号位外取反,补码+1

  • integer内toXXX有转换进制的方法

2.3.7运算符

算术

  • %取模结果符号与被取模数符号相同
  • %10取个位 /10%10取十位 /10/10%10取百位

位运算符

  • <<左移:每移动1位相当于*2
  • 右移:每移动1位相当于/2,最高位原来是啥就补啥
  • 无符号右移:最高位补0

使用位运算符进行交换数据:

num1 = num1 ^num2;
num2 = num1 ^num2;
num1 = num1 ^num2;

三元运算符
条件表达式?值1:值2;//统一值类型,三元可嵌套
运算符优先级:()小括号运算最优,编写时常用即可

2.4 程序流程控制

顺序,分支,循环
分支结构
if(boolean)-else
switch(byte,short,char,int,enum5.0,String7.0)-case-default-break
循环结构
for(初始化条件;循环条件;迭代条件){循环体}
while() || do…while()
嵌套循环:外层控制行,内层控制列
跳出结构
break continue //lable:标签,跳出语句后不可有语句

三、数组

  • 相同类型数据顺序排列并命名

  • 数组名 元素 下标|索引 长度

  • 特点:有序,引用类型,开辟的空间连续,长度确定后不可更改

  • 分类:一维数组,二维数组…

  • 声明:type[] arr = new type[]{…}静态 || new type[num]动态;

  • 长度:arr.length

  • 遍历:fori foreach lambda

  • 默认初始化值

  • 整型:0 浮点型:0.0 字符:\u0000(ASCII编码0) boolean:false

  • 引用类型:null

常见异常

  • NullPointerException
  • ArrayIndexOutOfBoundsException

二维数组时第一维放置地址值,第二维放置类型默认值,但声明new type[num][]时,一维数组内值为null,二维数组未初始化直接使用会进行报错提示

四、常见算法

杨辉三角
(a+b)^n
//n为杨辉三角中的行数,当n=2时,杨辉三角二行系数为121,即a^2+2ab+b^2
[i][0]以及[i][i]的所有元素赋值1
第三行开始j=1;j<length-1使用算法ij=[i-1][j-1]+[i-1][j]

二分查找
前提:有序
有一个头索引0和尾索引length-1
设置middle=(head+end)/2
if-elseif-else判断相等小于大于条件

排序算法
衡量算法:时间复杂度,空间复杂度,稳定性
十大内部排序算法:选择排序(直接选择排序,堆排序),交换排序(冒泡排序,快速排序),插入排序(直接插入排序,折半插入排序,希尔排序),归并排序,桶式排序,基数排序

算法特性
输入输出,有穷性,确定性,可行性

冒泡排序
外层循环0<length-1循环n-1次
内层循环0
<length-1-i比较长度次数
判断条件:i和i+1比较
快速排序,归并排序//非常牛逼的东西

五、内存结构

  • 栈stack(局部变量)
  • 堆heap[地址值0x0000](new的对象、数组)
  • 方法区methodArea(类的加载信息,常量池tring,静态域static)

new Heap堆:新生区,养老区,永久存储区(不在堆内,其实是方法区)

虽然JVM规范将方法区描述为堆的一个逻辑部分,但它还有一个别名叫做Non-Heap(非堆),目的就是和堆分开。

  • JDK1.6中字符串常量池被划分在方法区中(具体实现:永久代)

  • JDK1.7中字符串常量池被划分到堆中(具体实现:永久代)

  • JDK1.8中字符串常量池被重新划分在方法区中 (具体实现:元空间),元数据区取代了永久代,元空间的本质和永久代类似,都是对JVM规范中方法区的实现

三种JVM

  • SUN公司的HotSpot

  • BEA公司的JRockit

  • IBM公司的J9 VM

六、面向对象OOP

Java类及类成员:属性、方法、构造器、代码块、内部类
三大特征

  • 封装性
  • 继承性
  • 多态性[(抽象性)]
  • 其它关键字:this,super,static,final,abstract,interface,package,import

类Class抽象的概念上的定义
对象是实际存在的,也叫做实例instance

  • 属性=成员变量=filed=域、字段

  • 行为=成员方法=method=函数

  • 创建类的对象=类的实例化=实例化类

  • return:使用在方法中,可直接结束方法运行

匿名对象:直接使用new Class().method()来使用,只能调用一次

自定义工具类:Util结尾,私有化构造器,静态方法

6.1 细谈方法

方法重载overload

  • 同名方法,参数个数或参数类型或参数类型顺序不同

方法重写override

  • 子类同名方法,参数相同
  • 重写后权限修饰符不小于父类权限,private不能重写
  • 重写后返回值只能是父类返回类型或父类返回类型的子类型
  • 可变形参:Type … variable,形式为数组,0~n个形参可填写,只能声明在最后一个
  • 参数传值:基本数据类型传数据值,引用数据类型传地址值

调用方法时可以不接收返回值

6.2 递归recursion

递归加法,阶乘,裴波那契数列(Fibonacci),汉诺塔,快速排序

6.3 封装和隐藏

  • 高内聚,低耦合

  • private私有全局变量

  • 设置公共的getter和setter方法

  • 封装性的体现:单例模式

6.4 继承extends

  • 减少代码冗余,提高代码复用性,便于扩展,多态前提
  • 子类:派生类
  • 父类:超类,基类
  • 子类继承后会获取父类所有属性和方法
  • 因为封装性的影响,继承的private属性不可以直接调用父类private属性,通过gettersetter方法的继承调用
  • 单继承
  • 所有的类继承于java.lang.Object类

6.5多态

  • 一个事物的多种形态
  • 方法:编译看左,运行看右
  • 变量:没有多态
  • 使用instanceof判断是否是类实例进行向下转型

6.6 访问权限修饰符

类内部:private

  • 同一包下:private 缺省(友好类)
  • 不同包的子类:private 缺省(友好类) protected
  • 同一个工程:private 缺省(友好类) protected public
  • //修饰类的内部结构:属性,方法,构造器,内部类
  • //类Class权限:public 缺省

构造器constructor

  • 默认含有无参构造器,创建有参构造器后默认无参构造器消失
  • 多个构造器共存组成重载

6.7 JavaBean

  • 公共类

  • 有无参公共构造器

  • 有属性且对应gettersetter方法

6.8 包装类

八种基本类型的引用类型

  • Type type = new Type(type variable)
  • 自动装箱:包装类 var = 基本类型数据
  • 自动拆箱:基本类型 var = 包装类对象
  • 包装类–>String:String.valueOf(包装类)
  • String–>包装类:Type.parseType(String)

Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],保存了-128127范围的整数,使用自动装箱时,给Integer赋值的范围在-128127范围中时,直接使用数组中的元素,不再new对象,目的是为了提高效率

-----------------------------------------------
UML图
-----------------------------------------------
Class
-----------------------------------------------
variable:type
-----------------------------------------------
method(variable:type):return type
-----------------------------------------------

6.9 this关键字

  • this.方法或属性,调用当前对象属性或方法

  • 通常情况省略不写

  • this()构造器嵌套

6.10 super关键字

super() super.variable super.method()
类构造器中this()或super()构造器只能二选一,不能同时出现

6.11 package import关键字

import static:导入指定包内静态结构,落脚点是类中的结构(属性或方法)
//import static java.lang.System.*

6.12 final关键字

  • 修饰:类、方法、变量

  • final类:不可被继承,与abstract相驳

  • final方法:不可被重写

  • final变量:此时”变量”被称为一个常量,全部常量声明为public static final CONSTANT;//需要进行数值初始化

  • final修饰形参时方法内只能调用不能重新赋值

6.13 static关键字

  • 数据在内存空间内只有一份

  • 可以修饰:属性、方法、代码块、内部类

  • 静态变量|类变量:内存内只有一个共享的静态变量,存在于方法区的静态域中。

  • 静态方法|类方法:随着类的加载而加载

    • //静态方法中只能调用静态的方法或属性,非静态方法中,既可以调用非静态方法或属性,也可以调用静态的方法或属性。常用于工具类的创建使用
  • 静态代码块:加载类时执行

6.14 代码块{}

  • 修饰:不写,static

  • 代码块执行优先级:static{}>{}>constructor()

  • 所有的父类到本类静态代码块执行完毕后执行所有的父类到本类非静态代码块,最后执行父类到本类的构造器

  • 代码块内可以写输出语句

  • {}非静态代码块:随着创建对象时执行

    • //初始化类的信息
  • static{}静态代码块:随着类的加载而执行

    • //初始化对象的属性
  • 静态代码块只能调用静态的属性或方法

  • 非静态代码块可以调用任何属性和方法

类内属性赋值优先级:默认初始化(int a)>显式初始化(int a=1;)==代码块({a = 2;})>构造器初始化>对象.属性

6.15 MVC设计模式

  • model数据模型层

  • view视图模型层

  • controller控制器层

6.16 abstract(抽象)

  • 可以用来修饰的结构:类、方法

  • 类:添加修饰符abstract

    • //不能实例化
  • 方法:增加修饰符abstract,删除方法体

    • //public abstract void method();
    • //抽象类中可以没有抽象方法
    • //不能用来修饰私有方法、静态方法、final声明的方法
    • //与平常类相似,增加了可以不写方法体的方法,子类需要重写实现抽象方法才可以写成普通类
    • //抽象类实现自己时对构造器添加方法体进行重写方法,相当于是创建了一个匿名类对象

6.17 interface(接口)

  • 可以实现多重继承,即多实现implements

  • 让一个类或接口具备多个功能,实现了多态性

  • 全局常量:public static final

  • 抽象方法:public abstract

    • //声明默认可省略
  • jdk7及以前:只能定义全局常量和抽象方法

  • jdk8:可以定义静态方法static、默认方法default

  • jdk9及以后:可以定义私有方法private

    • //接口体现就是定义了一种规范,在一个接口内声明必须实现的方法
    • //接口中定义的静态方法只能通过接口调用
    • //如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中同名同参数的方法–>类优先原则
    • //类实现了多个接口,多个类中定义了同名同参数的默认方法,实现类在没有重写此方法的情况下会报错。–>接口冲突
    • //直接调用接口中的默认方法:Interface.super.defaultMethod();

6.18 内部类

分类:成员内部类、局部内部类(方法内,代码块内,构造器内)
成员内部类

  • 修饰符:缺省,static静态
  • 可以被final,abstract修饰
  • 成员内部类调用外部类的非静态属性:[Class.this.]method();

成员内部类的创建

  • 静态内部类:Class.inner in = new Class.inner();
  • 非静态内部类:Class.inner in = new Class().inner();

6.19 枚举类enum

jdk5前

public static final enumClass = new EnumClass();
  • jdk5.0出现enum关键字定义枚举类

  • 使用:定义一组常量时,使用枚举类

  • 枚举类的定义:有限的,确定的类对象

    • 如果枚举类中只有一个对象,则可以作为单例模式的实现方式

定义枚举类

  • 定义时:对象之间用’,’分隔,结尾用’;’结束

  • 不重写toString方法时,sout输出为枚举对象名

//自定义枚举类
Class Season{
//定义枚举类对象的属性
private final Stirng seasonName;
private final String seasonDesc;
//给枚举对象赋值
Seanson(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonName;
}
//枚举类的对象
public static final Season SPRING = new Season("春天","春暖花开");
public static final Season SUMMER = new Season("夏天","夏日炎炎");
......
//提供get方法
public String getSeasonName(){
return seasonName;
}
public String getSeasonDesc(){
return seasonDesc;
}
//重写toString()
...
}

//enum定义枚举类
enum Season{
//对象提到最前方,对象之间用','分隔,结尾用';'结束
PRING("春天","春暖花开"),SUMMER("夏天","夏日炎炎")[,...];
//定义枚举类对象的属性
private final Stirng seasonName;
private final String seasonDesc;
//提供get方法
public String getSeasonName(){
return seasonName;
}
public String getSeasonDesc(){
return seasonDesc;
}
//重写toString()
...
}

常用方法

  • Enum[] values()

    • 返回枚举类的对象(常量)数组
  • Enum valueOf(String str)

    • 根据str名找到枚举类的对象名,并返回枚举对象
  • toString()

    • 不重写toString方法时输出枚举对象名
  • 枚举可实现interface接口

    • 方法一:与普通类相同,在enum类中实现抽象方法

    • 方法二:在枚举类定义时分别实现接口中的抽象方法

interface Info{
void show();
}
//enum定义枚举类
enum Season implements Info{
//对象提到最前方,对象之间用','分隔,结尾用';'结束
SPRING("春天","春暖花开"){
@Override
public void show(){
System.out.println("春天....");
}
},SUMMER("夏天","夏日炎炎"){
@Override
public void show(){
System.out.println("春天....");
}
}[,...];
//定义枚举类对象的属性
private final Stirng seasonName;
private final String seasonDesc;
//提供get方法
public String getSeasonName(){
return seasonName;
}
public String getSeasonDesc(){
return seasonDesc;
}
}

调用Switch

//声明对象时用Enum.枚举对象,调switch时直接使用枚举对象

enum Status{
FREE,BUSY,VOCATION;
}
psvm{
Status status = Status.FREE;
switch(status){
case FREE:...
case BUSY:...
case VOCATION:...
default
}
}

七、JUnit4

  • 1.写Test类
  • 2.类内写普通方法
  • 3.方法上添加@Test注解
    • 没异常绿,有异常红

@Test

  • 调用测试方法前后使用:

  • 实例方法:@Before @After

  • 静态方法:@BeforeClass @AfterClass

八、Annotation注解

JDK5.0新增

代码里面的特殊标记,可以在编译,类加载,运行时被读取,并执行相应的处理

实用:配置切面,代替xml配置

框架=注解+反射+设计模式

8.1 常用Annotation

8.1.1 文档相关

  • @author标明开发该模块作者,多个作者之间使用’,’分隔

  • @version标明该模块的版本

  • @since哪个版本开始

  • @param方法参数说明

  • @return方法返回值说明

  • @exception方法抛出异常说明

8.1.2 编译时格式检查

  • @Override重写:限定重写父类方法

  • @deprecated弃用:标识所修饰元素(类、方法等)已过时

  • @SuppressWarings抑制警告:抑制警告编译器

8.1.3 注解的使用

  • 无参数

  • 单参数(“”)

  • 多参数({“”,””})

//未使用的变量上添加SuppressWarings注解
@SuppressWarings("unused")
int num = 1;

8.1.4 自定义注解

  • 注解声明为:@interface

  • 内部定义成员,通常使用value标识

  • 都会指定两个元注解:Retention、Target

  • 可以指定成员的默认值,使用default定义

  • 如果自定义注解没有成员,表明是一个标识作用

//定义
public @interface MyAnnotation{
//当定义default属性时,注解使用可忽略属性赋值@MyAnnotation直接调用
String value() default "person";
//String[] value();
}
//使用注解
@MyAnnotation(value = "person")
class Person{}

8.1.5 元注解

元Annotation用于修饰其他Annotation定义

JDK5.0提供了四个标准类型

  • (1)Retention:指定生命周期

    • //生命周期:SOURCE CLASS RUNTIME

    • //@Retention(RetentionPolicy.SOURCE)

    • //只有被声明为RUNTIME生命周期的注解才能通过反射获取

  • (2)Target:指定被修饰Annotation能用于修饰哪些程序元素

    • //@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
  • (3)Dcoumented:被修饰的Annotation类将被javadoc提取成文档

  • (4)Inherited:被修饰的Annotation将具有继承性,如果某个类使用了该注解,继承的子类自动具有该注解

    • 元数据理解:String name = “bamboo”

    • //最重要的是”bamboo”,String name对现有数据进行修饰,String name就是元注解

8.1.6 反射获取注解

@Test
method(){
Class clazz = Class.class;
Annotation[] annotations = clazz.getAnnotation();
}

8.1.7 JDK8新增可重复注解,类型注解

@Repeatable(Annotation.class)

九、设计模式

代码结构,编程风格以及解决问题的思考方式

9.1 单例模式(singleton)

采取一定方式保证在整个系统中对某个类只有一个对象实例

9.1.1 饿汉模式

  1. 私有化构造器

  2. 私有化一个instance的static对象并进行new分配内存//private Class instance = new Class();

  3. 公共静态方法getInstance()返回类对象,return instance;

9.1.2 懒汉模式(延迟构造)

//线程不安全,方法增加synchronized称为安全线程

  1. 私有化构造器
  2. 私有化一个instance的static对象,不进行new分配内存//private Class instance = null;
  3. 公共静态方法getInstance()返回类对象,return instance;//其中增加判断
if(instance == null){
instance = new Class();
}

线程安全的懒汉

private Class(){}
private static Class instance = null;
public static synchronized Class getInstance(){
//此时锁是Class.class,此时为静态同步方法的锁
if(instance == null){
//会出现线程阻塞的地方
instance = new Class();
}
return instance;
}
//或是
private Class(){}
private static Class instance = null;
public static Class getInstance(){
synchronized(Class.class){
if(instance == null){
//会出现线程阻塞的地方
instance = new Class();
}
}
return instance;
}

9.2 模板方法模式(TemplateMethod)

实现某一算法时,步骤很固定通用,父类已经写好的,但某部分易变,易变部分可以抽象出来,供不同的子类实现
固定通用部分方法:

//final修饰
public final void methodName(){
......
inconstancy();//钩子方法,回调方法
......
}

抽象出来的易变部分:

//abstract修饰
public abstract void inconstancy();

9.3 代理模式(Proxy)

9.4 工厂设计模式(Factory)

创建者和调用者分离
]

main方法[
main内可以对args进行分配内存//args=new String[num];
或是通过外部Class.main调用静态main方法进行放入String类型的数组进行使用。
run Configuration中设置args变量,使用空格分割
或是控制台java Class “test1” “test2”
]

十、classpath说明

编译前文件路径寻找

  • 类.class.getResource(“”).getPath()
  • 对象.getClass().getResource(“”).getPath()

编译后class文件路径寻找:

  • 类.class.getClassLoader().getResource(“”).getPath()
  • 对象.getClass().getClassLoader().getResource(“”).getPath()

十一、异常处理Exception

异常Throwable事件分两类:Error,Exception

11.1 Error

JVM都无法解决的严重问题,JVM内部错误,资源耗尽等严重情况。

OutOfMemoryError堆溢出

11.2 Exception

运行时java异常

11.2.1 RuntimeException

运行时异常:非受检异常,直接编译略过

常见异常

  • NullPointerException

  • ArrayIndexOutOfBoundsException

  • ClassCastException

  • NumberFormatException

  • InputMismatchException

  • ArithmeticException

11.2.2 编译时javac异常

受检异常,进行异常捕获,最理想是在编译期间捕获

常见异常

  • IOException

  • FileNotFoundException

  • ClassNotFoundException

11.2.3 异常处理

  • (1) try-catch-finally

  • (2) throws Exception

    • 方法内使用(2)进行抛出异常,main方法中使用(1)进行捕获异常

    • catch内抛出调用方法

    • getMessage()

    • e.printStackTrace() //常用

11.2.4 finally

  • 关键字可选

  • finally声明是一定会被执行的

  • finally一定会执行,如果其中有return语句,则先执行finally后执行return语句,finally{return;}

11.2.5 throws

  • 用法:throws 异常类

  • 子类继承父类的throws异常类,只能是父类的异常子类,父类如果没有抛出异常,子类也不能抛出异常

11.2.6 throw

  • 方法内throw new 异常类Exception(“message”)//手动抛出异常,使用throws抛出至上级

11.2.7 自定义异常

继承Exception或RuntimeException

定义一个static final long serialVersionUID

定义有参,无参构造器,有参构造器内super(message)

//1.创建自定义异常
public class NumericalFaultException extends Exception {
static final long serialVersionUID = -1111111111111112111L;
public NumericalFaultException() {
}
public NumericalFaultException(String message) {
super(message);
}
}
//2.将异常用被检测方法中抛出并填写参数内提示信息
public void setAge(int age)
throws NumericalFaultException {
if (age > 120 || age < 0)
throw new NumericalFaultException("年龄输入错误。");
this.age = age;
}
//3.调用方法时捕获异常
try{
stu.setAge(-20);
} catch (NumericalFaultException e) {
e.printStackTrace();
//System.out.println(e.getMessage());
}

十二、多线程

  • 线程创建方式:四种

  • 线程同步方式:三种

12.1 概念

  • 程序program:一段静态的代码

  • 进程process:程序的一次执行过程,正在运行的一个程序

  • 线程thread:进程进一步细化为线程,一个程序内部的一条执行路径

  • 并发:一个CPU同时执行多个任务

  • 并行:多个CPU同时执行多个任务

12.2 线程的分类

1.守护线程:服务用户线程,可以通过在start()方法前调用thread.setDaemon(true)将用户线程变成守护线程,例如java垃圾回收,若JVM中都是守护线程,则当前JVM将退出

2.用户线程

12.3 Thread

12.3.1 常用方法

  • start():启动当前线程,调用当前线程的run()

  • run():重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中

  • currentThread():静态方法,返回执行当前代码的线程//Thread.currentThread()

  • getName():获取当前线程的名字//Thread.currentThread().getName()或thread().getName()

  • setName():设置当前线程的名字//thread.setName()

  • yield():线程类内调用,释放当前线程CPU的执行,供给其他线程使用,可能即刻此线程被调用//this.yield();‘this’可省略

  • join():线程对象调用,将其他线程直接加入当前线程中执行//a线程中调用线程b的join(),此时a线程进入阻塞状态,直到b线程执行完毕,才会执行a线程

  • stop():强制结束线程,不被建议使用,过时

  • sleep(long millitime):休眠指定毫秒值,即当前时间内是阻塞状态

  • isAlive():判断当前线程是否存活

  • 线程通信:wait() notify() notifyAll()

12.3.2 构造器

new Thread子类(“Name”)给当前线程起名

12.4 线程优先级

  • MAX_PRIORITY:10

  • MIN_PRIORITY:1

  • NORM_PRIORITY:5 //默认优先级

  • 获取和设置线程的优先级:

  • getPriority()

  • setPriority(int p)

高优先级高概率被CPU执行,不是一定被CPU先执行

12.5 线程的创建与使用

12.5.1 方式一

  1. 继承Thread类

  2. 重写Thread类的run()

  3. 创建Thread子类的对象

  4. 调用对象.start()执行线程

//调用run()方法执行在主线程中,不是多线程

//start()启动线程方法只能调用一次,否则会报IllegalThreadStateException异常

12.5.2 方式二

  1. 实现Runnable接口

  2. 重写Runnable接口的run()方法

  3. 创建Runnable接口实现类的对象

  4. 将Runnable接口实现类对象添加进Thread的参数中创建对象

    • //new Thread(Runnable run);

    • //new Thread(Runnable run,String threadName);

  5. 调用start()方法

    • //此方式会只制造 一个Runnable对象的run所以后续Thread调用Runnable实现的run公用的是同一个地址,所以内部值唯一地址,无需使用static进行声明

    • //Runnable天然实现了一种共享数据的情况

    • //联系:Thread类实现了Runnable方法

方式三、四(JDK5.0)

12.5.3 方式三

① Callable接口

  • 支持泛型:当Callable指定泛型时,FutureTask也要指定泛型,否则调用get()方法需要进行强转

  • 实现Callable接口,重写call()方法

  • 可以有返回值,可以抛出异常,支持泛型返回值

  • //抛出的异常调用get()时捕获

  • 需要借助FutureTask类

② Future接口

  • 可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。

  • FutureTask同时实现了Runnable,Future接口。既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值

③ 实现线程

  • (1)创建线程类实现Callable接口,重写call()方法

    • //不需要返回值则return null;
  • (2)创建FutureTask对象,参数填写Callable实现类

  • (3)创建Thread对象,参数填写FutureTask对象

new Thread(futureTask).start();
  • (4)使用FutureTask对象的get()方法接收返回值

12.6 线程池

相关API:ExecutorService和Executors

12.6.1 ExecutorService

线程池接口,常见子类ThreadPoolExecutor

void execute(Runnable command)执行任务,无返回值,一般用于执行Runnable

<T> Future<T> submit(Callable<T> task)执行任务,有返回值,一般用于执行Callable

void shutdown()关闭连接池

12.6.2 Executors

工具类,线程池的工厂类,用于创建并返回不同类型的线程池

  • Executors.newCachedThreadPool()创建可根据需要创建新线程的线程池

  • Executors.newFixedThreadPool(n)创建可重用固定线程数的线程池

  • Executors.newSingleThreadExecutor()创建只有一个线程的线程池

  • Executors.newSchedulThreadPool(n)创建一个可以安排在给定延迟后运行命令或定期执行的线程池

① 线程管理

  • corePoolSize核心线程池的大小

  • maximumPoolSize最大线程数

  • keepAlivetime线程没有任务时最多保持多长时间后悔结束

② 实现

ExecutorService service = Executors.newFixedThreadPool(num);
//可选择将线程接口ExecutorService强转为线程池实现类
ThreadPoolExecutor service1 = (ThreadPoolExecutor)service;
//线程池实现类设置线程池属性
service1.setXXX();
service.execute(new Runnable());
service.execute(new Runnable());
service.submit(new Callable());
service.shutdown();

12.7 线程的生命周期

  • 新建(new Thread)

  • ->就绪(thread.start())

  • ->运行(获取CPU的执行权后执行内部的run(),失去CPU执行权或调用yield()后返回就绪)

  • ->阻塞(调用sleep()或wait()或join()或等待同步锁或suspend()执行后回到就绪阶段)

    • //等待同步锁使用获取同步锁进入就绪

    • //wait()等待后用notify()/notifyAll()进行唤醒进入就绪

    • //suspned()挂起,已被弃用,resume()结束挂起进入就绪

  • ->死亡(调用stop()或线程执行run()方法结束或出现异常并未处理)

12.8 线程的同步

线程安全:多线程对某个数据的共享,会造成操作的不完整性,导致破怀数据。Java中通过同步机制来解决线程安全问题。

12.8.1 同步代码块

synchronized(同步监视器){//常使用this为同步监视器
//需要被同步的代码
}

① 说明

操作共享的数据的代码,即为需要被同步的代码

② 同步监视器

  • 俗称锁,任何一个类的对象都可以被充当锁

  • 锁要求:多个线程必须要共用同一把锁,才能实现同步监视器的实现。

③ 同步监视器的创建

  • 可以使用单例singleton创建对象来给予锁

  • *实现Runnable接口的类的线程安全,使用this来作为同步监视器

  • *继承Thread类的线程安全,同步监视器可以用Class.class来代替,类class也是对象,!慎用this充当同步监视器

12.8.2 同步方法

如果操作共享数据的代码完整的声明在一个方法中,将使用此方法声明同步

//Runnable同步方法
private synchronized Type methodType(){
//内部填写需要被同步的代码
//Runnable同步监视器:this
}
//Thread同步方法
private static synchronized Type methodType(){
//synchronized同步static方法
//内部填写需要被同步的代码
//内部调用getName()需要用Thread.currentThread()来进行静态调用
//Thread同步监视器:Class.class[这是一个对象]
}
public void run(){
methodType();
}

//操作代码时,只能有一个线程参与,其他线程等待。效率低下

  • 实例的同步方法:同步监视器为this

  • 静态的同步方法:同步监视器为当前类的class

12.9 死锁

不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁

死锁只会阻塞,不会抛异常

12.9.1 死锁演示

//死锁演示
pvsm{
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
//死锁1
new Thread(){
@Override
public void run(){
synchronized(s1){
s1.append("a");
s2.append("b");
synchronized(s2){
s1.append("1");
s2.append("2");
}
}
}
}.start();
//死锁2
new Thread(new Runnable(){
@Override
public void run(){
synchronized(s2){
s1.append("c");
s2.append("d");
synchronized(s1){
s1.append("3");
s2.append("4");
}
}
}
}).start();
//此方法调用后如果进入顺序为:死锁1进入s1同步锁,死锁2进入s2同步锁,死锁1等待死锁2的s2同步锁放行进入s2同步锁,死锁2等待死锁1的s1同步锁放行进入s1同步锁,此时双方都有线程阻塞,下一个同步锁被占用,导致程序无法正常执行,陷入阻塞状态无法结束运行。
//如果想要此程序死锁出现的概率提高,添加sleep(long)方法即可
}

使用同步时,要避免死锁,不要同步来回调

12.9.2 解决方法

  • 专门的算法、原则

  • 减少同步资源的定义

  • 避免嵌套同步

12.10 Lock(锁)

  • JDK5.0提供的线程同步机制,显示定义同步锁对象来实现同步

  • java.util.concurrent.locks.Lock接口

  • 典型实现类ReentrantLock(可重入锁)

//两种锁的应用
private ReentrantLock lock =
new ReentrantLock();
//Runnable使用锁
private static ReentrantLock lock =
new ReentrantLock();
//Thread使用静态锁
//在线程类中添加Lock锁
private ReentrantLock lock =
new ReentrantLock();

@Override
public void run(){
try{
//锁住线程
lock.lock();
//code or method
}finally{
//解锁线程
lock.unlock();
}
}

12.11 synchronized与Lock

  • 相同点:都可解决线程安全问题

  • 不同点:synchronized机制在执行完相应的同步代码后自动释放同步监视器。Lock需要手动的启动同步,同时手动的结束同步

推荐:Lock > 同步代码块 > 同步方法

12.12 sleep与wait

  • 相同点

    • 一旦执行,都能使当前线程进入阻塞状态
  • 不同点

    • (1)声明位置不同,Thread.sleep(),Object.wait()

    • (2)使用方法不同,sleep()可以在任意场景调用,wait()必须使用在同步代码块或同步方法时调用。

    • (3)sleep()阻塞不释放同步监视器,wait()阻塞且释放同步监视器

12.13 线程通信

  • wait():执行方法后,当前线程进入阻塞状态,并释放同步监视器

  • notify():执行方法后,唤醒被wait的一个线程,如果有多个线程被wait,就会唤醒优先级高的线程

  • notifyAll():执行方法后,唤醒所有被wait的线程

  • //此三项方法只能使用在同步代码块或同步方法中。

  • //此三项方法调用者只能是同步代码块或同步方法中的同步监视器,否则会出现异常

  • //此三项方法被定义在Object类中

@Override
public void run() {
while (true) {
synchronized (this) {
notify();//唤醒锁
if (number <= 100) {
System.out.println(Thread.currentThread().getName()+":"+number);
number++;
try {
wait();//不仅会阻塞,还会释放锁,使下一线程可以进入此安全锁
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

}else {
break;
}
}
}
}

十三、API(常用类)

13.1 Scanner

java.util.Scanner;
Scanner sc = new Scanner(System.in);
if(sc.hashNextXXX()){
sc.nextXXX();
}

13.2 String

  • 不可变的字符序列,是一个final类,不可被继承

  • 字符串是常量,值在创建后不能更改

  • String实现了Serialzable接口,表示字符串支持序列化

  • String实现了Comparable接口,表示可以比较大小

  • String对象的字符内容是存储在一个字符数组value[]中的,内部定义了final char[] value用于存储字符串数据

  • String不可变的字符序列。//任何操作都不可变

  • //使用字符串直接赋值后,使用”==”进行比较会返回ture

13.2.1 两种赋值方式

  1. String str = “string”;

    • //此方式数据声明在方法区中的字符串常量池中

    • //此方法内容相同时”==”比较为TRUE

  2. String str = new String(“string”);

    • //此方法声明的数据保存的是地址值,数据在堆空间开辟空间后 的地址值

    • //此方法内容相同但构造器分别声明时”==”为FALSE,原因是保存的地址值

13.2.2 new String()

new String(“str”)创建了两个对象

  • (1)堆空间中的new结构

  • (2)char[]对应的常量池中的数据”str”

//常量与常量的拼接结果在常量池。且常量池不会存在相同内容的常量

//只要其中一个是变量(String类型,不论是不是newString赋值),结果就都保存在堆中

//如果有声明final的String字符串,则此String类型为常量,修改后仍为常量(常量保存在字符串常量池中),与常量池中数据对比为ture

//如果拼接的结果调用intern()方法,返回值就在常量池中

13.2.3 字符串常量池

  • 在方法区中存在字符串常量池

  • 使用””赋值的数据都在字符串常量池中

  • 在对值有所改变时(重新赋值时),每次都会在字符串常量池中创建新的字符串地址,无法在原有位置对String类型赋值

  • 当对现有字符串进行”+=”连接字符串时,也会在字符串常量池中重新创建新的字符串地址

13.2.4 值传递

String str = new String("good");
public void change(String str){
str="test ok";
}
psvm{
change(str);
sout(str);
//此时str为good,因值传递(此项值为地址)进入方法后,方法形参地址发生改变至字符串常量池,所以并未改变原有str变量地址的值,String不可变型
}

13.2.5 常用方法

  • int length()

  • char charAt(int index)

  • boolean isEmpty()

  • String toLowerCase()

  • String toUpperCase()

  • String trim()忽略前后空白

  • boolean equals(Object obj)

  • boolean equalsIgnoreCase(String anotherString)

  • String concat(String str)等同于使用”+”连接符

  • int compareTo(String anotherString)

  • String substring(int beginIndex)

  • String subsring(int beginIndex,int endIndex)

  • boolean endWith(String suffix)

  • boolean startsWith(string prefix)

  • boolean startsWith(string prefix,int toffset)指定索引开始的子字符串是否包含此字符

  • boolean contains(CharSequence s)

  • int indexOf(String str) //不存在返回-1

  • int lastIndexOf(String str) //不存在返回-1

  • String replace(CharSequence target,CharSequence replacement)

  • replaceAll(String regex,String replacement)

  • boolean matches(String regex)判断是否匹配正则

  • String[] split(regex)分割字符串:切片

  • char[] toCharArray()

  • byte[] getBytes(“UTF-8”)//编码

  • new String(byte[] ,”UTF-8”)//解码

  • Type Type.parseType(String)

  • String.valueOf(Type type)

13.3 StringBuffer StringBuilder

13.3.1 StringBuffer可变字符序列

线程安全,效率低

//空参构造器制造16长度的char[]

//扩容时扩容为原来容量的2倍数+2,同时将原有数据中的元素复制到新的数组中

建议使用构造器new StringBuffer(int capacity)初始化容量

13.3.2 StringBuilder可变字符序列

JDK5.0

可变字符序列

未同步线程synchronized,效率高

建议使用构造器new StringBuilder(int capacity)初始化容量

13.3.3 常用方法

  • append(XXX) //方法链

  • delete(int start,int end)

  • replace(int start,int end,String str)指定范围内数据替换为str

  • insert(int offset,XXX)

  • reverse()

  • int indexOf(String str)

  • String substring(int start,int end)

  • int Length()

  • char charAt(int index)

  • setCharAt(int n,char ch)

13.4 Math

Math.sqrt()

Math.abs()绝对值

Math.round(double)四舍五入转为Long型

Math.random()

//[0~1) return double
//公式:[a,b]:(int)(Math.random()*(b-a+1)+a)

13.5 BigInteger和BigDecimal

不变的任意精度(光年也可,超过Long长度)的整数或浮点数

构造器

BigInteger(String val) 通用

方法

  • abs() //返回绝对值的BigInteger

  • add(BigInteger val)

  • subtract(BigInteger val)

  • multiply(BigInteger val)

  • divide(BigInteger val)

//注:参数后指定精度(int),写静态常量,指定返回的形态,例:BigDecimal.ROUND_HALF_UP

pow(int exponent)返回幂次 //只有整数可以是哟会给你

13.6 Random

int nextInt(num)

13.7 Arrays

boolean eqlaus(int[] a,int[] b)
String toString(int[] a)
void fill(int[] a,int value)将指定值填充到数组中,全部替换
void sort(int[] a)
binarySearch(int[] a ,int key)对排序后的数组进行二分法检索指定的值

List asList(arr[])

13.8 System

System.exit(0)
System.currentTimeMillis()
流输出到控制台new PrintStream(System.out)

13.9 TIME

13.9.1 System

  • System.currentTimeMillis()适用于做时间差

  • System.exit(int status)可以在图形化界面直接退出

  • System.gc()垃圾回收器

  • getProperty(String key)获取系统参数

13.9.2 Date

构造器

  • new Date()
  • new Date(long date)

方法

  • toString()类中已经重写方法

  • getTime()返回当前Date对象的毫秒数(时间戳)

两个Date类

  • java.util.Date

  • java.sql.Date //操作数据库时使用

13.9.3 SimpleDateFormat

操作:格式化为字符串,解析为日期

使用带参构造器:

new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”)

方法:

String format(Date date) //格式化为字符串

Date parse(String date) //解析为Date,字符串格式””

13.9.4 Calendar日历类

创建对象:Calendar.getInstance()

静态属性:调用Calendar.XXX

方法:调用静态属性进行使用

  • get(静态属性)

  • set(静态属性,value)

  • add(静态属性,value)

  • getTime()

  • setTime()

13.9.5 JDK8前面临的问题

  • 可变性:日期时间的类应该是不可变的

  • 偏移量:Date中年份是从1900年开始,月份是从0开始的

  • 格式化:格式化只对Date有用,Calendar无用

  • 线程不安全,也不能处理更小的时间单位

13.9.6 LocalDate LocalTime LocalDateTime

不可变性,修改后返回新对象,保留原始数值

实例化:Class.now() Class.of(year,month,day[,…])

方法:

  • getXXX() //获取

  • withXXX() //设置

  • plusXXX() //添加某值

  • minusXXX() //减去某值

13.9.7 Instant 瞬时

用于获取时间戳,精确到纳秒级

创建对象:

  • Instant.now()

方法:

  • instant.atOffset(ZoneOffset.ofHours(8)) //调用方法设置在东八区(中国时区)

  • long instant.toEpochMilli() //获取毫秒数

13.9.8 DateTimeFormatter

格式化或解析日期、时间

创建对象:

  • (1) 默认格式DateTimeFormatter.ISO_LOCAL_DATE_TIME

  • (2) 固定格式DateTimeFormatter.ofLocalizedDateTime(FormatStyle.XXX)

  • (3) 自定义格式DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”)

方法:

  • String format(LocalDateTime) //参数为jdk8新增的三个日期时间类

  • TemporalAccessor parse(String date) //解析为日期

13.10 Object

equals() hashCode() toString() clone() finalize() wait() notify() notifyAll() getClass()

x.equals(null)==>return null
null.equals(x)==>NullPointerException
"=="符号使用时必须保证两边类型一致
"a"=="a"==>true
new String("a")==new String("a")==>false

13.11 比较器

Double.compare(obj1,obj2);

13.11.1 Comparable接口(自然排序)

实现此接口的对象的列表(和数组)可以由Collections.sort和Arrays.sort自动排序

重写compareTo(obj)

  • 如果当前对象this大于形参对象obj,则返回正整数

  • 如果当前对象this小于形参对象obj,则返回负整数

  • 如果当前对象this等于形参对象obj,则返回零

//在compareTo(obj)中进行自然排序
@Override
public int compareTo(Object o){
if(o instanceof Class){
Class class = (Class)o;
//默认升序
if(this.XXX > class.XXX){
return 1;
}else if(this.XXX < class.XXX){
return -1;
}else{
return 0;
}
}
}

13.11.2 Comparator接口(定制排序)

可以将接口多态写出来进行使用

Comparator com = new Comparator(){
@Override
public int compare(Object o1,Object o2){
//.....
}
}
Arrays.sort(arr,com);

重写compare(Object o1,Object o2)方法

返回正整数表示o1大于o2

返回0表示相等

返回负整数表示o1小于o2

使用:Arrays.sort(arr , Comparator comparator)

@Override
public int compare(Object o1,Object o2){
if(o1 instanceof Class && o2 instanceof Class){
Class c1 = (Class)o1;
Class c2 = (Class)o2;
return c1.compareTo(c2);
//如果需要降序排序,则在return上添加'-'号进行颠倒
}
throw new RuntimeException(String message);
}

13.11.3 对比

Comparable接口一旦实现则固定,Comparator接口属于临时性的比较。

13.11.4 比较器实现

实现对自定义排序的数据进行排序

//创建数组类
public class Student implements Comparable<Student>
//数组类内创建不可变List集合存储数据
private static final List<String> COMPARE_STR =
Arrays.asList("integer", "long", "float", "double", "index", "insert", "update", "select", "delete");
//重写compareTo方法
@Override
public int compareTo(Student o) {
//使用List数组的方法indexOf确认索引下标,进行相减操作
return -(COMPARE_STR.indexOf(this.getName())-COMPARE_STR.indexOf(o.getName()));
//默认升序排序,如将结果取负,则为降序排序
}
//使用时对类数组进行Arrays排序
Arrays.sort(students);//此时students是一个数组对象
//调Arrays.toString(students),Student类需要被重写toString方法
System.out.println(Arrays.toString(students));
/*
以下为结果
原赋值数组数据:1:delete 21 2:float 66 3:long 33 4:index 77 5:long 86
排序后数组数据顺序(降序排序):
[Student{name='delete', age=21},
Student{name='index', age=77},
Student{name='float', age=66},
Student{name='long', age=33},
Student{name='long', age=86}]
*/

十四、集合

  • Array存储对象具有弊端,集合是一个动态的存储数据的容器

  • 集合、数组都是对多个数据进行存储操作的结构,简称Java容器

  • 说明:此时存储是在内存层面的存储,不涉及到持久化(.txt,.jpg,.avi,数据库)存储

14.1 数组与集合的对比

数组:

  • 有序,可重复

  • 只有arr.length可用,没有现成的属性和方法可用

  • 初始化后长度确定,长度不可修改

集合:Collection体系和Map体系

14.2 概述

  • Collection接口,Map接口

  • 单列数据与键值对数据

14.3 关系

  • Collection

    • List
    • Set
  • List:有序可重复

    • Vector
    • ArrayList
    • LinkedList
  • Set:无序不可重复

    • HashSet
      • LinkedHashSet
    • TreeSet
  • Map:一一对应

  • Hashtable

  • HashMap

    • LinkedHashMap
  • TreeMap

  • Hashtable

    • Properties

对象排序接口:

  • Comparable
  • Comparator

容器工具类:Collections

迭代器:Iterator

14.4 Collection接口

Collection coll = new ArrayList();

常用方法

  • add(E e) addAll(Collection c)

  • remove(“”) removeAll(Collection coll)

  • retainAll(Collection coll) //将两者的交集保存,其他的删除

  • int size()

  • isEmpty() //返回size==0,内容为空,不是指针为空

  • clear()

  • boolean contains(“”) //判断是否存在,内部调用equals进行对比

  • boolean containsAll(Collection coll)

  • hashCode()

  • toArray()

集合:Arrays.asList(123,456);

Iterator iterator() //返回此接口,用于遍历

forEach(方法引用) //用于遍历

14.5 List接口

元素有序、且可重复

常用实现类:ArrayList、LinedList、Vector

  • 相同点:三个实现类都实现了List接口,存储数据特点相同,存储有序,可重复数据

  • 不同点:

    • ArrayList:主要实现类,线程不安全,效率高,使用Object[] elementData存储

    • LinkedList:对于频繁插入、删除操作,使用此类效率比ArrayList效率高,底层使用双向链表存储

    • Vector:古老实现类,线程安全,效率低

14.5.1 常用方法

  • add(int index,Object ele)

  • addAll(int index,Collection eles)

  • Object get(int index)

  • int indexOf(Object obj)

  • int lastIndexOf(Object obj)

  • Object remove(int index) remove(Object obj)

  • Object set(int index,Objec ele)

  • List subList(int fromIndex,int toIndex) //返回此位置的子集合

14.5.2 ArrayList

jdk7建议开发时使用带参构造器new ArrayList( int capacity)设置初始值

jdk8中new ArrayList()创建的{}

如调用remove(?)方法,当?是数字时,认为?是一个索引,使用new Integer(?)才为对象

① 循环

  1. Iterator迭代器

  2. 增强foreach

  3. 普通for循环

  4. stream循环

  5. forEach(方法引用)循环

14.5.3 LinkedList

new LinedList()内部声明了Node类型的first和last属性,默认为null

14.5.4 Vector

已不使用,可使用下列方式进行线程安全操作

使用Collections.synchronizedList(List list)返回一个线程安全

14.6 Set接口

无序的,不可重复的

  • HashSet:主要实现类,线程不安全,可以存储null值

  • LinkedHashSet:HashSet的子类,遍历时按照添加的循序遍历

  • TreeSet:可以按照添加对象的指定属性进行排序

14.6.1 常用方法

无可用扩充方法,方法继承于Collection接口

14.6.2 无序性说明

根据数据的hashCode进行排序,而不是乱序

14.6.3 不可重复性说明

添加元素时先通过hashcode判断,再按照equals判断

14.6.4 hashCode 与 equals

重写的条件尽可能相等

14.6.5 HashSet

new HashSet()底层实现了HashMap

14.6.6 LinkedHashSet

频繁遍历效率高于HashSet

14.6.7 TreeSet

添加的数据只能是相同类的

两种排序,自然排序和定制排序

① 特性

与其他Set不同,判断重复(自然排序中)使用Comparable接口进行判断

② 底层结构

红黑树存储结构

③ 自然排序

实现Comparablechongxie compareTo(Object o)

④ 定制排序

new TreeSet(new Comparator)

14.7 Map接口

双列数据,键值对key-value

  • HashMap(主要实现类):线程不安全,相率高,存储null的key和value

    • LinkedHashMap:可以按照添加的循序实现遍历
  • TreeMap:保证按照添加的key-value进行排序,实现排序遍历,涉及到key的自然排序和定制排序

  • Hashtable(古老实现类):线程安全,效率低,不能存储null的key和value

    • Properties:处理配置文件,key和value都是String类型

14.7.1 常用方法

  • put(key,value) putAll(Map) //体现的是修改,重复key的value会被覆盖

  • Object remove(key)

  • clear()

  • get(obj) size() isEmpty() equals(obj)

  • boolean containKey/containValue(obj)

  • 元视图的操作方法

  • Set KeySet()

  • Collection values()

  • Set entrySet() //得到的都是Entry,通过getKey() getValue()进行获取

14.7.2 底层原理

jdk7 :数组+链表

  • 实例时创建16length的Entry[] table数组

  • 先调hashCode判断,哈希值相同继而调用equals方法进行比较数据

jdk8 :数组+链表+红黑树

  • 底层数组是Node[]不是Entry[]

  • 实例化不创建数组

  • 首次调用put()方法,底层创建16length数组

14.7.3 key与value

key无序,不可重复,Set存储所有的key,获取:Set keySet()

value无序,可重复 ,使用Collection存储所有的value,获取Collection values()

Set entrySet()

14.7.4 LinkedHashMap

按照添加顺序排序

14.7.5 TreeMap

key必须向同类型

根据key进行排序:自然排序,定制排序

14.8 Properties

用来处理配置文件,key和value都是String类型

  • 直接new Properties()

  • 调用load(InputStream)来加载资源

  • 调getProperty(String key)获取value

14.9 Iterator遍历

迭代器Iterator接口(设计模式的一种)

使用

hasNext() next() remove()

//注:remove()只能在调用next()后执行

Iterator iterator = collection.iterator();
while(iterator.hasNext()){
//next():指针下移,随后将下移以后的集合位置上的元素返回
iterator.next();
/*删除操作(删除集合中的数据)
Object obj = iterator.next();
if("String".equals(obj)){iterator.remove();}
*/
}

14.10 Foreach遍历

jdk5.0新增foreach循环,用于遍历集合、数组

内部调用迭代器Iterator实现

for(Object obj :collection){
//集合类型 局部变量:集合对象
//数组类型 局部变量:数组对象
sout(obj);
}

14.11 Collections工具类

操作Set,List,Map的工具类

  • reverse(List) shffle(List)

  • sort(List) sort(List,Comparator)

  • swap(List,int,int) //将指定List集合的ij元素进行交换

  • Object max/min(Collection[,Comparator])

  • int frequency(Collection) //返回指定集合中指定元素的出现次数

  • copy(List dest,List src)

  • XXX synchronizedXXX(XXX)要求线程安全可以调用此方法,ArrayList和HashMap都线程不安全

十五、泛型Generic

<T>标签

把元素的类型设计为一个参数,这个类型参数叫做泛型

泛型不能是基本数据类型

泛型类型没有被指明某一指定泛型时,默认Object类型

JDK7类型推断:List<String> list = new ArrayList<>();
  • <E>Element (在集合中使用,因为集合中存放的是元素)
  • <T>Type(Java 类),T代表在调用时的指定类型。
  • <K>Key(键)会进行类型推断
  • <V>Value(值)

泛型的指明:继承泛型时,使用泛型创建对象时

自定义泛型结构:泛型类、泛型接口、泛型方法、泛型属性

泛型类型不可定义静态方法,静态方法可以被泛型方法定义

泛型方法☆

在方法中出现了泛型的结构,泛型的参数与泛型参数没有任何关系,即泛型方法所属的类是不是泛型类都没有关系。

在调用时指明泛型参数的类型。

//泛型方法
public <E> List<E> copy(E[] arr){
...
}
//返回类型通过放入的类型决定

通配符?

  • <? extends Class>
  • <? super Class>

十六、DAO

data(base) access object

数据访问对象

数据库连接的类,增删改查

操作数据库的

十七、IO流

Input Output Stream

17.1 File

java.io包下

  • 相对路径:IDEA相对于module

  • 绝对路径:相对于磁盘根目录

  • 分隔符:File.separator

"\\" == "/"
//windows和dos系统用"\"来标识
//unix和url用"/"标识

17.1.1 常用方法

  • getAbsolutePath()

  • getPath()

  • getName()

  • getParent()

  • length()

  • long lastModified() //获取最后一次修改时间,毫秒值

  • String[] list()

  • File[] listFiles()

  • boolean renameTo(File)文件重命名为指定的文件路径

    • //实例:file1.renameTo(file2),文件1存在,文件2不存在,才可进行转换,有修改路径并重命名的功能

判断功能:

  • isDirectory() isFile() exists()

  • canRead() canWrite() isHidden()

增删功能:

  • createNewFile() mkdir() mkdirs()

  • delete() //不走回收站

17.2 流

InputStream OutputStream Reader Writer

17.2.1 关闭流

写在finally中,先判断流非null,再进行close()

注!!关闭外层流时,内层流也会自动关闭,内层流的手动关闭可以省略

17.3 字节字符流

  • 字符流:文本文件
  • 字节流:非文本文件

17.3.1 FileInputStream

  • int read()

  • int read(byte[])

17.3.2 FileOutputStream

  • write(byte[])

  • write(byte[],0,len)

17.3.3 FileReader

  • int read() //返回字节,读取结束返回-1

  • while(read() != -1){}

  • int read(char[]) //char型数组,返回每次读入的数据个数,读完返回-1

17.3.4 FileWriter

  • new FileWriter(file,boolean append) //append为是否追加数据

  • new String(char[],0,len)

  • write(str)

源文件不存在则新建文件

17.4 字符字节缓冲流

开发时常使用字符字节缓冲流处理,内部1024*8长度字节数组接收数据,提高流的读取和写出速度

先造节点流FileXXX再造缓冲流

  • BufferedInputStream

  • BufferedOutputStream

    • flush() //刷新缓冲区
  • BufferedReader

    • String readLine() //读完返回null,不接收换行符
  • BufferedWriter

    • flush()

    • newLine()

17.5 转换流

字节流和字符流之间的转换

  • 字节==>字符
  • 编码==>解码

第二个参数不写为系统默认字符集,一般写utf8

17.5.1 InputStreamReader解码

存入时什么字符集写什么字符集

17.5.2 OutputStreamWriter编码

想以什么字符集输出就写什么字符集

17.6 标准输入输出流

System.in System.out //字节流

默认控制台输入输出

System.setIn(InputStream in)

System.setOut(PrintStream out)

重新指定输入输出的流

17.7 打印流

PrintStream PrintWriter

基本数据类型格式转化为字符串输出

print()

println()

提供了一系列重载的方法

17.8 数据流

将数据持久化到文件中,读取或写出基本数据类型的变量或字符串

17.8.1 DataInputStream

17.8.2 DataOutputStream

writeUTF(String str)

writeInt(int)

writeBoolean(true)

flush()

17.9 对象流

存储和读取基本数据类型数据或对象,一个文件中基本都是一个类型

17.9.1 实现Serializable接口

17.9.2 类体声明序列化版本

不显示定义会自动生成UID,但若是对类修改,UID发生变化可能无法进行反序列化

public static final long serialVersionUID = 1837592785982379257L;

对象序列化机制:自行百度理解

17.9.3 特别

不能序列化static和transient修饰的成员变量

17.9.4 ObjectOutputStream

序列化,最好为.dat格式

写出到文件中

17.9.5 ObjectInputStream

反序列化

读取到内存中

17.10 RandomAccessFile

任意(随机)存取文件流

直接继承Object类,实现了DataInput和DataOutput接口

即可以作为输入,也可以作为输出

new RandomAccessFile(FIle,mode)

默认write从头开始逐个覆盖

可以深入文件内部修改

17.10.7 mode

  • r:只读
  • rw:读写
  • rwd:读写,且同步内容的更新
  • rws:读写,且同步文件内容和元数据的更新

17.10.8 常用方法

seek(int position) //指向某个位置

//可以通过file.length()获取长度,通过seek进行文件末尾追加操作

17.11 ByteArrayOutputStream

创建此对象构造器为空,调用write方法写出的数据存在对象中,当对象内存被沾满时,会自动扩容

17.12 NIO.2

NIO出自JDK1.4更加高效的方式进行文件读写,但不太行,于是有了NIO.2

  • Path、Paths、Files核心API
  • Path path = Paths.get(“文件路径”); //可获取文件

17.12.1 Path

可替代File类

17.12.2 Paths

静态方法get(String first,String … more) //可选多个字符串组成文档路径,返回一个路径

17.13 apach-commons-io

第三方jar实现数据读写

17.13.1 FileUtils

copyFile()

十八、网络编程Socket

IP:定位唯一的主机

端口号:定位软件通信,用来区分主机上的软件

网络通信协议

OSI TCP/IP

18.1 IP分为IPv4和IPv6

  • IPV4:4字节组成,4个0~255

  • IPV6:128位,16个字节,分成8个无符号整数,每个整数使用4个16进制标识,例如: 3ffe:3201:1401:…

  • 分类:公网(万维网,公有地址)和局域网(私有地址)

  • 私有地址:192.168.0.0-192.168.255.255

  • 域名:www.baidu.com

  • DNS:解析域名为IPV4/IPV6地址

18.2 端口号

  • 公认端口:0~1023,HTTP:80,FTP:21,Telnet:23
  • 注册端口:1024~49151,Tomcat:8080,MySQL:3306,Oracle:1521
  • 动态/私有端口:49152~65535

18.3 网络通信协议

18.3.1 TCP

  • 可靠
  • 先建立TCP链接,形成传输数据通道
  • 三次握手
  • 连接时可发送大量数据
  • 传输完毕释放连接,效率低

18.3.2 UDP

  • 不可靠
  • 不需要建立连接
  • 数据报发送,大小限制64K
  • 可以广播发送
  • 发送数据结束无需释放资源,开销小,速度快

18.4 InetAddress

  • 唯一标识Internet上的计算机(通信实体)
  • 本地回环地址127.0.0.1
  • 主机名:localhost

18.4.1 常用方法

  • InetAddress.getByName(“address”) //实例化,可写域名或IP
  • InetAddress.getLocalHost()

//获取的域名会自动返回网络上的实际地址

InetAddress inet1 = InetAddress.getByName("www.baidu.com");
System.out.println(inet1);
//www.baidu.com/39.156.66.18

18.5 Socket:TCP

端口号和IP地址的组合得出一个网络套接字

先有服务器ServerSocket后有客户端Socket

18.5.1 常用方法

  • 关闭socket传输:shutdownOut[In]put()
  • 客户端:new Socket(InetAddress,port)
  • OutputStream getOutputStream(); //调os的write输出
  • 服务器:new ServerSocket(port)
  • accept() //接收Socket
  • InputStream getInputStream() //获取客户端传来的数据

//建议接收数据存入ByteArrayOutputStream,使用baos.toString()进行输出

InetAddress inet = InetAddress.getByName("127.0.0.1");

18.6 TCP通信

//服务端
public class Server {
public static void main(String[] args) {
System.out.println("-----------服务器启动------------");
ServerSocket ss = null;
try {
ss = new ServerSocket(8888);
while (true) {
Socket accept = ss.accept();
new Thread(new ServerReceiveThread(accept)).start();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
//服务器线程
public class ServerReceiveThread implements Runnable {
private Socket socket;
public ServerReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String message;
while ((message = br.readLine()) != null) {
System.out.println(socket.getInetAddress().getHostName() + "-" + socket.getInetAddress().getHostAddress() + ":" + message);
}
} catch (Exception e) {
System.out.println(socket.getInetAddress().getHostName() + "-" + socket.getInetAddress().getHostAddress() + ":" + "下线了");
}finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}

//客户端
public class Client {
public static void main(String[] args) {
Socket socket = null;
PrintStream ps = null;
try {
InetAddress inet = InetAddress.getByName("192.168.0.107");
socket = new Socket(inet, 8888);
OutputStream os = socket.getOutputStream();
ps = new PrintStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("发送:");
if (sc.hasNextLine()) {
ps.println(sc.nextLine());
ps.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ps != null) {
ps.close();
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}

18.7 DatagramSocket:UDP

客户端

new DatagramSocket()

new DatagramPacket(data,0,data.length,InetAddress)发送的数据包 //data为byte[]

send(packet)发送

close()关闭socket连接

服务器

new DatagramSocket(port)

new DatagramPacket(data,0,data.length)接受数据

receive(packet)

使用packet.getData()获取数据

18.8 URL

  • 统一资源定位符Uniform Resource Locator
  • 对应互联网上某一资源地址
  • http://loaclhost:8080/bamboo/new.jpg
  • 协议 主机名 端口号 资源地址

18.8.1 常用方法

HttpURLConnection openConnection() //用于连接,调用connect()获取连接,使用getInputStream()读入输入流,使用disconnect()关闭连接

  • getProtocol()获取协议
  • getHost()获取主机名
  • getPort()获取端口号
  • getPath()获取文件路径
  • getFile()获取文件名
  • getQuery()获取查询名

十九、反射机制

Reflection(反射),被视为动态语言的关键

获取类的内部信息,直接操作任意对象的内部属性和方法

动态语言:运行时代码根据某些条件改变自身条件

  • java.lang.Class
  • java.lang.reflect.Method
  • java.lang.reflect.Field
  • java.lang.reflect.Constructor
  • ……

反射前:不可以通过new的对象进行调用内部private成员或方法

反射后:可调用private属性或方法

19.1 常用方法

  • Class.class用于制造Class类
  • class.getConstructor(param.class…) 进行构造器的创建
  • constructor.newInstance(param…)进行实例化对象
  • class.getDeclaredField(String fieldName) fieldName.set(class实例,param)

//反射出属性修改

  • class.getDeclaredMethod(String methodName,paramType.class) methodName.invoke(class对象)

//反射出方法进行调用,如果有返回值,强转返回值类型并接收

  • setAccessible(boolean) //破怀封住性,true时可以调用private修饰的结构

19.2 使用条件

反射特性:动态性

不确定具体对象时使用

19.3 Class理解

javac.exe编译后生成一个或多个字节码文件.class

类的加载:使用java.exe对字节码文件进行解释运行,将字节码文件加载到内存中。加载到内存中的类,称为运行时类,作为Class的一个实例

19.4 获取Class实例

方式一:调运行时类的属性.class

Class clazz = Person.class;

方式二:调运行时类的对象,调用getClass()

Class clazz = p1.getClass();

方式三:调Class静态方法forName(String classpath) //比较常用,体现反射动态性

Class clazz = Class.forName("com.bamboo.java.Person");//抛出ClassNotFound异常

方式四:使用类加载器ClassLoader

ClassLoader cl = 类.class.getClassLoader();
Class clazz = cl.loadClass("com.bamboo.java.Person");

19.5 获取Class属性

19.5.1 使用Declared修饰的方法

//getFields() getDeclaredFields()区别:后者不考虑权限,前者考虑权限,如private则不可被调用

19.5.2 Field:属性

Modifier:权限修饰符,获取时返回Int,default:0 public:1 private:2

//可通过Modifier.toString(int modifier)获取对应数值的权限字符串名

  • Type:数据类型,返回Class类型,调getName()返回数据类型名
  • Name:属性名,返回String

19.5.3 Method:方法名

  • Annotation:注解,先获取属性或方法,再获取注解
  • ReturnType:返回值类型
  • ParamaterTypes:获取参数类型
  • ExceptionTypes:获取异常

19.5.4 Constructor:构造器

19.5.5 Superclass:运行时父类

GenericSuperclass:带泛型的父类

19.5.6 Interface:接口

19.5.7 Package:包

19.6 设置

使用Declared修饰的get方法获取属性。。。等(可获取被private的属性。。。)

  • setAccessible(true)保证当前属性可访问
  • 设置属性set(实例,值)
  • 获取属性get(实例)

方法获取:参数1为方法名,参数2为形参列表…

调用方法invoke(实例,参数…),返回值为对应类中的返回值类型,如是static方法,使用Class.class作为实例参数

获取构造器,参数写类.class,调newInstance()创建对象

19.7 创建运行时类的对象

//1.
Class<Person> clazz = Person.class;
//前提:具有空参构造器,权限不是private,通常设置为public
Person p = clazz.newInstance();//内部调用了Person类的空参构造器
//习惯用Class建立对象,比较通用,使用获取的构造器造对象可能导致不通用(其中参数不同)

19.8 可获取Class实例的结构

外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类

interface []数组 enum annotation 基本数据类型 void Class

元素类型和元素维度相同,则被认为同一Class实例

19.9 ClassLoader读配置文件

Properties pros = new Properties();
InputStream is = 类.class.getClassLoader().getResourceAsStream("xxx.properties");
//获取类路径为classpath,根目录下
pros.load(is);
String xxx = pros.getProperty("xxx");

19.10 反射应用:动态代理

????????????????????????????????????????????????

二十、JDK8新特性

14年发布,滞后期,出来后经过时间的检验才被使用

20.1 Lambda表达式

简化写法:-> :Lambda操作符 或 箭头操作符

  • 左:参数列表
  • 右:Lambda体
  • 格式:(e1,e2)->{sout…};
  • 无参可只写()
  • 只有一个参数可写为:e1->{}
  • 单个语句不需要书写{}
  • 直接返回的语句不需要写{},也不能写return

20.2 函数式接口

@FunctionalInterface:用于实现Lambda表达式

只有一个抽象方法的接口

20.2.1 内置四大核心函数式接口

  • Consumer<T> :void accept(T t) //消费型接口
  • Supplier<T> :T get() //供给型接口
  • Function<T,R> :R apply(T t) //函数型接口
  • Predicate<T> :boolean test(T t) //断言型接口

20.3 方法引用

"::" :MethodReferences

使用:当要传递给Lambda体的操作,已经有实现的方法,就可以使用方法引用,本质上就是Lambda表达式

  • 方式一:对象::实例方法
  • 方式二:类::静态方法
  • 方式三:类::实例方法
  • 构造器引用
  • 方法引用

20.4 Stream API

对集合进行操作

20.4.1 注

不会改变源数据,会返回一个持有结果的Stream流

延迟操作,执行终止操作前都不会执行

每次终止后需要新建Stream流

20.4.2 使用步骤

1.创建Stream

2.中间操作

3.终止操作(终端操作)

20.4.3 创建方式

一、集合创建

//顺序流
Stream stream = list.stream();
//并行流,像线程
Stream stream = list.parallelStream();

二、数组创建

//通过Arrays类的静态方法创建
Stream stream = Arrays.stream(arr[]);
//IntStream stream = Arrays.stream(arr[]);当数组是int时返回指定类型流

三、Stream的of()

Stream stream = Stream.of(T... value);

四、创建无限流

//迭代
public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f)
/*
具有限制limit和终止操作forEach结束
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::print);
Console: 0 2 4 6 8 10
*/

//生成
public static<T> Stream<T> generate(Supplier<T> s)
/*
Stream.generate(Math::random).limit(10).forEach(System.out::print);
Console: 0 2 4 6 8 10 随机数
*/

20.4.4 中间操作

① 筛选与切片

  • filter(Predicate p) 接收Lambda 排除某些元素
  • distinct() 筛选去重
  • limit(n) 截断,不超过给定数量
  • skip(n) 跳过元素返回被跳过的n个元素的流

② 映射

  • map(Function f) 接收一个函数作为参数,应用到每一个元素上,将其映射成一个新的元素,返回新的类型
  • flagMap(Function f) 将流中的每个值都换成另一个流,将所有流连成一个流,解锁Stream嵌套 Stream<Stream>
  • map类似add,flagMap类似addAll

③ 排序

  • sorted() sorted(Comparator com)
  • 自然排序(implements Comparable) 和 定制排序

20.4.5 终止操作

① 匹配与查找

  • boolean allMatch(Predicate p)
  • boolean anyMatch(Predicate p)
  • boolean noneMatch(Predicate p)
  • findFirst()
  • findAny()
  • Long count()
  • Object max(Comparator c)
  • Object min(Comparator c)
  • forEach(Consumer c) //Stream是内部迭代,Collection做迭代是外部迭代

② 归约

  • reduce(T iden,BinaryOperator b) 流中元素反复结合,得到一个值,返回T,identity是初始值
  • reduce(BinaryOperator b) 流中元素反复结合,得到一个值,返回Optional

③ 收集

  • collect(Collector c)

  • 需要传入参数:Collectors.{toList() toSet toCollection()}

  • ……

20.5 Optional

处理臭名昭著的空指针异常

Optional<T>是一个容器类,保存类型T的值

20.5.1 创建Optional类对象

Optional.of(T t) 创建一个Optional实例,t必须非空

Optional.empty()创建空的Optional实例

Optional.ofNullable(T t)创建一个t可以是null的实例

20.5.2 判断Optional容器

boolean isPersent() 判断是否包含对象

void ifPresent(Consumer<? super T> consumer) 如果有值,就执行接口的实现代码,并且该值会作为参数传给它。

20.5.3 获取Optional容器的对象

  • T get() 调用对象包含值,没有则抛异常
  • T orElse(T other) 没值则返回指定other对象
  • ……

20.5.4 优化代码,NullPointerException

public String getName(Class c){
Optional<Class> o = Optional.ofNullable(c);
Class returnC = o.orElse(new Class("param"));
return returnC.getName();
}

二十一、JDK9

此版本开始发布新版本周期为6个月

三年为周期发布长期支持版本LST(long term support)

二十二、小Tips

1.使用Scanner时,先进行hasNextLine()判断,再进行nextLine()接收,杜绝报错

2.引用类型数组中:先判断是否==null后使用”||”进行.length==0判断,杜绝空指针异常且判断因哟红数组长度

//(quoteArr == null) || (quoteArr.length == 0)

二十三、IDEA

JetBrains(捷克)公司开发

23.1 基本设置

  1. 取消更新
  2. 设置字体13、14
  3. 设置字符编码
  4. 忽略大小写提示
  5. 设置模板template
  6. 设置maven
  7. VM添加-Dfile.encoding=UTF-8 //可解决TomcatCatalinaLog中文乱码

23.1 idea.properties

idea.config.path=${user.home}/.IntelliJIdea/config

idea.config.path=D:\Develop\JetBrains\IntelliJ IDEA/config
#---------------------------------------------------------------------

Uncomment this option if you want to customize a path to the caches directory.

#---------------------------------------------------------------------

idea.system.path=${user.home}/.IntelliJIdea/system

idea.config.path=D:\Develop\JetBrains\IntelliJ IDEA/system
#---------------------------------------------------------------------

Uncomment this option if you want to customize a path to the user-installed plugins directory.

#---------------------------------------------------------------------

idea.plugins.path=${idea.config.path}/plugins

idea.plugins.path=D:\Develop\JetBrains\IntelliJ IDEA/plugins
#---------------------------------------------------------------------

Uncomment this option if you want to customize a path to the logs directory.

#---------------------------------------------------------------------

idea.log.path=${idea.system.path}/log

idea.log.path=D:\Develop\JetBrains\IntelliJ IDEA/log

23.2 plugins

Auto filling Java call arguments

安装完该插件以后,调用一个函数,使用 Alt+Enter 组合键,调出 “Auto fill call parameters” 自动使用该函数定义的参数名填充

Maven Helper

以安装该插件,安装后 IDEA 中打开 pom.xml 文件时,就会多出一个 “Dependency Analyzer” 选项卡

MyBatisCodeHelperPro

mybatis代码帮助插件。最好的Mybatis代码提示,完整支持Mybatis动态sql代码提示,代码检测,写sql几乎所有地方都有代码提示

Free MyBatis plugin

mybatis 增强插件。free-idea-mybatis是一款增强idea对mybatis支持的插件。快速从代码跳转到mapper及从mapper返回代码。

Alibaba Java Coding Guidelines

阿里巴巴代码规范插件。

CodeGlance

拖动浏览代码更加方便,还有放大镜功能

Rainbow Brackets

它可以实现配对括号相同颜色,并且实现选中区域代码高亮的功能。对增强写代码的有趣性和排错等都有一些帮助。

Translation

设置微软后Ctrl+Shift+Y获得翻译,可设置原始格式翻译

One Dark theme

黑暗主题

Atom_Material_Icons

图标更替

23.3 快捷键

23.3.1 基本快捷键

  • F11文本高亮标记

  • Ctrl+N查找类

  • Ctrl+Alt+Shift+N查找方法或全局变量

  • Ctrl+Shift+N查找文件

  • Ctrl[+Alt]+Space获取静态常量或方法建议

  • Ctrl+W选取内容

  • 在语句开头按Ctrl+W选取关键字对应语句,例如if语句

  • 复制删除:Ctrl+D复制行 Ctrl+X剪切行 Ctrl+Y删除行

  • Alt+Shift+↑↓移动行

  • Ctrl+Shift+↑↓移动方法

  • 环绕和解开:Ctrl+Alt+T Ctrl+Shift+Delete

  • 多选:Alt+J选择 Alt+Shift+J取消一项 Ctrl+Alt+Shift+J选择文中所有匹配项

  • Ctrl+F12文件结构//可查看具体类定义随后Alt+7展开结构方法

23.3.2 补全

  • Ctrl+Shift+Space类型匹配补全

  • .后缀补全

  • Ctrl+Space基本补全词条

  • Ctrl+Shift+Enter补全语句

  • Alt+Enter意图补全

  • Tab补全,使用Ctrl+Space查看补全建议,选择使用Tab进行补全

23.3.3 重构

  • Shift+F6重命名

  • Ctrl+Alt+V提取变量集体更名

  • Ctrl+Alt+Shift+T重构部分列表

  • Alt + Insert快捷插入

23.3.4 代码辅助

  • 本地历史记录恢复撤销无法恢复的删除内容

  • Ctrl+Alt+L格式化代码

  • Ctrl+P形参信息,可以获取形参列表的内容

  • Ctrl+Q预览光标处文档,可以看到形参内容等信息

  • Ctrl+Shift+I查看文本光标处符号的定义,可以看到方法全部内容

  • Ctrl+F12显示本类所有方法

  • Ctrl+H显示本类所有实现类

23.3.5 编码辅助

  • F2跳转高亮错误

  • Ctrl+F1获得简要说明信息,可以获取方法帮助

23.4 快捷模板学习

  • Editor->Posfix Completion

  • Editor->Live Templates

可以自定义模板进行减少代码量

二十四、扩展工具

24.1 @Lombok

  • @Accessors(chain=true) 是 Lombok 中的一个注解,它可以通过链式调用的方式来简化 Java 对象的构建和操作。

  • @Accessors(chain=true) 可以自动为 Java 类中的 setter 方法返回当前对象的实例,从而实现链式调用。

User user = new User().setName("Alice").setAge(18);