Java常见语法知识
List和ArrayList
List是接口,ArrayList是实现类,List还有其他实现类(如LinkedList、Vector)
List的List
正确:
1 | List<List<Integer>> edges; |
在力扣编程中编写了下列代码:
1 | List<List<Integer>> edges; |
这是错误的,因为如果运行的话,java编译的时候看左边edges是List<List<Integer>>类型,那么后续假如运行edges.add(new LinkedList<Integer>)会报错,但实际上edges里面是ArrayList<Integer>。
所以编译器禁止List<List<Integer>> edges = new ArrayList<ArrayList<Integer>>(); // 编译错误,
遍历String并获取字符相对于a的位数
1 | String str = "helloworld"; // 示例字符串(全小写字母) |
- charAt()
- 相对位数:
c - 'a'
增强for循环遍历:
1 | String str = "abcxyz"; |
- toCharArray()
length、length()、size()等长度
length(): String类型的长度。
1 | String str = "abcxyz"; |
length: int数组的长度
1 | int[] answer; |
size():ArrayList的长度、Stack(Deque)
1 | List<Integer> route = new ArrayList<>(); |
length——数组的属性;
length()——String的方法;
size()——集合的方法;
变量初始值
在java中,成员变量(类中声明的变量)会被自动赋予默认值,而局部变量(方法内部声明的变量)不会自动初始化,必须显式赋值后才能使用(否则编译报错)。
- 成员变量分为静态变量和实例变量。
- 实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。
- 静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
| 类型 | 未赋值时的默认值 |
|---|---|
byte |
0 |
short |
0 |
int |
0 |
long |
0L |
float |
0.0f |
double |
0.0d |
char |
'\u0000' |
boolean |
false |
引用类型变量为null。
力扣中少用static
https://leetcode.cn/problems/implement-trie-prefix-tree/description/?envType=study-plan-v2&envId=top-100-liked
力扣在运行多个测试用例时,会创建多个 Trie
实例。如果使用静态变量,前一个测试用例的数据会污染后一个测试用例,导致结果错误。
简单总结:在面向对象编程中,除非确实需要共享数据,否则应该使用实例变量而不是静态变量。
ArrayList常见api
- 修改元素:
set(int index, E element) - 删除元素:
remove(int index) - 大小:
size() - 判断是否存在:
contains() - 排序:
Collections.sort(list) - 访问某个元素:
get(i) - 用于删除动态数组中的所有元素,使列表的大小变为
0:
clear()
引用传递和对象复制
问题代码:
1 | class Solution { |
Java 中列表是引用类型,直接使用
answer.add(tmp) 存储的是 tmp
对象的引用,而不是当前 tmp 中的内容快照。
问题根源:引用传递的特性
在你的代码中,tmp 是一个全局的
List<Integer>
对象,整个回溯过程中始终是同一个对象(只是不断添加 / 删除元素)。
当你执行 answer.add(tmp) 时,本质是把 tmp
的引用地址添加到了 answer
中。而回溯过程中,tmp 会继续被修改(比如
tmp.remove(...)),这会导致 answer
中所有之前添加的 “排列” 都跟着一起变化(因为它们指向同一个
tmp 对象)。
最终,当回溯完成后,tmp
会回到空列表状态,answer
中存储的所有引用都会指向这个空列表,导致结果错误。
为什么 answer.add(new ArrayList<>(tmp))
能解决问题?
new ArrayList<>(tmp)
会创建一个新的列表对象,并将当前 tmp
中的所有元素复制到这个新对象中。此时添加到 answer
中的是新对象的引用,后续对 tmp
的修改不会影响这个新对象。
这样,answer 中存储的就是回溯过程中 tmp
在不同阶段的内容快照,最终能正确保留所有排列结果。
总结
- 引用类型变量存储的是对象的地址,直接添加引用会导致后续修改影响已存储的内容。
- 通过
new ArrayList<>(tmp)创建新对象并复制内容,能确保每个排列结果被独立保存,不受后续回溯操作的影响。
表示几次方
math.pow(a, b);
位运算
1 | // ==================== 基本位运算符 ==================== |
StringBuilder的API
String的API
子串是substring(),都是小写
Stack的API
在Java中,我们用Deque可以实现Stack的功能:
初始化:
Deque<Integer> stack = new LinkedList<>();把元素压栈:
push(E)/addFirst(E)把栈顶的元素“弹出”:
pop()/removeFirst()取栈顶元素但不弹出:
peek()/peekFirst()大小:
size()
小顶堆/大顶堆的API
1 | // 默认小顶堆 |
添加元素:
offer()移除并返回队头:
poll()查看队头:
peek()
字符转数字
错误写法:
1 | String digits = "23"; |
正确写法:
1 | int x = digits.charAt(0) - '0'; // 字符转数字(如 '2' - '0' = 2) |
Boolean和boolean
boolean(基本类型)
- 只有两个值:
true或false - 不能为
null - 默认值为
false
Boolean(包装类)
- 有三个可能值:
true、false、null
数学运算
开根号:Math.sqrt(a)或Math.pow(a, 0.5)
数组复制
Arrays.copyOf()
1 | // 原数组 |
参数传递
Java中传递引用数据类型的时候也是值传递。(复制的是引用数据类型的地址)
1 | public boolean isPalindrome(ListNode head) { |




