静态导入
用于导入类中的静态成员和静态方法,格式如下:
import static java.lang.math.*; // 在当前命名空间导入所有静态字段
import static java.lang.math.PI; // 在当前命名空间导入某一静态字段
静态导入的好处是可以简化书写,弊端是缺少类名作为前缀,不能让人一眼就看出静态方法或静态成员属于哪个类。
可变参数
格式:
int...arr) {}
2、只能出现在参数列表最后;
...位于类型 与 变量名之间;
使用:
在调用可变参数方法时,编译器隐含一个创建数组的动作,数组名为最后一个参数名,在方法体中以数组的形式访问参数:
int getSum(int a, int...arr) {
int sum = a;
for (int i : arr) {
sum += i;
}
return sum;
}
泛型 generic
使用泛型的好处:
1、通过提供额外的类型信息,加强了编译时期的类型检查,将可能在运行时发生的错误提前在编译时期检查出来;
2、避免了类型强转的麻烦。
注意:
1、泛型应用于集合、反射中。
2、数组不能加上泛型信息:List<String>[] 是错误的写法。
3、泛型检查只在编译阶段,编译过后会去除泛型信息,ArrayList<String>和ArrayList<Integer>是同一个类型。所以,可以利用反射机制绕过编译时期对泛型的检查:
// 定义一个实际类型参数为Integer的集合
List<Integer> intList = new ArrayList<>();
// 通过反射机制向集合加入String对象
intList.getClass().getMethod("add", Object.class).invoke(al, "abcd");
通配符 ?
使用了通配符?的集合表示该集合存放的元素未知,?表示未知类型的类。
边界通配符
<? extends T>:表示可以接收T类型或者T的子类型对象。
<? extends T&E>:表示可以接收实现了T接口和E接口的类的子类对象。
<? super T>:表示可以接收T类型或者T的父类型对象。
通配符表示不确定的类型,所以在创建集合时应该明确指定实际的类型参数而不要使用通配符:
List<?> intList = // 使用了通配符
new ArrayList<Integer>();
intList.add(123); // 报错,其实除了null外,不能往intList加入任何元素
泛型类
class Person<T> {
private T obj;
public void set(T obj) {
this.obj = obj;
}
}
当类中的操作的引用数据类型不确定的时候,以前用的Object来进行扩展的,现在可以用泛型来表示。这样可以避免强转的麻烦,而且将运行问题转移到的编译时期。
泛型方法
当方法操作的引用数据类型不确定的时候,可以将泛型定义在方法上。注意,泛型方法标识必需连着返回类型: <T> void。
// 将数组元素添加到集合中
public <T> void copy(Collection<T> col, T[] arr) {
for (T ele : arr) {
col.add(ele);
}
}
另外,静态方法无法访问类上定义的泛型,所以,如果静态方法想使用泛型,必须要将泛型定义在该方法上。
泛型接口
格式与泛型类差不多:interface Comparable<T>{}
枚举类 java.lang.Enum
- enum定义,枚举类与其他类很相似。由于所有的枚举类都继承了Enum,所以枚举类不能再继承其他类了。
- 构造方法隐式地被指定为私有的。
- 枚举常量必须在第一行初始化,常量之间用逗号分隔,如果还有其他成员或者方法,用分号表示枚举常量定义结束。
- Serializable和Comparable<E>接口。
常用方法:
String name() // 获得此枚举常量的名称
int ordinal() // 获得枚举常量的序数,默认第一个枚举常量的序数为 0
Class<E> getDeclaringClass() // 获取枚举类的字节码对象
static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
// 根据名字获得指定类型的枚举常量
一个复杂的枚举类:
enum TrafficLamp {
RED(30) {
public TrafficLamp nextLamp() {
return GREEN;
}
},
GREEN(30) {
public TrafficLamp nextLamp() {
return YELLOW;
}
},
YELLOW(5) {
public TrafficLamp nextLamp() {
return RED;
}
};
int time;
TrafficLamp(int time) {this.time = time;}
public abstract TrafficLamp nextLamp();
}
注解 Annotation
注解是附加在程序上的元信息,这些信息在编译时期或者运行时期可以被使用和解析,通常用于对程序进行说明和配置。
3个内置注解:
@Override:可注解方法,表示被注解的方法打算覆盖父类方法,如果该方法没有覆盖父类方法,编译器会报错。 ——SOURCE周期
@Deprecated:可注解程序中的所有元素,不鼓励程序使用这样的元素。 ——SOURCE周期
@SuppressWarnings:可注解所有元素,通知编译器忽略指定的、掉针对此元素的警告。 ——RUNTIME周期
4个元注解:——可对注解进行注解
@Documented
@Inherited
@Retention
注解的3个保留策略:
SOURCE
CLASS
RUNTIME
@Target:指示注释类型所适用的程序元素的种类。
程序元素的分类:
ANNOTATION_TYPE
CONSTRUCTOR
FIELD
LOCAL_VARIABLE
METHOD
PACKAGE
PARAMETER
TYPE
自定义注解:
@Retention(RetentionPolicy.RUNTIME) // 指示自定义注解的保留策略
@Target(ElementType.METHOD) // 指示自定义注解所适用的元素种类
public @interface MyAnnotation { // 使用关键字 @interface 自定义注解
int[] intMethod(); // 方法名就是参数名,返回类型就是参数的类型
String name() default "hello"; // 使用关键字 default 指定参数的初始值
}