通过整理一些 Java 面试题,帮助查漏补缺 Java 相关基础知识
本文使用 JDK1.8 进行测试
经常会有将数组转换为 List 的需求,而常用的方法就是使用 java.util.Arrays
类的 asList
静态方法,所以常常有下面这段代码:
String[] arr = new String[]{"a", "b", "c"};
List<String> list = Arrays.asList(arr);
返回值为 java.util.List
,于是就对返回值进行 add
、 addAll
、 remove
、 removeAll
等操作:
list.add("d");
运行程序时却发现报错如下:
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at java.util.AbstractList.add(AbstractList.java:108)
查看 asList
方法的 API 文档可以看到说明:
Returns a fixed-size list backed by the specified array.
即 asList
方法返回的 List 为固定大小,所以当我们执行会改变 List 元素个数的操作时会抛出异常。如果要深究其原因的话,可以发现 Arrays.asList()
的返回值为一个名为 ArraysList
的静态内部类而不是 java.util.ArrayList
类,该静态内部类继承了 AbstractList
类, AbstractList
类的 add
方法定义如下:
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
同理其 addAll
、 remove
、 removeAll
方法也都是抛出 java.lang.UnsupportedOperationException
异常,又因为 ArrayList
静态内部类并没有重写 AbstractList
类的这些方法,所以会直接调用其父类的方法导致抛出异常。
如果要把数组转换为大小可变的 List 可以通过如下方法解决:
ArrayList<String> list = new ArrayList(Arrays.asList(arr));
list.add("d");
String[] arr = new String[]{"a", "b", "c", "d"};
return Arrays.asList(arr).contains("b");
String[] arr = new String[]{"a", "b", "c", "d"};
Set<String> set = new HashSet<>(Arrays.asList(arr));
return set.contains("b");
String[] arr = new String[]{"a", "b", "c", "d"};
for(String str : arr) {
if(str.equals("c")) {
return true;
}
}
如果使用 Maven 的话需要先导入对应依赖如下:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
String[] arr = new String[]{"a", "b", "c", "d"};
return ArrayUtils.contains(arr, "c");
class Super<T>{
private T t;
public Super(T t){
this.t = t;
System.out.println(t);
}
}
public class Subextends Super{
public Sub(){
System.out.println("sub");
}
public Sub(String s){
System.out.println(s);
}
public static void main(String[] args){
Sub sub = new Sub();
Sub sub2 = new Sub("world");
}
}
Sub 子类的两个构造方法都会出现编译错误,究其原因是因为:
子类的所有构造方法(无论是有参还是无参)都会调用父类的无参构造方法
此处的父类因为已经定义了有参构造方法,导致编译器不再为其提供默认的无参构造方法,所以会导致子类的构造方法报编译错误,可通过以下任意一种方法解决:
public Sub() {
super(3);
System.out.println("sub");
}
public Sub(String s) {
super("hello");
System.out.println(s);
}
final StringBuilder sb = new StringBuilder("hello");
sb.append("world");
程序可正常运行,可见 final
修饰的变量引用的对象可以改变,但引用不可变,所以下面的代码编译错误:
final StringBuilder sb = new StringBuilder("hello");
sb = new StringBuilder("hello world");