> 文档中心 > 泛型和枚举的学习笔记

泛型和枚举的学习笔记


泛型Generic

泛型类

package demo;public class SuperArray<T> {    private Object[] array;    //根据下标查询数字    //当前最后一个数字的下边,要为-1 ,以为数组的第一个下标为0    private int currentIndex = -1;    //构造是初始化    public SuperArray(){ array = new Object[8];    }    //添加数据的方法    public void add(T data){ System.out.println("我是数组的实现!---add"); currentIndex++; //自动扩容 if(currentIndex > array.length-1){     array = dilatation(array); } array[currentIndex] = data;    }    public T get(int index){ System.out.println("我是数组的实现---get"); return (T)array[index];    }    //数组扩容的方法    private Object[] dilatation(Object[] oldArray){ Object[] newArray = new Object[oldArray.length * 2]; for (int i = 0; i < oldArray.length; i++) {     newArray[i] = oldArray[i]; } return newArray;    }    //验证下标是否合法    private boolean validateIndex(int index) { //只要有一个不满足就返回false return index <= currentIndex && index >= 0;    }    public static void main(String[] args) { SuperArray<String> superArray=new SuperArray<>(); superArray.add("123"); superArray.add("456"); System.out.println(superArray.get(1));    }}

在类后加入,使用时声明该泛型是哪个类

泛型方法

package demo;public class Demo1 {    public <T> T show(T t){ System.out.println(t); return t;    }    public static <T> T show2(T t){ System.out.println(t); return t;    }    public static void main(String[] args) { Demo1 demo1 = new Demo1(); Integer show = demo1.show(123); String s = Demo1.show2("123");    }}

方法定义要加入, 最后尽量返回泛型,如果不返回的话,相当于用Object

泛型继承

public interface Comparator<T>{    int compare(T t1,T t2);}
package demo;public class User {    private String name;    private Integer age;    public User() {    }    public User(String name, Integer age) { this.name = name; this.age = age;    }    public String getName() { return name;    }    public void setName(String name) { this.name = name;    }    public Integer getAge() { return age;    }    public void setAge(Integer age) { this.age = age;    }}
package demo;public class UserComparator implements Comparator<User>{    @Override    public int compare(User t1, User t2) { return t1.getAge()- t2.getAge();    }}
package demo;public class Test1 {    public static void main(String[] args) { UserComparator userComparator=new UserComparator();// Comparator userComparator=new UserComparator(); int compare = userComparator.compare(new User("zs", 18), new User("ls", 16)); System.out.println(compare);    }}

明确类型的泛型继承,也可以用不明确类型的,(把UserComparator替换成泛型类)

类型通配符

  • 无界(SuperArray superArray)
  • 上界((SuperArray superArray) dog类及其子类都能放入数组
  • 下界 (SuperArray superArray) dog类及其父类都能放入数组

类型擦除

  • 不能用类型参数替换基本类型。就比如,没有SuperArray,只有SuperArray。因为当类型擦除后,SuperArray的原始类型变为Object,但是Object类型不能存储double值,只能引用Double的值

  • 泛型被擦除后,其实这两个方法是一致的,并不能构成泛型。

    泛型和枚举的学习笔记

  • 类型擦除和多态冲突 虚拟机巧妙的使用了桥方法,来解决了类型擦除和多态的冲突(类型擦除后,JVM自动补充方法把Object方法补充,区分Date的方法,来区分方法调用)

静态方法和静态类中的问题

public class Test2<T> { public static T one;   //编译错误        public static T show(T one){ //编译错误     return null; }    }

因为泛型类中的泛型参数的实例化是在定义对象的时候指定的,而静态变量和静态方法不需要使用对象来调用。对象都没有创建,如何确定这个泛型参数是何种类型,所以当然是错误的。

public class Test2<T> { public static <T> T show(T one){ //这是正确的     return null; }    }

因为这是泛型方法

枚举 enum

枚举基本特性

本质是静态常量

public class SeasonConstant {    public static final int SPRING = 1;    public static final int SUMMER = 2;    public static final int AUTUMN = 3;    public static final int WINTER = 4;}
public enum SeasonEnum {    SPRING,SUMMER,AUTUMN,WINTER;}
values() 静态的自动生成的 可以遍历enum实例,其返回enum实例的数组
ordinal() 父类的实例方法 返回每个实例在声明时的次序
name() 父类的实例方法 返回enum实例声明时的名称
getDeclaringClass() 返回其所属的enum类
valueOf() 静态的自动生成的 根据给定的名称返回相应的enum实例
package demo;public class Test1 {    public static void main(String[] args) { SeasonEnum[] values = SeasonEnum.values(); for (int i = 0; i < values.length; i++) {     System.out.println(values[i].name());     System.out.println(values[i].ordinal());     System.out.println(values[i].getDeclaringClass());     System.out.println("----------------"); }    }}

Enum中添加新方法

public enum SeasonEnum {    SPRING("春天","春暖花开的季节"),    SUMMER("夏天","热的要命,但是小姐姐都穿短裤"),    AUTUMN("秋天","果实成熟的季节"),    WINTER("冬天","冷啊,可以吃火锅");    private String name;    private String detail;    SeasonEnum() {    }    SeasonEnum(String name, String detail) { this.name = name; this.detail = detail;    }    public String getName() { return name;    }    public void setName(String name) { this.name = name;    }    public String getDetail() { return detail;    }    public void setDetail(String detail) { this.detail = detail;    }}

Switch语句中的Enum

public static void main(String[] args) {    SeasonEnum season = SeasonEnum.SPRING;    switch (season){ case SPRING:     System.out.println("春天来了,又到了万物交配的季节!"); case SUMMER:     System.out.println("夏天来了,又可以穿大裤衩了!"); case AUTUMN:     System.out.println("秋天来了,又到了收获的季节!"); case WINTER:     System.out.println("冬天来了,又到了吃火锅的季节了!"); default:     System.out.println("也没有别的季节了。");    }}
  • 常规情况下必须使用 enum 类型来修饰 enum 实例,但在 case 语句中不必如此,
  • 意思就是 case SPRING: 不需要写成 case SeasonEnum.SPRING:

枚举的优势

阿里《Java开发手册》对枚举的相关规定如下:

【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。

【参考】枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。

  • int 类型本身并不具备安全性,假如某个程序员在定义 int 时少些了一个 final 关键字,那么就会存在被其他人修改的风险,而反观枚举类,它“天然”就是一个常量类,不存在被修改的风险
  • 使用 int 类型的语义不够明确,比如我们在控制台打印时如果只输出 1…2…3 这样的数字,我们肯定不知道它代表的是什么含义
  • 对程序修改常量时,只需要对枚举修改,不用对所有常量进行修改