java 知识点整理--java5新特性(未完)

算是一个读书笔记吧,很多知识点不总结很容易忘记,没有什么特别系统和深奥的知识点,我们做安卓开发的,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

这部分限于目前掌握情况,暂时等待补充吧