泛型与枚举
学习内容
枚举
枚举就是一个常量集合,规定某个类中的对象(枚举值) 个数(这个对象是被public static final修饰的),例如:季节(春/夏/秋/东)、星期(星期一到星期日)等
声明枚举
[修饰符列表] enum 枚举名 {类体}
阿里规约
【参考】枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
此处以声明SeasonEnum为例
package com.jsoft.enumdemo;
public enum SeasonEnum {
// 枚举对象 -----> 必须在类体最上面
SPRING(1,"春天"),
SUMMER(2,"夏天"),
AUTUMN(3,"秋天"),
WINTER(); // -----> 此处的“()”可以省略
// 构造器
SeasonEnum() {}
SeasonEnum(int code, String name) {
this.code = code;
this.name = name;
}
// 属性
private int code;
private String name;
// Getter Setter
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
-
枚举类中枚举对象放必须在类体的最前面
-
枚举类中枚举对象(枚举值)都是被public static final修饰的,是常量,规范要求命名大写
-
枚举类中的枚举对象之间以",“分割,并且最后一个枚举对象以”;"结尾
-
枚举类中构造器都是私有的,并且可以省略“private”
-
枚举类中可以有Getter/Setter方法
-
枚举类中枚举对象如果是无参的可以省略“()”
上面的代码经过反编译后结果是这样的,可以看出
SPRING(1,“春天”);,–对应–> public static finalSeasonEnum SPRING = new (1,“春天”);
枚举的静态导入
import static 全类名.枚举对象名/通配符(*)
为什么要静态导入枚举? ——> 对枚举使用静态导入可以省略"枚举类.",直接使用枚举对象
package com.jsoft.enumdemo;
// 枚举的静态导入
import static com.jsoft.enumdemo.SeasonEnum.*;
public class Test {
public static void main(String[] args) {
SeasonEnum season1 = SeasonEnum.AUTUMN;
// 对枚举使用静态导入可以省略枚举类,直接使用枚举对象
SeasonEnum season2 = AUTUMN;
}
}
枚举的应用
枚举应用在switch分支中(java5新特性)
package com.jsoft.enumdemo;
import static com.jsoft.enumdemo.SeasonEnum.*;
public class Test {
public static void main(String[] args) {
SeasonEnum season = AUTUMN;
switch (season) {
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
default:
}
}
}
使用枚举类实现单例模式
待补充。。。
枚举值的比较
因为枚举类中都是常量(静态常量),所以对枚举进行等值比较时建议 使用“==”进行比较。
枚举的优势
对于有多种情况的选择时,我们可以使用int类型的常量也可以使用枚举,那么枚举相对int类型有什么优势呢?
- int类型不具备安全性。假如程序员在声明变量时手一哆嗦,少写了final,该变量会存在被他人修改的风险;而枚举类天然就是一个常量类,不存在失误的情况
- 使用int类型,语义不够明确。
泛型
什么是泛型
- 泛型是Java5引入的新特性,泛型提供了类型安全检测机制,此机制在程序员编译时检测非法类型
- 泛型的本质就是参数化类型,也即是说将所操作的类型被指定为一个参数
- 泛型是一种将数据类型确定推迟到创建对象、调用方法时才明确的特殊类型
- 泛型只能指定引用数据类型,不能指定原始类型(基本数据类型)
- 泛型修饰的类、方法、接口分别称为泛型类、泛型方法、泛型接口
使用泛型的好处
1.使用泛型这种机制,使集合中的元素类型统一了
2.使用泛型这种机制,从集合中取出的元素是泛型指定的类型,不需要进行大量的向下转型
泛型的缺点
- 缺乏多样性
泛型的应用场景
- 父类(接口),起到的是一个规范的作用,对里面的数据类型是没有明确要求的
- 容器类(超级数组,链表、队列、栈)
- 当类型无法确定时,使用泛型
泛型修饰的成员
泛型类
语法格式:[修饰符列表] class 类名<标识符> {类体}
具体案例如下
package com.jsoft.generics;
public class Test<T> {
public T method(T t) {
return t;
}
public static void main(String[] args) {
Test<String> test = new Test<>();
System.out.println(test.method("我是泛型类中的方法,不是泛型方法"));
}
}
泛型方法
语法格式:[修饰符列表] <标识符> 返回值类型 方法名(参数列表) {方法体}
如果我们只关心方法,可以不定义泛型类,只定义泛型方法
泛型方法是不是一定要在泛型类里: 不是
泛型类中是不是一定要有泛型方法:不是
使用泛型方法,最好要结合返回值,否则和Object一样
有人可能会问了,我可以直接使用泛型类完成对方法类型的确定,但为什么还需要用到泛型类呢?我们来看下面的一个例子
package com.jsoft.generics;
public class Test<T> {
public T method(T t) {
return t;
}
public static void main(String[] args) {
// 我们需要指定方法类型为String
Test<String> test1 = new Test<>();
String str = test1.method("1");
// 我们需要指定方法类型为Integer类型
Test<Integer> test2 = new Test<>();
Integer integer = test2.method(1);
// 我们需要指定方法类型为Double类型
Test<Double> test3 = new Test<>();
Double doubleVal = test3.method(1.0);
}
}
通过上面的代码可以看出,通过泛型类的方式我们想要指定方法不同类型需要创建多个对象,代码显的十分冗余。那么上面的代码能继续简化么,请看下面的代码(使用泛型方法)
package com.jsoft.generics;
public class Test {
// 泛型方法
public <T> T method(T t) {
return t;
}
public static void main(String[] args) {
Test test = new Test();
// 指定String类型
System.out.println(test.method("1"));
// 指定Integer类型
System.out.println(test.method(1));
// 指定Double类型
System.out.println(test.method(1.0));
}
}
静态泛型方法
静态方法如果时泛型方法,泛型的声明必须写 因为静态结构是属于类的,不属于某个对象那个
泛型接口
语法格式:[修饰符列表] interface 接口名<标识符> {类体}
泛型方法与泛型类关系
- 如果一个泛型类中,尽量不要在使用泛型方法
- 泛型方法多数都是出现在非泛型类中
继承关系中的泛型
泛型类在继承时:
- 父类是一个泛型类,子类要不要是泛型类? 随便
- 在子类继承父类时,子类泛型和父类泛型都写出来的情况下,父跟子
- 如果在继承时,没有写出任何泛型,当前子类就不是泛型类
- 在继承关系中,如果需要,父类和子类都需要指定泛型
在Java7开始,可以省略等号右边的泛型的声明,<>必须得写(规范)
通配符
泛型中的通配符用"?"表示,
类型擦除
为了兼容性,使用原始类型(没有泛型)是可以的。泛型刚刚出现的时候,还存在大量的不适用泛型的代码,保证代码的兼容性,将参数化类型的实例传递给设计用于原始类型的方法必须,为例保持兼容性,Java泛型中,其实有一种类似伪泛型,因为Java在编译期间所有的泛型都会被擦掉Java的泛型语法是在编译期这个维度上实现,正常来书在生成第字节码文件中,不包含泛型的类型信息的,在JVM中,由泛型附加的类型信息对JVM是看不到的,可以理解为,泛型的本质是让程序员在编写代码时遵守的一个规则