Java基础总结(一)

transient

  • transient会阻止实例中用此关键字声明的变量持久化,当对象被反序列化时,这样的实例变量值是不会被恢复的
  • transient只能修饰变量,不能修饰方法和类,变量如果是自定义类,该类需要实现Serializable接口
  • 一个静态变量不管是否被transient修饰,均不能被序列化(被反序列化后,静态变量的值是JVM中存储的该变量的值)

for..each循环

for...each 原理

for...each是JDK提供的一种语法糖,其实际是通过迭代器来实现遍历的,这也是为什么for...each只能用于数组或实现了Iterable接口的类,如集合

for...each 注意事项

在使用for...each时,不能更改被迭代的对象,否则会抛出ConcurrentModificationException异常,因为for..each的内部原理实质就是使用Iterator迭代器进行迭代,而Iterator是工作在一个独立的线程中,并且拥有一个mutex锁, Iterator被创建之后会建立一个指向原来对象的单链表索引,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,从而抛出异常。

如果使用迭代器迭代集合,是可以使用迭代器自己的remove方法删除集合元素


for (String str : list) {
    //...
}

for (String str : list) {
    list.remove(str); //会抛出ConcurrentModificationException
}

Iterator iter = list.iterator();
while (iter.hasNext()) {
    str = iter.next();
    if (str.equals("")) {
        iter.remove(); //如果使用iterator删除元素,不会抛出异常
    }
}

泛型

类型擦除

Java的泛型都是在编译器的层次实现的,在最终生成的Java字节码中并不包含泛型的类型信息,编译器在编译的时候会取出泛型中的类型参数,这个过程称为泛型擦除,由此引出的泛型的特性有:

  • 泛型类并没有自己独有的Class类对象, 对于List, List它们的Class都是List.class
  • 静态变量被泛型类的所有实例共享, 如果有一个类声明为MyClass, 同时有一个静态变量var, 则访问这个静态变量都是通过MyClass.var, 而不是MyClass.var或MyClass.var
  • 泛型的类型参数不能出现在异常处理的catch语句中

上下界

通配符?表示未知类型, 如List表示List包含的元素是未知的. 不能通过List list = new ArrayList()来创建List对象

可以使用上下界来限制位置类型的范围:

  • List, 表示List中包含的都是MyClass及其子类
  • List, 表示List中包含的都是MyClass及其父类

ArrayList和LinkedList的区别

  • ArrayList底层使用数组实现, LinkedList底层使用双向链表实现

数组的查询和赋值比较快,因为可以直接通过数组下标访问指定位置
链表中删除和增加比较快,因为可以直接通过修改链表的指针进行元素的增删

  • LinkedList和ArrayList相比,增删的速度较快,但是查询和修改至的速度较慢,同时LinkedList还实现了Queue接口,所以还提供了offer(), peek(), poll()等方法

你可能感兴趣的:(Java基础总结(一))