算是一个读书笔记吧,很多知识点不总结很容易忘记,没有什么特别系统和深奥的知识点,我们做安卓开发的,java就是我们的地基之一,温故知新,共勉。
每个特性后面给出Effective java的建议,让我们荡漾在理论的海洋中吧~
本篇主要简述java5的新特性,分别是:
- 泛型
- 枚举
- 注解
- for-each循环
- 自动装箱和自动拆箱
- 可变参数
- 静态导入
- 并发包java.util.concurrent
泛型(Generic Type)
泛型保证了集合的类型安全,没有泛型,从集合中读取的值必须手动进行类型强转,一旦插入类型错误的对象,强转就会出错。有了泛型,编译器预知集合接受的类型,自动进行类型强转,且能在编译时告知是否类型出错。(Effective Java p97 第五章)
概念:泛型类+泛型接口(声明中具有一个或多个类型参数的类或接口)
写法:类名或接口名后跟着<>, 如List<String>
引入概念:
原生态类型:不带任何实际类型参数的泛型名称,如List<E&>对应的原生态类型为List
无限制的通配符类型:用?表示,不确定或不关心实际的类型参数, List<?> 只能添加null,不能添加其他元素
有限的通配符类型:<? extends 具体类型> <? super 具体类型> <? extends 具体类型 & 具体接口类型>
显式的类型说明:在类名和方法名中加一个.<具体类型>
泛型的擦除机制:编译时强化类型,运行时丢弃元素的类型信息。
数组和列表的差异:
- 数组是协变的,列表不是。比如Sub是Super的子类型,则Sub[]是Super[]的子类型,但List<Sub>不是List<Super>的子类型
- 数组是具体化的,列表(除了无限制的通配符类型)是不可具体化的。不可具体化表示运行时包含的信息比编译时少(泛型的擦除机制)
Effective Java的建议
- 请不要在新代码中使用原生态类型,除了类文字(*.class)必须使用, instanceof(泛型的擦除机制)
- 消除非受检警告,无法消除切能证明该警告是类型安全的,可以用@SuppreeWarnings(‘unchecked’)注解来消除,并且范围要尽可能小,同时添加注解,告知原因
- 列表优先于数组(数组和列表的差异)
- 优先考虑泛型
- 优先考虑泛型方法
- 利用有限通配符来提升API的灵活性
- 优先考虑类型安全的异构容器(异构:容器内元素类型不同)
枚举(Enum)
相对于传统的int/string枚举类型,枚举提供了编译时的安全,自动的序列化,是真正的final
概念:由一组常量组成合法值的类型。
引入概念:
位域: 用OR位运算将几个常量合并到一个集合中。
Effective Java的建议
- 用enum代替int常量
- 用实例域代替序数, 永远不要根据枚举的序数导出与它关联的值,最好完全避免使用ordinal方法
- 用EnumSet代替位域,当底层的枚举类型少于等于64个时,整个EnumSet就是用单个long表示,性能堪比位域
- 用EnumMap代替序数索引
- 用接口模拟可伸缩的枚举
注解
注解也被称作元数据,为我们在代码中添加信息提供了一种形式化的方法,使我们可以再稍后某个时刻非常方便的地使用这些数据(Java编程思想 第20章 p620)
java.lang 提供了三个内置注解
@Override 表示当前方法覆盖超类方法
@Deprecated 表示废弃的方法或域
@SuppressWarnings 关闭不当的编译器警告
元注解: java提供四种元注解,专门负责新注解的创建
@Target 定义注解将应用在什么地方。ElementType.METHOD(方法) FIELD(域) LOCAL_VARIAVLE(局部变量) CONSTRUCTIOR(构造器) PACKAGE(包) PARAMETER(参数) TYPE(类,接口,enum)
@Retention 表示在什么级别保存该注解信息。SOURCE(编译器丢弃) CLASS(class可用,被VM丢弃) RUNTIME(运行期也保留,可通过反射机制读取该注解信息)
@Documented 将此注解包含在Javadoc中
@Inherited 允许之类继承父类的注解
例如:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {}
在比如我们在Android中经常用到的注解:
public final class Gender {
@IntDef({MAN, WOMAN, OTHER})
public @interface Type {}
public static final int MAN = 0;
public static final int WOMAN = 1;
public static final int OTHER = 2;
}
接口元素
接口允许的元素类型有:
- 基本类型
- String
- Class
- enum
- Annotation
- 以上类型的数组
元素的默认值有限制,首先不能有不确定的值(要么必须有默认值,要么使用注解时必须提供),其次对于非基本类型元素,不能给null值
语法为:public int id() default -1;
注解处理器
AnnotatedElement接口
- getAnnotation(Class
annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null - getAnnotations() 返回此元素上存在的所有注释。
- getDeclaredAnnotations() 返回直接存在于此元素上的所有注释。
- isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
Effective Java的建议
- 注解优于命名模式(增加错误提示、确保只用于相应元素、参数值与程序元素关联)
- 坚持使用Override注解
- 用标记接口定义类型(标记接口值没有包含方法声明的接口)
for-each循环
这部分就不多说了
Effective Java的建议
- for-each循环优于传统的for循环
自动装箱和自动拆箱
每个基本类型都有对应的引用类型,称为装箱类型。如int的装箱类型为Integer.
主要区别:
- 基本类型只有值,装箱类型具有与它们值不同的同一性。即两个装箱类型值相同,但是可以是不同的同一性。
- 基本类型只有功能完备的值,装箱类型还有个非功能值null
- 基本类型比装箱类型节约时间和空间
Effective Java的建议
- 基本类型优先于装箱基本类型(集合中的键和值,泛型中的参数化类型必须使用装箱基本类型)
可变参数
可变参数方法接受0个或多个指定类型的参数
Effective Java的建议
- 慎用可变参数(可变参数方法的每次调用都会导致进行一次数组分配和数组化)
静态导入(static import)
也没什么好说的 import static xxx;
在大量利用工具类导出的常量时,使用静态导入机制,避免用类名来修饰常量名
并发包java.util.concurrent
这部分限于目前掌握情况,暂时等待补充吧