注意:以下总结基于JDK1.8版本
JDK:Java Development Kit,Java开发工具包,包含JRE
JRE:Java Runtime Environment,Java运行时环境,包含JVM
JVM:Java Virtual Machine,Java虚拟机
JDK=JRE+开发工具(源码编译:javac命令)
JRE=JVM+核心类库(解释运行:java命令)
Java 基础语法
程序基础
类:类是一个模板,它描述一类对象的行为和状态。
方法:方法就是行为,一个类可以有很多方法。
对象:对象是类的一个实例,有状态和行为。
实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。
基本语法:标识符以字母,$或_开始,大小写敏感,类名首字母大写,方法名小写字母开头,后续单词大写,源文件名与类名相同,主方法入口为psvm。
Java有3种注释,单行注释,以
//
开头,直到这一行的结尾结束;多行注释以/*
星号开头,以*/
结束,可以有多行;或者以/**
开头,以*/
结束,如果有多行,每行通常以星号开头。关键字
48个关键字:abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while。
2个保留字:goto、const。
3个特殊直接量:true、false、null。
数据类型
八大基本数据类型(二进制补码表示,整数默认int,浮点数默认double)
整数类型:byte(1B),short(2B),int(4B),long(8B)
浮点数类型:float(4B),double(8B)
字符类型:char(0/1)
布尔类型:boolean(16 位 Unicode 字符)
自动类型转换:byte,short,char—> int —> long—> float —> double
引用数据类型:诸如对象,数组,字符串等
变量类型
- 类变量/静态变量:独立于方法之外的变量,用 static 修饰,一份拷贝,初始化后不可改变
- 实例变量:独立于方法之外的变量,没有 static 修饰,具有默认值,常用private
- 局部变量:类的方法中的变量,需要初始化,作用域为方法
修饰符
访问修饰符:private(方法) –> default(包) –> protected(同包子类) –> public(所有类)
非访问修饰符:
static 修饰符,用来修饰静态类方法和类变量,一般通过类名调用,所有实例共享
final 修饰符,修饰类不能够被继承,修饰方法不能被继承类重写,修饰变量为不可修改的常量
abstract 修饰符,用来创建抽象类和抽象方法。
synchronized 和 volatile 修饰符,主要用于线程的编程。
运算符:算术运算符,关系运算符,位运算符,逻辑运算符,赋值运算符,三目运算符
?:
,instanceof运算符(判断实例是否为指定类型或子类)流程控制
顺序结构:
;
结尾条件结构:if…else / switch…case
循环结构:while,do…while,for
注意:break跳出当前循环代码块,continue跳转下一次循环迭代
数组
- 声明创建
- dataType[] arrayRefVar = new dataType[arraySize];
- dataType[] arrayRefVar = {value0, value1, …, valuek};
- 多维数组可直接多维分配空间,也可先高维分配,后低维分配
- 遍历
- 普通for循环按索引(从0开始)遍历
- 增强for循环直接遍历元素
- 排序
- Arrays数组类提供sort()方法进行排序
面向对象
方法
方法==>方法头(修饰符,返回值,方法名,形参)+ 方法体
构造方法:
- 默认的无参数构造方法;
- 编译器根据参数自动判断选择哪个构造方法;
- 构造方法相互调用,便于代码复用。
参数绑定:
- 基本类型参数的传递,是调用值的复制。
- 引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方。
重载 overload
- 同名方法,形参列表不同,方法签名不同
- 一般返回值是相同的
封装 Encapsulation
封装实现细节,对外提供接口(this.set+get),便于修改,减少耦合
继承 Extends
- 单继承+多重继承,根类为object,父类通用,子类具体
- 子类访问父类protected变量和方法,重写override,返回值和形参不变,修改核心
- 子类不会继承任何父类的构造方法,子类显式调用
super()
并给出参数以定位到父类相应的构造方法 - 继承是is-a关系,组合是has-a关系
- 可以安全地向上转型为更抽象的类型;借助
instanceof
判断也可以强制向下转型
多态
针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法
存在的必要条件=继承+重写+父类引用指向子类对象
实现方式:重写,接口,抽象类和抽象方法
object类定义的三个重要方法
toString():把instance输出为String;
equals 的作用:
引用类型:默认情况下,比较的是地址值,引用类型的比较一般都会覆写该方法
== 的作用:
基本类型:比较的就是值是否相同
引用类型:比较的就是地址值是否相同- hashCode():计算一个instance的哈希值。
接口 Implements
- 接口比抽象类更加抽象,支持多继承
- 接口中的成员变量只能是默认public static final
- 接口都是抽象方法,默认public abstract省略,但可以定义default方法
- 接口可以继承接口,扩展功能
- 函数式接口:只能有一个抽象方法的接口,比如Comparator、Runnable、Callable
抽象类和抽象方法 abstract
- 抽象类不能实例化对象,设计原则用于子类继承,非抽象子类必须实现父类的抽象方法
- 抽象方法只定义方法签名(只有方法名加括号),含有抽象方法必须申明为抽象类
常用类
String
可以直接创建(存储在公共池中),也可以new创建(新建对象在堆上)
常用操作:
- 长度lenth(),拼接concat()或+
- 索引查找indexOf(),子串查看contains()
- 提取子串substring(),替换子串replace()
- 格式化字符串String.format(),占位符:整数
%s
字符串%s
浮点数%f
- 类型转换:String.valueOf(),Integer.parseInt(),toCharArray()
字符编码:ASCII(1B)=> GB2312(1B)=> Unicode(2B+)=> UTF-8(1-4B)
java使用unicode编码表示String 和char,转换编码就是String和byte()转换(优先考虑UTF-8)
String 是不可变对象,操作不改变原对象,二是返回新的字符串
StringBuffer和StringBuilder(可变对象,链式操作自身)
Math
- 数学计算库:min/max,abs,pow/sqrt,exp/log ……
Random
- SecureRandom:生成安全的随机数
1 | Random r = new Random(seed); |
大数:BigInteger和BigDecimal
枚举
- 枚举是特殊的类,为了做信息的标识和分类,声明一组带标识符的常数
- name()获取枚举常量的名字,ordinal()获取常量定义的顺序
1 | enum Color |
日期时间
- Date和Calendar(旧API); 格式化SimpleDateFormat
- yyyy:年、MM:月、dd: 日、HH: 小时、mm: 分钟、ss: 秒
- LocalDateTime(新API);格式化DateTimeFormatter
Lambda表达式
- 可选类型声明、可选括号、可选返回关键字
- 形如:参数列表 -> 方法体
1 | interface MathOperation { |
处理函数式接口时,可把实例化匿名内部类改写为Lambda表达式,简化代码
1 | //匿名内部类 |
异常处理
- Error表示严重错误,无法处理;而Exception是运行时错误,可以被捕获并处理。不需要捕获的异常,包括
Error
及其子类,RuntimeException
及其子类不做强制性捕获要求,剩下必须捕获的又称为检查性异常
- 采用try…catch…finally捕获异常;调用
printStackTrace()
可以打印异常的传播栈 - 只要是方法声明的Checked Exception,就需要在调用层捕获或者抛出
- 日志库取代手动打印
- java.util.logging
- Apache第三方日志库Commons Logging,自动搜索挂接Log4j
集合类
Java标准库自带的java.util
包提供了集合类:Collection
,它是除Map
外所有其他集合类的根接口。优点有:接口和实现分离,支持泛型,通过迭代器统Iterator一访问集合。
List
- 有序列表:数组实现ArrayList和链表实现LinkedList
- 其它操作:add、get、set、remove、size
- 在List中查找元素时,List的实现类通过元素的equals()方法比较两个元素是否相等,因此,放入的元素必须正确重写equals()方法。
1 | List<T> list = new ArrayList<T>(); |
1 | // 三种常用遍历方式 |
Map
- 键值映射表,通过key高效查找value,Map查找速度比List快,可作为缓存
- key无序HashMap,有序TreeMap
- 其它操作:put(key,value)、get(key)、size()、containsKey(key)、getOrDefault(key,value)
- map采用空间换时间的方式,key通过hashCode()计算数组索引,返回对应value
- 作为key的对象必须正确重写equals()方法
- 作为key的对象还必须正确重写hashCode()方法,并且保证相等对象哈希值相等(保证正确性),不相等对象哈希值尽量不相等(减少冲突)
- hashmap内部使用数组默认大小为16,自动扩容*2,但需要重现计算索引,避免影响性能,一般提前预设定好大小
- 哈希冲突:利用list存储不同key但hashcode相同的value
1 | Map<K,V> map = new HashMap<K,V>(); |
1 | // 遍历key |
Set
- 不重复的元素集合,相当于只有不重复的key
- 无序HashSet,有序TreeSet
- 其它操作:add、remove、contains、size
- 放入Set的元素和Map的key类似,要正确重写equals()和hashCode()方法,否则元素无法正确加入Set
1 | Set<T> set = new HashSet<T>(); |
- Collections.sort()
- 第一个参数为集合实例,第二个参数为比较器Comparator(利用匿名内部类或Lambda表达式实现)
- 重写compare方法注意,升序和降序区分:返回-1代表前者放前面,即权重小的放前面
反射 Reflection
- 反射机制用于在程序运行期间动态变化时,对任意类或对象都能调用其字段和方法(通过Class实例获取)
- class在JVM中动态加载,JVM为每一个class创建一个Class类型的实例(名为Class的class),而Class实例包含了该class的所有信息
1 | Class c = String.class; // 静态变量获取实例 |
反射访问字段:
Class实例
通过getField(name)、getDeclaredField(name)方法获取Field实例
,利用Field可以获取字段信息,读取或者设置对象字段,如果存在访问限制,要首先调用setAccessible(true)来访问非public字段,会破坏封装反射调用方法:
Class实例
通过getMethod(name, Class)、getDeclaredMethod(name, Class)方法获取Method实例
,利用Method可以获取方法信息,采用invoke(instance, parameters)调用对象的某个方法反射调用构造方法:通过
Class
实例的方法可以获取Constructor
实例,通过Constructor
实例可以创建一个实例对象反射获取继承关系:getSuperclass获取父类类型,getInterfaces获取当前类实现的所有接口
动态代理:动态代理不需要在编译期就实现,并且往往可以代理多个类class,拦截对真实业务对象的访问。静态代理只代理一个类class,由程序员编写,在编译器就生成相应的.class文件,由程序员调用。
使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过代理类来调用目标方法,代理类会将所有的方法调用,分派到目标对象上反射执行
动态代理是通过Proxy类创建代理对象,然后将接口方法代理给InvocationHandler接口完成的
1 | import java.lang.reflect.InvocationHandler; |
注解 Annotation
- 注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”:用作标注的元数据
- 自定义注解
- 使用@interface定义注解
- 添加参数以及default默认值,最常用参数为value
- 使用元注解配置注解,Target指定应用范围,Retention指定生命周期
1 |
|
注解按生命周期分有三类
- SOURCE:在编译期被丢弃,如@Override、@SuppressWarnings
- CLASS:仅保存在class文件中,加载结束后并不会存在于内存中
- RUNTIME:加载进JVM,并且在运行期可以被程序读取
使用反射API读取注解信息
添加自定义注解本身对程序逻辑没有任何影响,需要编写代码来使用注解,比如检查字段规则