API 架构
文档注解
通过javadoc
指令可生成文档@author
、@version
、@since
、@param
、@return
、@throws
数据类型
Primitive Type
type | range |
---|---|
byte | 8-bit signed two's complement integer (-27 to 27 -1, inclusive) |
short | 16-bit signed two's complement integer (-215 to 215 -1, inclusive) |
int | 32-bit signed two's complement integer (-230 to 230 -1, inclusive) |
long | 64-bit signed two's complement integer (-263 to 263 -1, inclusive) |
char | 16-bit unsigned unicode character (0 to 216 -1, inclusive) |
float | 32-bit ANSI/IEEE 754 single-precision float |
double | 64-bit ANSI/IEEE 754 single-precision float |
returnAddress | address of an opcode |
reference | reference to an object on the heap, or null |
Reference Type
ASCII, American Standard Code for Information Interchange
char | int | hex | unicode |
---|---|---|---|
0 | 48 | 0x0030 | u0030 |
A | 65 | 0x0041 | u0041 |
a | 97 | 0x0061 | u0061 |
二进制
- 源码,十进制值对应的二进制值。Java中使用32-bit存储,以0b前缀表示字面量。
- 反码,正数为本身,负数的源码取反。
- 补码,反码加1。
八进制:以0为前缀表示。
十六进制:以0x为前缀表示。
positive | negative | |
---|---|---|
decimal | 19 | -19 |
binary | 0000 0000 0000 0000 0000 0000 0001 0011 | 1000 0000 0000 0000 0000 0000 0001 0011 |
octonary | 23 | 1777777777777777777755 |
hexacimal | 13 | FFFFFFFFFFFFFFED |
radix-minus-one complement | 0000 0000 0000 0000 0000 0000 0001 0011 | 1111 1111 1111 1111 1111 1111 1110 1100 |
two's complement | 0000 0000 0000 0000 0000 0000 0001 0100 | 1111 1111 1111 1111 1111 1111 1110 1101 |
位运算符
19 | -19 | |||
---|---|---|---|---|
0001 0011 | 1001 0011 | |||
左移 | >> | n >> 2 | 0000 0100 | 1111 1011 |
右移 | >>> | n >>> 2 | 0000 0100 | 0011 1011 |
无符号右移 | << | n << 2 | 0100 1100 | 1011 0100 |
或 | & | n & 2 | 0000 0010 | 0000 0010 |
与 | | | n | 2 | 0001 0011 | 1001 0011 |
异或 | ^ | n ^ 2 | 0001 0001 | 1001 0001 |
非 | ~ | ~n | 1110 1100 | 0110 1100 |
算数运算符:+、-、*、/、%、++、--
赋值运算符:=
关系运算符:<、>、<=、>=、==、!=、instanceof
扩展运算符:+=、-=、*=、/=
逻辑运算符:&&、||、!
a | b | !a | a&&b | a||b |
---|---|---|---|---|
true | true | false | true | true |
true | false | false | false | true |
false | true | true | false | true |
false | false | true | false | false |
短路运算
a && b
:当a为false时,b不会进行计算。a || b
:当a为true时,b不会进行计算。
Supplier<Boolean> supl = () => {
System.out.println("--->");
return false;
}
if (false & supl.get()){}
if (false && supl.get()){}
if (true | supl.get()){}
if (true || supl.get()){}
三目运算符:expr? a : b;
标识
大小写敏感,可以包含字母、数字、下划线、美元符号。不能以数字开头,不能使用关键字和保留字。
命名约定
- 类名通常使用大写字母开头的驼峰命名法。
- 方法名和变量名通常使用小写字母开头的驼峰命名法。
- 常量名通常全部使用大写字母,并用下划线分隔单词。
变量
Java是强类型语言所有变量必须先定义后使用,变量是程序中最基本的存储单元,每个变量都有类型可以是基本类型和引用类型,变量必须使用合法标识符。
作用域
局部变量:从属方法,方法随方法块的生命周期存活。
实例变量:从属实例,随实例的生命周期存活。
静态变量:从属类,需要使用static 修饰,随类加载存活值可改变。
实例常量:从属实例使用final 进行修饰,随实例生命周期存活需要初始化值并且不能更改。
常量:从属类,需要使用
static final
修饰,随类加载存活需要初始化值并且不能更改。
public class Clz {
// 实例变量
Clz var = new Clz();
// 静态变量
static Clz var = new Clz();
// 实例常量
final Clz var = new Clz();
// 常量
static final Clz var = new Clz();
void method() {
// 局部变量
Clz var= new Clz();
}
}
其他修饰符
transient
:序列化忽略。序列化对象时,JVM会跳过被transient
修饰的实例变量。volatile
:保证变量的可见性。volatile
修饰的实例变量,被线程访问时,都强制从共享内存中重新读取该变量的值。而且,当实例变量发生变化时,会强制线程将变量值写回到共享内存。这样不同线程每次访问时都能获取相同值。
类型转换
强制转换、向上转型、声明式转换
- 失去精度
- 高位阶向低位阶转换
- 父类向子类转换
自动转换、向下转型、匿名式转换
- 低位阶向高位阶转换
- 子类向父类转换
- 数值类型中不同类型间进行计算,byte, short 自动转化为 int, 算式会根据最左边变量类型进行转换。当存在高阶位类型向低阶位进行转换时,可能会出现内存溢出现象,导致计算错误。
- 由低向高分别为:byte、short、int、long、float、double
方法
构造方法
用于初始化引用类型生成实例。其方法名与所属的类同名且无显式声明返回类型,但其返回值类型与所属的类相同。 支持重载(@Overload
)。
普通方法
access-modifier other-modifier return-value method-name(variables) {}
访问权限
package
:为了更好组织类Java提供了包机制,用于区别类名的命名空间。import
:引用某一包成员时需要显式声明导入该包。
修饰符 | 同类 | 子类 | 同包 | 子类异包 | 异包 |
---|---|---|---|---|---|
private | 1 | 0 | 0 | 0 | 0 |
default | 1 | 1 | 1 | 0 | 0 |
protected | 1 | 1 | 1 | 1 | 0 |
public | 1 | 1 | 1 | 1 | 1 |
其他修饰符
static
:方法脱离实例存在final
:子类型中不能覆写该方法abstract
:该修饰符所修饰的方法仅为声明方法而无方法体定义具体行为,其子类型必须覆写该方法。synchronized
:一种内置的同步机制,用于控制多个线程对共享资源的访问。它确保在任何时刻,只有一个线程可以执行某个特定代码块或方法。
返回值
- 无返回值:
void
- 声明返回值:可定义具体返回类型或基础类型。
参数列表
- 无参数
- 形式参数:传入参数,在调用时传入。
- 可变参数:v1.5 引入。必须在参数列表的最后一位声明,用于接受不定数额参数但同类型参数。(
method(Integer... array){}
)
方法体
所声明方法下的具体行为
@Overload
子类型对父类型声明的方法进行覆写或是实现
@Override
- 同一个类中方法名相同参数列表不同
- 返回类型可不同
- 返回类型不同不足以成为方法重载
控制流
顺序结构:基础执行结构为顺序结构。语句与语句直接从上到下依次执行。
选择结构
- 单分支
if (expr) {}
- 双分支
if (expr) {
} else {}
- 多分支1
if (expr) {
} else if (expr) {
} else {}
- 多分支2
- v7 开始支持
String
- val 必须为字面量或常量
- expr:
byte
,short
,int
,char
,String
case
穿透:case
块中若没有break
关键字作为结束标志,当case
块执行完后会继续执行相邻的后一case
块。
- v7 开始支持
switch (expr) {
case val0:
break;
case val1:
break;
default:
break;
}
嵌套结构:在选择结构的基础上进行任意嵌套。
循环
while
:先判断后执行。满足条件才执行。
while (expr) {}
do-while
:先执行后判断,至少执行一次。
do {
} while (expr)
for
:执行顺序init->expr->for
块->incr
for (init; expr; incr) {}
乘法表
for(int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(i + " * " + j + " = " + (i * j) + "\t");
}
System.out.print("\n")
}
三角形
for (int i = 0; i <= 10; i++) {
for (int j = 10 - i; j 0; j--) {
System.out.print("\t");
}
for (int j = 0; j <= i; j++) {
System.out.print(" * ");
}
for (int j = 0; j <= i - 1; j++) {
System.out.print(" * ");
}
System.out.print("\n");
}
for
增强:v1.5 引入,用于迭代数组和集合
int[] arr = {};
for (int i : arr) {}
goto
:作为保留字但并未实际应用。其效果由continue和break两个关键字实现。
break
:while
、for
块中的终止符
continue
跳过一轮循环
- 质数:大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
x: for (int i = 0; i <=100; i++) {
for (int j = 2; j < i/2; i ++) {
if (i % j == 0) continue x;
System.out.print(i + "/t");
}
}
递归
- 方法体定义所定义行为中调用当前声明方法,构成循环调用。
- 需要
if
定义终止条件(防止出现java.lang.StackOverflowError
) - 参数存在动态变化
- 阶乘
int factorial(int i) {
if (i == 1) return 1;
return i * factorial(i - 1);
}
数组
固定长度:初始化后长度不能修改。
类型相同:同一数组同一类型。
数组类型:可定义为基础类型或者引用类型。
声明
int[] arr;
int arr[];
初始化
arr = new int[10];
arr = {...}
arr = new int[] {...};
访问
for (int i = 0; i < arr.length; i++) {}
for (int i : arr) {}
索引越界:索引值超出数组初始化长度。java.lang.ArrayIndexOutOfBoundsException
- 几维数组
int[][] arr = new int[][];
int[][] arr = {{}, {}, };
int[][] arr = new int[][]{{...}, {...}, ...};
- 冒泡排序1
for (int i = arr.length - 1; i == 0; i--) {
for (int j = 0; j < i; j++) {
int k = j + 1;
if (arr[j] > arr[k]) {
arr[k] = arr[j] ^ arr[k];
arr[j] = arr[j] ^ arr[k];
arr[k] = arr[j] ^ arr[k];
}
}
}
- 冒泡排序2
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
int k = j + 1;
if (arr[j] < arr[k]) {
arr[k] = arr[j] ^ arr[k];
arr[j] = arr[j] ^ arr[k];
arr[k] = arr[j] ^ arr[k];
}
}
}
OOP
面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它使用对象和类的概念来模拟现实世界中的实体和它们之间的关系。面向对象编程的核心思想是将数据(属性)和处理数据的方法(行为)封装在对象中,以提高代码的可重用性、灵活性和可维护性。
类
类是对象的蓝图或模板,它定义了一组属性(成员变量)和方法(成员函数),这些属性和方法在创建对象时会被实例化。(class
)
对象
对象是类的实例,每个对象都拥有类中定义的属性和方法。(this
)
封装(Encapsulation)
封装是将数据和操作数据的方法组合在一起,并隐藏内部实现的细节,只暴露有限的接口供外部访问。(private
、default
、protected
、public
)
继承(Inheritance)
继承是一种创建新类的方式,新类(子类)可以继承现有类(父类或超类)的属性和方法,同时也可以添加新的属性和方法或覆盖(@override
)继承的方法。(implements
、extends
、@Override
、super
、final
)
多态(Polymorphism)
多态是指对象可以有多种形式,允许不同类的对象对同一消息做出响应。这意味着一个接口可以被多个类实现,具体调用哪个类的方法取决于对象的实际类型。(implements
、extends
、@Override
、@Overload
)
抽象(Abstraction)
抽象是将复杂的现实问题简化的过程,只关注与当前问题相关的属性和行为,忽略不相关的细节。(abstract
、interface
、default
)
面向对象设计原则
- 单一职责原则(SRP):一个类应该只有一个引起它变化的原因。
- 开放封闭原则(OCP):软件实体应该对扩展开放,对修改封闭。
- 里氏替换原则(LSP):子类对象应该能够替换其基类对象。
- 接口隔离原则(ISP):不应该强迫客户依赖于它们不使用的方法。
- 依赖倒置原则(DIP):高层模块不应该依赖于低层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。
泛型
v1.5 引入。泛型一种允许在编译时检查类型安全的机制。它允许你在定义类、接口和方法时指定一个或多个类型参数,这些类型参数可以在使用时被具体的类型替代。
- 仅允许引用类型
- 泛型参数不能被实例化。(例如,new T() 是不允许的)
- 泛型类的类型参数不能用于静态方法或静态变量。
- 在运行时,泛型类型信息会被擦除,这意味着
List<String>
和List<Integer>
在运行时都被视为List
。
无界通配符:<?>
表示可以接受任何类型的泛型类型。(例如,List<?>
可以接受List<String>
、List<Integer>
)
有界通配符
- 上限通配符:
<? extends T>
表示可以接受 T 或其子类型的泛型类型。 - 下限通配符:
<? super T>
表示可以接受 T 或其父类型的泛型类型。
<E> void method(E[] arr) {
for (E e : arr) {}
}
<T extends Comparable> T max(T... arr) {
return Arrays.stream(arr).max((a, b) -> a.compareTo(b)).get();
}
interface class List<E> extends Collection<E> {
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
boolean addAll(Collection<? extends E> c);
}
内部类
- 成员内部类:定义在类的内部的类,通常用于封装外部类的某些功能。它可以直接访问外部类的所有成员,包括私有成员。
Outer ot = new Outer();
Inner in = ot.new Inner();
class Outer {
class Inner {}
}
- 静态内部类:
static
关键字定义的内部类。它不能访问外部类的非静态成员,但可以访问外部类的静态成员。静态内部类的实例不需要外部类的实例。
class Outer {
static class Inner {}
}
- 局部内部类:在一个方法或作用域内定义的类。它只能在定义它的方法或作用域内使用。局部内部类可以访问方法中的局部变量,但这些局部变量必须是 final 或者实际上没有被修改过的。
class Outer {
void method() {
class Inner {}
}
}
- 匿名内部类:匿名内部类是一种没有名字的内部类,通常用于创建类的实例时。它通常用于实现接口或继承类,并且只能在定义时创建一个实例。
class Outer {
Runnable run = new Runnable() {
@Overide
public void run() {}
};
}
- Lambda:v8 引入了 Lambda 表达式,这是一种简洁的语法结构,用于表示匿名函数。Lambda 表达式主要用于简化对函数式接口的实现,特别是在与 Java 8 的流(Streams)API 结合使用时,可以极大地提高代码的可读性和简洁性。
class Outer {
void method () {
Runnable run = () -> {};
Thread t = new Thread(run);
t.start();
}
}
异常
异常处理是一种机制,用于在程序运行时处理错误和异常情况。通过异常处理,程序可以在遇到错误时优雅地恢复或终止执行,而不是直接崩溃。
检查异常(Checked Exceptions):这些异常在编译时必须被处理。如果方法可能抛出检查异常,那么调用该方法的代码必须捕获该异常或在方法签名中声明抛出该异常。(例如:
IOException
、SQLException
等。)非检查异常(Unchecked Exceptions):这些异常在编译时不需要被显式处理,但通常建议进行处理以提高程序的健壮性。非检查异常又分为运行时异常和错误。
- 运行时异常(Runtime Exceptions):例如,
NullPointerException
、ArrayIndexOutOfBoundsException
- 错误(Errors):通常表示严重的系统级问题,如 OutOfMemoryError、StackOverflowError 等。
- 运行时异常(Runtime Exceptions):例如,
常见异常
java.lang.ArrayIndexOutOfBoundsException
java.lang.NullPointerException
java.lang.ArithmeticException
java.lang.MissingResourceException
java.lang.ClassNotFoundException
关键字:throws
、try
、catch
、throw
、finally
try-catch-finally
try {
} catch(Exception e) {
} finally {}
try-with-resources
v7 引入的一个特性,用于自动管理资源,确保在使用完资源后能够正确地关闭资源,而不需要显式调用 close()
方法。这个特性特别适用于那些实现了 AutoCloseable
或 Closeable
接口的资源,如文件流、数据库连接等。
try (InputString is = new InputStream("")) {}
注解
注解(Annotations)是一种特殊的标记机制,用于为代码提供元数据信息。注解本身并不直接改变代码的逻辑,但可以被编译器、运行时环境或第三方工具读取并用于各种目的,如代码生成、编译时检查、运行时行为控制等。
内置注解
@Override
@Overload
@Deprecated
:API 过期警告@suppressWarnings
:抑制警告
元注解
@Target
:使用位置@Retention
:生效阶段,SOURCE、CLASS、RUNTIME@Documented
:指示被注解的注解类型应该被包含在 JavaDoc 文档中@Inherited
:用于指示一个注解类型是否可以被子类继承。当一个注解类型被@Inherited
注解时,如果一个类被该注解标记,那么它的子类也会自动继承这个注解,除非子类显式地被其他注解标记覆盖。@interface
:自定义注解。块中定义方法返回值类型可以是基本类型、class
、String
、enum
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RententionPolicy.RUNTIME)
public @interface CusAnno {
String value() default "";
int no() default -1;
}
@CusAnno(value = "cus anno", no = 1)
class Clz {}
反射
反射(Reflection)是一种强大的机制,允许程序在运行时动态地访问和操作类、接口、字段、方法等。通过反射,你可以在运行时获取类的信息、创建对象、调用方法、访问字段等,而不需要在编译时就确定这些信息。
类加载完后,在方法区中会存储一个相应的Class
对象(一个类只有一个Class
对象),包含了整个类的完整信息。Reflection API
(java.lang.reflect
)可以获取任何类的内部信息,并且能直接操作任意对象的内部属性及方法。
通常编码思路:类加载、实例化、操作实例
反射编码思路:类加载、获取类实例、实例化、操作实例
主要功能:
- 获取类的名称、包信息、修饰符等。获取类的构造方法、字段、方法、接口等。
- 动态地创建类的实例对象。
- 动态地调用对象的方法,无论方法的访问权限如何。
- 访问字段动态地访问和修改对象的字段值,即使字段是私有的。
- Class
Class<String> clz = Class.forName("java.lang.String");
Class<Clz> clz = Clz.class;
Class clz = clz.getClass();
- 类型
// class
Class cls = Object.class;
// interface
Class cls = Runnable.class;
// array
Class cls = int[][].class;
// annotation
Class cls = Override.class;
// enum
Class cls = ElementType.class;
// void
Class cls = void.class;
线程
线程是 Java 并发编程的基础,允许程序在多个任务之间进行并行执行。线程是操作系统能够进行调度和执行的最小单位,它被包含在进程之中,是进程中的一个执行流。Java 提供了多种方式来创建和管理线程,使得并发编程变得更加灵活和高效。
properties
- priority:权重值,CUP优先考虑权重大的线程进行调度。1 ~ 10,默认为 5。
- daemon:线程可分为守护线程和用户线程。虚拟机必须确保用户线程执行完毕,而不用等待守护线程执行完毕,如,后台记录日志、监控内存、垃圾回收。
method
- join:
join()
方法是Thread
类的一个方法,用于等待一个线程完成其执行。当你调用一个线程的join()
方法时,当前线程会暂停执行,直到被调用join()
的线程执行完毕。这个方法通常用于确保某个线程在继续执行其他任务之前已经完成其工作。
Thread t0 = new Thread(() -> {
System.out.println("t0: run");
Thread.sleep(3000);
System.out.println("t0: finish");
});
Thread t1 = new Thread(() -> {
System.out.println("t1: run");
t0.join();
System.out.println("t1: finish");
});
t1.start();
t0.start();
生命周期
NEW:Thread state for a thread which has not yet started.
RUNNABLE:Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
BLOCKED:Thread state for a thread blocked waiting for a monitor lock.
WAITING:Thread state for a waiting thread.
TIMED_WAITING:thread state for a waiting thread with a specified waiting time.
TERMINATED:Thread state for a terminated thread. The thread has completed execution.
java.lang.Thread
class CusThread extend Thread {
@Override
public void run() {}
public static void main(String[] args) {
Thread t = new CusThread();
t.start();
}
}
java.lang.Runnable
void method() {
Runnable rn = () -> {};
Thread t = Thread(rn);
t.start();
}
java.util.concurrent.Callable
void method() {
Callable<Integer> cal = () -> 0;
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> ft = excutor.submit(cal);
Integer val = ft.get();
}