枚举类型(enum type)是指由一组固定的常量组成合法的类型。Java 中由关键字enum 来定义一个枚举类型
Java 定义枚举类型的语句有以下特点:
1) 使用关键字 enum ;
2) 类型名称,比如这里的 Season ;
3) 一串允许的值,
4) 枚举可以单独定义在一个文件中,也可以嵌在其它 Java 类中;
5) 枚举可以实现一个或多个接口(Interface);
6) 可以定义新的变量 ;
7) 可以定义新的方法;
8) 可以定义根据具体枚举值而相异的类
enum 就和 class 一样,只是一个关键字,他并不是一个类; 当我们使用 enmu 来定义一个枚举类型的时候,编译器会自动帮我们创建一个 final类型的类继承 Enum 类,所以枚举类型不能被继承
java 枚举值比较用双等于号和 equals 方法没啥区别,两个随便用都是一样的效果。
因为 enum 类型的每个常量在JVM中只有一个唯一实例; 枚举 Enum 类的 equals 方法默认实现就是通过 == 来比较的;
枚举类可以应用在 switch 语句中。因为枚举类天生具有类型信息和有限个枚举常量,所以比 int 、 String 类型更适合用在 switch 语句中.
Java 泛型( generics) 是 JDK 5 中引⼊的⼀个新特性, 允许在定义类和接口的时候使⽤类型参数( type parameter) 。
声明的类型参数在使⽤时⽤具体的类型来替换
泛型最⼤的好处是可以提⾼代码的复⽤性。 以 List 接⼜为例,我们可以将 String、Integer 等类型放⼊List 中, 如不⽤泛型, 存放 String 类型要写⼀个 List 接口, 存放Integer 要写另外⼀个 List 接口, 泛型可以很好的解决这个问题;
泛型就是定义一种模板,例如 ArrayList<T> ,然后在代码中为用到的类创建对应的 ArrayList<类型>;,既实现了编写一次,万能匹配,又通过编译器保证了类型安全;
类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。
类型擦除的主要过程如下:
将所有的泛型参数用其最左边界(最顶级的父类型)类型替换 移除所有的类型参数。
通配符分为限定通配符和非限定通配符
表示类型的上界,格式为:<? extends T>,即类型必须为 T 类型或者 T 子类 <? extends T> 允许调用读方法 T get() 获取 T 的引用,但不允许调用写方法 set(T) 传入 T 的引用(传入 null 除外) 表示类型的下界,格式为:<? super T>,即类型必须为 T 类型或者 T 的父类 <? super T> 允许调用写方法 set(T) 传入 T 的引用,但不允许调用读方法 Tget() 获取 T 的引用(获取 Object 除外)。
泛型中 K T V E ?的含义
E - Element (在集合中使用,因为集合中存放的是元素) T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的 java 类型(无限制通配符类型)
S、U、V - 2nd、3rd、4th types
List<Object>和原始类型 List 之间的区别
原始类型 List 和带参数类型 List<Object>之间的主要区别是,在编译时编译器不会对原始类型进行类型安全检查,却会对带参数的类型进行检查。通过使用 Object 作为类型,可以告知编译器该方法可以接受任何类型的对象,比如String 或 Integer。 它们之间的第二点区别是,你可以把任何带参数的类型传递给原始类型 List,但却不能把 List<String>传递给接受 List<Object>的方法,因为会产生编译错误
List<?>和 List<Object>之间的区别是什么?
List<?> 是一个未知类型的 List,而 List<Object> 其实是任意类型的 List。你可以把List<String>, List<Integer>赋值给 List<?>,却不能把 List<String>赋值给 List<Object>
注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”:注解可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。
Java的注解可以分为三类:
> @SuppressWarnings :告诉编译器忽略此处代码产生的警告。
这类注解不会被编译进入 .class 文件,它们在编译后就被编译器扔掉了。
定义一个注解时,还可以定义配置参数。配置参数可以包括:
所有基本类型; String; 枚举类型; 基本类型、String以及枚举的数组。
因为配置参数必须是常量,所以,上述限制保证了注解在定义时就已经确定了每个参数的值。
Java语言使用 @interface 语法来定义注解( Annotation )
package com.demo;
//定义一个注解
public @interface Report {
int type() default 0; //无参方法 有默认值
String level() default "0";
String value() default "";
}
注解的参数类似无参数方法,可以用 default 设定一个默认值(强烈推荐)。最常用的参数应当命名为 value 。
有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)。Java标准库已经定义了一些元注解,我们只需要使用元注解,通常不需要自己去编写元注解。
package com.demo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 最常用的元注解是 @Target 。使用 @Target 可以定义 Annotation 能够被应用于源码的哪些位
* 置:
* 类或接口: ElementType.TYPE ;
* 字段: ElementType.FIELD ;
* 方法: ElementType.METHOD ;
* 构造方法: ElementType.CONSTRUCTOR ;
* 方法参数: ElementType.PARAMETER 。
*
* 另一个重要的元注解 @Retention 定义了 Annotation 的生命周期:
* 仅编译期: RetentionPolicy.SOURCE ;
* 仅class文件: RetentionPolicy.CLASS ;
* 运行期: RetentionPolicy.RUNTIME 。
* 如果 @Retention 不存在,则该 Annotation 默认为 CLASS 。因为通常我们自定义
* 的 Annotation 都是 RUNTIME ,所以,务必要加
* 上 @Retention(RetentionPolicy.RUNTIME) 这个元注解
* */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Report {
int type() default 0; //无参方法 有默认值
String level() default "0";
String value() default "";
}
@Target 定义的 value 是 ElementType[] 数组,只有一个元素时,可以省略数组的写法。
定义 Annotation 的步骤:
注解定义后也是一种 class ,所有的注解都继承自java.lang.annotation.Annotation ,因此,读取注解,需要使用反射API;
Java提供的使用反射API读取 Annotation 的方法包括:
判断某个注解是否存在于 Class 、 Field 、 Method 或 Constructor :
Class.isAnnotationPresent(Class) Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
使用反射API读取Annotation:
Class.getAnnotation(Class) Field.getAnnotation(Class)
Method.getAnnotation(Class)
Constructor.getAnnotation(Class)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。