该备忘单是针对 Java 初学者的速成课程,有助于复习 Java 语言的基本语法。
String first = "John";
String last = "Doe";
String name = first + " " + last;
System.out.println(name);
查看: Strings
String word = "QuickRef";
for (char c: word.toCharArray()) {
System.out.print(c + "-");
}
// 输出: Q-u-i-c-k-R-e-f-
查看: Loops
char[] chars = new char[10];
chars[0] = 'a';
chars[1] = 'b';
String[] letters = {"A", "B", "C"};
int[] mylist = {100, 200};
boolean[] answers = {true, false};
查看: Arrays
StringBuilder sb = new StringBuilder(10);
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
| | | | | | | | | |
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5 6 7 8 9
sb.append("Reference");
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
| R | e | f | e | r | e | n | c | e |
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5 6 7 8 9
sb.delete(3, 9);
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
| R | e | f | | | | | | |
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5 6 7 8 9
sb.insert(0, "My ");
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
| M | y | | R | e | f | | | |
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5 6 7 8 9
sb.append("!");
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
| M | y | | R | e | f | ! | | |
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5 6 7 8 9
int[][] matrix = {{1, 2, 3}, {4, 5}, {6}};
int x = matrix[1][0]; // 4
System.out.println(Arrays.deepToString(matrix));
// 输出: [[1, 2, 3], [4, 5], [6]]
for (int i = 0; i < matrix.length; ++i) {
for(int j = 0; j < matrix[i].length; ++j) {
System.out.println(matrix[i][j]);
}
}
// 输出: 1 2 3 4 5 6
+ (加法运算符(也用于字符串连接))- (减法运算符)* (乘法运算符)/ (分区运算符)% (余数运算符)= (简单赋值运算符)++ (增量运算符;将值增加 1)-- (递减运算符;将值减 1)! (逻辑补码运算符;反转布尔值)== (等于)!= (不等于)> (比...更棒)>= (大于或等于)< (少于)<= (小于或等于)&& 条件与|| 条件或instanceof (将对象与指定类型进行比较)~ (一元按位补码)<< (签名左移)>> (有符号右移)>>> (无符号右移)& (按位与)^ (按位异或)| (按位包含 OR)public Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println("eat something");
}
}
// Dog类继承Animal类
public Dog extends Animal {
// 调用父类的构造函数
public Dog(String name){
super(name);
}
}
请注意Java不支持多继承,只能够单继承,但支持多重继承 即,一个类最多只有一个父类,但可以有爷爷类和太爷爷类
super引用当前类的父类 this引用自身
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
被final 关键字修饰的类不能够被继承 被final 关键字修饰的方法不能被子类重写
重写者位于被重写者的子类中 重写者的签名必须与被重写者的签名相同
class Animal {
// 被重写者
void say(String sentence) {
System.out.println("Animal say: " + sentence);
}
}
class Dog extends Animal {
// 重写者
// 重写者位于被重写者的子类 重写一般需要添加 @Override 注解
@Override
void say(String sentence) { // 签名与被重写者相同
System.out.println("Dog say: " + sentence);
}
}
重载位于同一类内部 签名必须不同
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a) {
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
}
抽象类不能被实例化为对象,因此,抽象类必须被继承才能够使用 抽象类使用abstract 关键字进行修饰
public abstract class Animal {
String name;
public Animal(String name) {
this.name = name;
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
}
使用abstract 关键字修饰的方法是抽象方法 抽象方法必须包含在抽象类中 子类必须重写父类中的所有抽象方法,除非子类也是抽象类
public abstract class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public abstract void say();
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void say(){
System.out.println("Dog");
}
}
与类的继承不同,接口可以继承多个接口
[可见性修饰符] interface 接口名称 [extends 其他接口名列表] {
// 声明变量
// 抽象方法
}
一个类可以实现多个接口 类必须实现接口的所有方法,除非该类是抽象类
public interface Animal {
public void eat();
public void say();
}
public class Dog implements Animal {
public void eat() {
System.out.println("Dog eat something");
}
public void say() {
System.out.println("Dog say something");
}
}
// 实现Runnable接口
public class RunnableThread implements Runnable {
@Override
public void run() {
// todo something
}
}
实现Callable接口,T 替换成实际类型
public class CallableTask implements Callable<T> {
@Override
public T call() throws Exception {
// todo something
return null;
}
}
继承Thrad类
public class ExtendsThread extends Thread {
@Override
public void run() {
// todo something
}
}
运行线程
public static void main(String[] args) throws ExecutionException, InterruptedException {
new Thread(new RunnableThread()).start();
new ExtendsThread().start();
FutureTask<Integer> integerFutureTask = new FutureTask<>(new CallableTask());
integerFutureTask.run();
}
ThreadPoolExecutor threadPoolExecutor
= new ThreadPoolExecutor(
2, 5,
5, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
new DefaultThreadFactory("pollName"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 内置的线程池, 不推荐生产使用
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(10);
Executors.newScheduledThreadPool(10);
Executors.newSingleThreadExecutor();
// CountDownLatch
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(() -> {
try {
...
}finally {
countDownLatch.countDown();
}
}).start();
countDownLatch.await();
CompletableFuture
CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {});
CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {});
CompletableFuture<Void> task3 = CompletableFuture.runAsync(() -> {});
CompletableFuture.allOf(task1, task2, task3).get();
Semaphore
Semaphore semaphore = new Semaphore(5);
try {
semaphore.acquire();
} finally {
semaphore.release();
}
// 需要synchronized修饰的代码块才能使用
wait();
notify();
notifyAll();
// 使用lock的条件唤醒
ReentrantLock lock = new ReentrantLock();
Condition condition= lock.newCondition();
lock.lock();
try{
// 当前线程唤醒或等待
condition.await();
condition.signal();
condition.signalAll();
} finally {
lock.unlock();
}
// LockSupport,可以先unpark,后续park不会阻塞线程
LockSupport.park(obj);
LockSupport.unpark(thread);
| 集合 | Interface | 有序 | 已排序 | 线程安全 | 复制 | Nullable |
|---|---|---|---|---|---|---|
| ArrayList | List | Y | N | N | Y | Y |
| Vector | List | Y | N | Y | Y | Y |
| LinkedList | List, Deque | Y | N | N | Y | Y |
| CopyOnWriteArrayList | List | Y | N | Y | Y | Y |
| HashSet | Set | N | N | N | N | One null |
| LinkedHashSet | Set | Y | N | N | N | One null |
| TreeSet | Set | Y | Y | N | N | N |
| CopyOnWriteArraySet | Set | Y | N | Y | N | One null |
| ConcurrentSkipListSet | Set | Y | Y | Y | N | N |
| HashMap | Map | N | N | N | N (key) | One null (key) |
| Hashtable | Map | N | N | Y | N (key) | N (key) |
| LinkedHashMap | Map | Y | N | N | N (key) | One null (key) |
| TreeMap | Map | Y | Y | N | N (key) | N (key) |
| ConcurrentHashMap | Map | N | N | Y | N (key) | N |
| ConcurrentSkipListMap | Map | Y | Y | Y | N (key) | N |
| ArrayDeque | Deque | Y | N | N | Y | N |
| PriorityQueue | Queue | Y | N | N | Y | N |
| ConcurrentLinkedQueue | Queue | Y | N | Y | Y | N |
| ConcurrentLinkedDeque | Deque | Y | N | Y | Y | N |
| ArrayBlockingQueue | Queue | Y | N | Y | Y | N |
| LinkedBlockingDeque | Deque | Y | N | Y | Y | N |
| PriorityBlockingQueue | Queue | Y | N | Y | Y | N |
List<Integer> nums = new ArrayList<>();
// 添加
nums.add(2);
nums.add(5);
nums.add(8);
// 检索
System.out.println(nums.get(0));
// 为循环迭代编制索引
for (int i = 0; i < nums.size(); i++) {
System.out.println(nums.get(i));
}
nums.remove(nums.size() - 1);
nums.remove(0); // 较慢,因为需要移动后续元素
for (Integer value : nums) {
System.out.println(value);
}
// lambda 打印元素
nums.forEach(
e -> System.out.println(e.toString())
);
Set<String> set = new HashSet<>();
if (set.isEmpty()) {
System.out.println("Empty!");
}
set.add("dog");
set.add("cat");
set.add("mouse");
set.add("snake");
set.add("bear");
if (set.contains("cat")) {
System.out.println("Contains cat");
}
set.remove("cat");
for (String element : set) {
System.out.println(element);
}
set.forEach(
e -> System.out.println(e.toString())
);
字节流
InputStream 字节输入流的抽象基类FileInputStream 从文件中读取字节的输入流ByteArrayInputStream 从字节数组中读取字节的输入流OutputStream 字节输出流的抽象基类FileOutputStream 向文件中写入字节的输出流ByteArrayOutputStream 将字节写入到字节数组的输出流字符流
Reader 字符输入流的抽象基类FileReader 从文件中读取字符的输入流BufferedReader 带缓冲区的字符输入流InputStreamReader 字节流到字符流的桥接器Writer 字符输出流的抽象基类FileWriter 向文件中写入字符的输出流BufferedWriter 带缓冲区的字符输出流OutputStreamWriter 字符流到字节流的桥接器对象流
ObjectInputStream 从输入流中读取Java对象的流ObjectOutputStream 将Java对象写入输出流的流缓冲流
BufferedInputStream 带缓冲区的字节输入流BufferedOutputStream 带缓冲区的字节输出流BufferedReader 带缓冲区的字符输入流BufferedWriter 带缓冲区的字符输出流数据流
DataInputStream 从输入流中读取基本数据类型的数据DataOutputStream 将基本数据类型数据写入输出流文件类
File 文件和目录路径名的抽象表示FileReader 从文件中读取字符的输入流FileWriter 向文件中写入字符的输出流输入输出异常处理
IOException Java I/O操作中的通用异常FileNotFoundException 当试图打开指定文件失败时抛出EOFException 在尝试读取流的末尾时抛出其他流
PrintStream 打印格式化表示的对象的输出流PrintWriter 格式化的文本输出流RandomAccessFile 随机访问文件的类,支持读取和写入操作// 文件输入流 (注意:需要手动关闭或使用 try-with-resources)
InputStream inputStream
= new FileInputStream("input.txt");
// 文件输出流 (注意:需要手动关闭或使用 try-with-resources)
OutputStream outputStream
= new FileOutputStream("output.txt");
// 缓冲字节输入流
InputStream bufferedInputStream
= new BufferedInputStream(inputStream);
// 缓冲字节输出流
OutputStream bufferedOutputStream
= new BufferedOutputStream(outputStream);
// 文件字符输入流
Reader fileReader
= new FileReader("input.txt");
// 文件字符输出流
Writer fileWriter
= new FileWriter("output.txt");
// 缓冲字符输入流
Reader bufferedFileReader
= new BufferedReader(
new FileReader("input.txt")
);
// 缓冲字符输出流
Writer bufferedFileWriter
= new BufferedWriter(
new FileWriter("output.txt")
);
序列化对象到文件
try (
ObjectOutputStream objectOutputStream
= new ObjectOutputStream(new FileOutputStream("object.dat"))
) {
objectOutputStream.writeObject(object);
}
从文件反序列化对象
try (
ObjectInputStream objectInputStream
= new ObjectInputStream(new FileInputStream("object.dat"))
) {
Object object = objectInputStream.readObject();
}
从集合创建流
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> streamFromList = list.stream();
从数组创建流
String[] array = {"d", "e", "f"};
Stream<String> streamFromArray = Arrays.stream(array);
创建空流
Stream<String> emptyStream = Stream.empty();
创建无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
// 过滤
Stream<String> filteredStream = list.stream().filter(
s -> s.startsWith("a")
);
// 映射
Stream<Integer> mappedStream = list.stream().map(String::length);
// 排序
Stream<String> sortedStream = list.stream().sorted();
// 去重
Stream<String> distinctStream = list.stream().distinct();
// 截断
Stream<String> limitedStream = list.stream().limit(2);
// 跳过
Stream<String> skippedStream = list.stream().skip(1);
// 聚合操作
Optional<String> anyElement = list.stream().findAny();
Optional<String> firstElement = list.stream().findFirst();
long count = list.stream().count();
Optional<String> maxElement = list.stream()
.max(Comparator.naturalOrder());
Optional<String> minElement = list.stream()
.min(Comparator.naturalOrder());
// 检查匹配
boolean anyMatch = list.stream().anyMatch(s -> s.contains("a"));
boolean allMatch = list.stream().allMatch(s -> s.length() == 1);
boolean noneMatch = list.stream().noneMatch(s -> s.contains("z"));
// 归约
Optional<String> reducedString = list.stream()
.reduce((s1, s2) -> s1 + s2);
String reducedStringWithIdentity = list.stream()
.reduce("Start:", (s1, s2) -> s1 + s2);
// 收集
List<String> collectedList = list.stream()
.collect(Collectors.toList());
Set<String> collectedSet = list.stream()
.collect(Collectors.toSet());
Map<Integer, String> collectedMap = list.stream()
.collect(
Collectors.toMap(String::length, Function.identity())
);
// 判断是否是数组、枚举、注解等
boolean isArray = clazz.isArray();
boolean isEnum = clazz.isEnum();
boolean isAnnotation = clazz.isAnnotation();
// 获取构造函数、字段、方法等
Constructor<?>[] constructors = clazz.getConstructors();
Field[] fields = clazz.getDeclaredFields();
Method[] methods = clazz.getDeclaredMethods();
Java 的 Consumer 接口里的 accept 方法接受参数但不返回值。要让它打印传入的参数,可以这样做:
Consumer<String> test = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
test.accept("test");
更简单的,我们可以直接传入Lambda表达式
Consumer<String> test = System.out::println;
方法引用通过方法的名字指向一个方法,使语言构造更简洁,减少冗余代码。
String text = "I am learning Java";
// 删除所有空格
text.replaceAll("\\s+", "");
// 拆分字符串
text.split("\\|");
text.split(Pattern.quote("|"));
查看: Regex in java
ArrayDeque: 可调整大小的数组双端队列,实现了Deque接口Arrays: 提供操作数组的静态方法,如排序、搜索、比较等Collections: 包含操作集合或返回集合的静态方法Date: 表示特定时间瞬间,精度为毫秒Dictionary: 抽象父类,可用于键值对映射,例如HashtableEnumMap: 专门用于枚举键的Map实现EnumSet: 专门用于枚举键的Set实现Formatter: 提供对布局、对齐、数字、字符串和日期/时间数据的格式化支持,以及特定于语言环境的输出SecureRandom: 生成安全的伪随机数流的实例UUID: 表示不可变的通用唯一标识符Vector: 实现了可增长的对象数组LocalDate: 表示无时区的日期,仅包含年月日,不可变且线程安全,适用于Java 8及更高版本LocalTime: 表示无时区的时间,仅包含时分秒,不可变且线程安全,适用于Java 8及更高版本LocalDateTime: 表示无时区的日期时间,包含年月日时分秒,不可变且线程安全,适用于Java 8及更高版本String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "123456";
String sql = "SELECT 1 as a, '2' as b";
String preparedSql = "SELECT * FROM t_user WHERE id = ?";
Connection conn = null;
Statement sm = null;
ResultSet rs = null;
try {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
// 驱动找不到
throw new RuntimeException(e);
}
// 2.建立连接
try (Connection connection = DriverManager.getConnection(url, user, password)) {
conn = connection;
// 3.创建Statement对象
try (Statement statement = connection.createStatement()) {
sm = statement;
// 4.执行SQL语句
try (ResultSet resultSet = statement.executeQuery(sql)) {
rs = resultSet;
// 5.处理结果集
while (resultSet.next()) {
// 按照列名取值
System.out.println(resultSet.getLong("a"));
// 按照索引取值
System.out.println(resultSet.getString(2));
}
}
}
// 3.创建PreparedStatement对象
try (PreparedStatement preparedStatement = connection.prepareStatement(preparedSql)) {
sm = preparedStatement;
preparedStatement.setLong(1, 1_000L);
// 4.执行SQL语句
try (ResultSet resultSet = preparedStatement.executeQuery()) {
rs = resultSet;
// 5.处理结果集
while (resultSet.next()) {
System.out.println(resultSet.getLong("id"));
System.out.println(resultSet.getString(2));
}
}
}
} catch (SQLException e) {
// 数据库异常
throw new RuntimeException(e);
} finally {
// 6.关闭资源
// 上面的try块里已经自动关闭,否则(JDK 7以前)按照以下顺序关闭
// 先打开的后关闭,后打开的先关闭
if (null != rs) {
try {
rs.close();
} catch (SQLException ignored) {
}
}
if (null != sm) {
try {
sm.close();
} catch (SQLException ignored) {
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException ignored) {
}
}
// 也可以直接工具类, 注意顺序
IOUtils.close(rs);
IOUtils.close(sm);
IOUtils.close(conn);
}